forked from mirrors/0ad
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af4896b4c5 | |||
| 84c2dc3f15 | |||
| 54b832b6a6 | |||
| 26bfd92dbd | |||
| 52baaa4bbd | |||
| 83bb6f3ed5 | |||
| 2cf908a974 | |||
| 6400a4a0c5 | |||
| 8f5b5670ff |
@@ -144,7 +144,7 @@ function initGUIFilters()
|
||||
function initGUIButtons(data)
|
||||
{
|
||||
// Either get back to the previous page or quit if there is no previous page
|
||||
let hasPreviousPage = !data || data.cancelbutton;
|
||||
let hasPreviousPage = !data || data.cancelbutton || false;
|
||||
Engine.GetGUIObjectByName("cancelButton").hidden = !hasPreviousPage;
|
||||
Engine.GetGUIObjectByName("quitButton").hidden = hasPreviousPage;
|
||||
// Turn 'save' off, it will be enabled on any change.
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
<animation file="other/fish_generic_idle_b.dae" name="Idle" speed="50"/>
|
||||
<animation file="other/fish_generic_idle_c.dae" name="Idle" speed="35"/>
|
||||
</animations>
|
||||
<props>
|
||||
<prop actor="fauna/seagull_circle.xml" attachpoint="root"/>
|
||||
</props>
|
||||
<mesh>skeletal/fish_generic.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="100" name="generic texture">
|
||||
<textures><texture file="skeletal/animal_fish_generic.png" name="baseTex"/></textures>
|
||||
<textures>
|
||||
<texture file="skeletal/animal_fish_generic.png" name="baseTex"/>
|
||||
</textures>
|
||||
</variant>
|
||||
</group>
|
||||
<material>basic_spec.xml</material>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<castshadow/>
|
||||
<float/>
|
||||
<group>
|
||||
<variant name="Seagull" frequency="1">
|
||||
<animations>
|
||||
<animation file="other/seagull_flight.dae" name="Idle" speed="150"/>
|
||||
</animations>
|
||||
<textures>
|
||||
<texture file="skeletal/animal_seagull.png" name="baseTex"/>
|
||||
</textures>
|
||||
<mesh>skeletal/seagull.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<material>default.xml</material>
|
||||
</actor>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<castshadow/>
|
||||
<float/>
|
||||
<group>
|
||||
<variant frequency="100" name="fish mesh">
|
||||
<animations>
|
||||
<animation file="others/bird_circle_idle_01.dae" name="Idle" speed="100"/>
|
||||
</animations>
|
||||
<mesh>skeletal/bird_circle.dae</mesh>
|
||||
<textures>
|
||||
<texture file="null_white.dds" name="baseTex"/>
|
||||
</textures>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="100" name="Variant A">
|
||||
<props>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_01"/>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_09"/>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_19"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant frequency="100" name="Variant B">
|
||||
<props>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_02"/>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_10"/>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_20"/>
|
||||
</props>
|
||||
</variant>
|
||||
<variant frequency="100" name="Variant C">
|
||||
<props>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_05"/>
|
||||
<prop actor="fauna/seagull.xml" attachpoint="fish_20"/>
|
||||
</props>
|
||||
</variant>
|
||||
</group>
|
||||
<material>default.xml</material>
|
||||
</actor>
|
||||
@@ -28,11 +28,8 @@
|
||||
<prop actor="fauna/tuna.xml" attachpoint="fish_18"/>
|
||||
<prop actor="fauna/tuna.xml" attachpoint="fish_19"/>
|
||||
<prop actor="fauna/tuna.xml" attachpoint="fish_20"/>
|
||||
<prop actor="fauna/seagull_circle.xml" attachpoint="root"/>
|
||||
</props>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="100" name="generic texture">
|
||||
<textures>
|
||||
<texture file="null_white.dds" name="baseTex"/>
|
||||
</textures>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<group>
|
||||
<variant frequency="1" name="massive">
|
||||
<variant frequency="1" name="Savanna Field Tall">
|
||||
<mesh>gaia/grass_large_2_tall.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="texture">
|
||||
<textures>
|
||||
<texture file="gaia/grass_savanna_a.png" name="baseTex"/>
|
||||
</textures>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<group>
|
||||
<variant frequency="1" name="massive">
|
||||
<mesh>gaia/grass_steppe.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="texture">
|
||||
<variant frequency="1" name="Steppe Field Tall">
|
||||
<mesh>gaia/grass_large_2_tall.dae</mesh>
|
||||
<textures>
|
||||
<texture file="gaia/grass_steppe.png" name="baseTex"/>
|
||||
</textures>
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<group>
|
||||
<variant frequency="1" name="large">
|
||||
<variant frequency="1" name="Tropic Field">
|
||||
<mesh>gaia/grass_large_1.dae</mesh>
|
||||
</variant>
|
||||
<variant frequency="1" name="massive">
|
||||
<mesh>gaia/grass_large_2.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="taxture">
|
||||
<textures><texture file="gaia/grass_tropic_a.png" name="baseTex"/></textures>
|
||||
<textures>
|
||||
<texture file="gaia/grass_tropic_a.png" name="baseTex"/>
|
||||
</textures>
|
||||
</variant>
|
||||
</group>
|
||||
<material>basic_trans_wind.xml</material>
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<actor version="1">
|
||||
<group>
|
||||
<variant frequency="1" name="massive">
|
||||
<variant frequency="1" name="Tropic Field Tall">
|
||||
<mesh>gaia/grass_large_2_tall.dae</mesh>
|
||||
</variant>
|
||||
</group>
|
||||
<group>
|
||||
<variant frequency="1" name="texture">
|
||||
<textures>
|
||||
<texture file="gaia/grass_tropic_a.png" name="baseTex"/>
|
||||
</textures>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,7 +2,7 @@ GameSettings.prototype.Attributes.MatchID = class MatchID extends GameSetting
|
||||
{
|
||||
init()
|
||||
{
|
||||
this.matchID = Engine.GetMatchID();
|
||||
this.matchID = 0;
|
||||
}
|
||||
|
||||
toInitAttributes(attribs)
|
||||
@@ -15,4 +15,9 @@ GameSettings.prototype.Attributes.MatchID = class MatchID extends GameSetting
|
||||
if (attribs.matchID !== undefined)
|
||||
this.matchID = attribs.matchID;
|
||||
}
|
||||
|
||||
pickRandomItems()
|
||||
{
|
||||
this.matchID = Engine.GetMatchID();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ class LobbyGameRegistrationController
|
||||
{
|
||||
let pData = { "Name": g_PlayerAssignments[guid].name };
|
||||
|
||||
if (g_PlayerAssignments[guid].player <= g_GameSettings.playerCount.nbPlayers)
|
||||
if (g_PlayerAssignments[guid].player != -1)
|
||||
++connectedPlayers;
|
||||
else
|
||||
pData.Team = "observer";
|
||||
|
||||
@@ -193,6 +193,24 @@ Status DeleteDirectory(const OsPath& path)
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
Status RenameFile(const OsPath& path, const OsPath& newPath)
|
||||
{
|
||||
if (path.empty())
|
||||
return INFO::OK;
|
||||
|
||||
try
|
||||
{
|
||||
fs::rename(path.string8(), newPath.string8());
|
||||
}
|
||||
catch (fs::filesystem_error& err)
|
||||
{
|
||||
debug_printf("RenameFile: failed to rename %s to %s.\n%s\n", path.string8().c_str(), path.string8().c_str(), err.what());
|
||||
return ERR::EXCEPTION;
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
|
||||
}
|
||||
|
||||
Status CopyFile(const OsPath& path, const OsPath& newPath, bool override_if_exists/* = false*/)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@@ -88,4 +88,6 @@ LIB_API Status DeleteDirectory(const OsPath& dirPath);
|
||||
|
||||
LIB_API Status CopyFile(const OsPath& path, const OsPath& newPath, bool override_if_exists = false);
|
||||
|
||||
LIB_API Status RenameFile(const OsPath& path, const OsPath& newPath);
|
||||
|
||||
#endif // #ifndef INCLUDED_FILE_SYSTEM
|
||||
|
||||
+11
-1
@@ -79,6 +79,7 @@ that of Atlas depending on commandline parameters.
|
||||
#include "rlinterface/RLInterface.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
#include "scriptinterface/ScriptEngine.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/JSON.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/system/TurnManager.h"
|
||||
@@ -192,6 +193,8 @@ static InReaction MainInputHandler(const SDL_Event_* ev)
|
||||
else
|
||||
{
|
||||
LOGMESSAGE("Installed mod %s", installer.GetInstalledMods().front());
|
||||
ScriptInterface modInterface("Engine", "Mod", g_ScriptContext);
|
||||
g_Mods.UpdateAvailableMods(modInterface);
|
||||
RestartEngine();
|
||||
}
|
||||
break;
|
||||
@@ -662,9 +665,16 @@ static void RunGameOrAtlas(int argc, const char* argv[])
|
||||
|
||||
// Install the mods without deleting the pyromod files
|
||||
for (const OsPath& modPath : modsToInstall)
|
||||
installer.Install(modPath, g_ScriptContext, true);
|
||||
{
|
||||
CModInstaller::ModInstallationResult result = installer.Install(modPath, g_ScriptContext, true);
|
||||
if (result != CModInstaller::ModInstallationResult::SUCCESS)
|
||||
LOGERROR("Failed to install '%s'", modPath.string8().c_str());
|
||||
}
|
||||
|
||||
installedMods = installer.GetInstalledMods();
|
||||
|
||||
ScriptInterface modInterface("Engine", "Mod", g_ScriptContext);
|
||||
g_Mods.UpdateAvailableMods(modInterface);
|
||||
}
|
||||
|
||||
if (isNonVisual)
|
||||
|
||||
@@ -866,6 +866,7 @@ bool Init(const CmdLineArgs& args, int flags)
|
||||
if (flags & INIT_MODS)
|
||||
{
|
||||
ScriptInterface modInterface("Engine", "Mod", g_ScriptContext);
|
||||
g_Mods.UpdateAvailableMods(modInterface);
|
||||
std::vector<CStr> mods;
|
||||
if (args.Has("mod"))
|
||||
mods = args.GetMultiple("mod");
|
||||
@@ -876,7 +877,7 @@ bool Init(const CmdLineArgs& args, int flags)
|
||||
boost::split(mods, modsStr, boost::algorithm::is_space(), boost::token_compress_on);
|
||||
}
|
||||
|
||||
if (!g_Mods.EnableMods(modInterface, mods, flags & INIT_MODS_PUBLIC))
|
||||
if (!g_Mods.EnableMods(mods, flags & INIT_MODS_PUBLIC))
|
||||
{
|
||||
// In non-visual mode, fail entirely.
|
||||
if (args.Has("autostart-nonvisual"))
|
||||
|
||||
+2
-3
@@ -136,7 +136,7 @@ const std::vector<Mod::ModData>& Mod::GetAvailableMods() const
|
||||
return m_AvailableMods;
|
||||
}
|
||||
|
||||
bool Mod::EnableMods(const ScriptInterface& scriptInterface, const std::vector<CStr>& mods, const bool addPublic)
|
||||
bool Mod::EnableMods(const std::vector<CStr>& mods, const bool addPublic)
|
||||
{
|
||||
m_IncompatibleMods.clear();
|
||||
m_EnabledMods.clear();
|
||||
@@ -156,8 +156,6 @@ bool Mod::EnableMods(const ScriptInterface& scriptInterface, const std::vector<C
|
||||
if (counts["mod"] == 0)
|
||||
m_EnabledMods.insert(m_EnabledMods.begin(), "mod");
|
||||
|
||||
UpdateAvailableMods(scriptInterface);
|
||||
|
||||
m_IncompatibleMods = CheckForIncompatibleMods(m_EnabledMods);
|
||||
|
||||
for (const CStr& mod : m_IncompatibleMods)
|
||||
@@ -233,6 +231,7 @@ void Mod::UpdateAvailableMods(const ScriptInterface& scriptInterface)
|
||||
{
|
||||
PROFILE2("UpdateAvailableMods");
|
||||
|
||||
m_AvailableMods.clear();
|
||||
const Paths paths(g_CmdLineArgs);
|
||||
|
||||
// loop over all possible paths
|
||||
|
||||
+11
-10
@@ -56,13 +56,23 @@ public:
|
||||
const std::vector<CStr>& GetIncompatibleMods() const;
|
||||
const std::vector<ModData>& GetAvailableMods() const;
|
||||
|
||||
/**
|
||||
* Fetches available mods and stores some metadata about them.
|
||||
* This may open the zipped mod archives, depending on the situation,
|
||||
* and/or try to write files to the user mod folder,
|
||||
* which can be quite slow, so should be run rarely.
|
||||
* TODO: if this did not need the scriptInterface to parse JSON,
|
||||
* we could run it in different contexts and possibly cleaner.
|
||||
*/
|
||||
void UpdateAvailableMods(const ScriptInterface& scriptInterface);
|
||||
|
||||
/**
|
||||
* Enables specified mods (& mods required by the engine).
|
||||
* @param addPublic - if true, enable the public mod.
|
||||
* @return whether the mods were enabled successfully. This can fail if e.g. mods are incompatible.
|
||||
* If true, GetEnabledMods() should be non-empty, GetIncompatibleMods() empty. Otherwise, GetIncompatibleMods() is non-empty.
|
||||
*/
|
||||
bool EnableMods(const ScriptInterface& scriptInterface, const std::vector<CStr>& mods, const bool addPublic);
|
||||
bool EnableMods(const std::vector<CStr>& mods, const bool addPublic);
|
||||
|
||||
/**
|
||||
* Get data for the given mod.
|
||||
@@ -83,15 +93,6 @@ public:
|
||||
*/
|
||||
static bool AreModsPlayCompatible(const std::vector<const Mod::ModData*>& modsA, const std::vector<const Mod::ModData*>& modsB);
|
||||
private:
|
||||
/**
|
||||
* Fetches available mods and stores some metadata about them.
|
||||
* This may open the zipped mod archives, depending on the situation,
|
||||
* and/or try to write files to the user mod folder,
|
||||
* which can be quite slow, so should be run rarely.
|
||||
* TODO: if this did not need the scriptInterface to parse JSON,
|
||||
* we could run it in different contexts and possibly cleaner.
|
||||
*/
|
||||
void UpdateAvailableMods(const ScriptInterface& scriptInterface);
|
||||
|
||||
/**
|
||||
* Checks a list of @a mods and returns the incompatible mods, if any.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "ModInstaller.h"
|
||||
|
||||
#include "lib/file/vfs/vfs_util.h"
|
||||
#include "lib/file/file_system.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Filesystem.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
@@ -49,9 +51,18 @@ CModInstaller::ModInstallationResult CModInstaller::Install(
|
||||
CreateDirectories(modTemp.Parent(), 0700);
|
||||
|
||||
if (keepFile)
|
||||
CopyFile(mod, modTemp, true);
|
||||
else
|
||||
wrename(mod, modTemp);
|
||||
{
|
||||
if (CopyFile(mod, modTemp, true) != INFO::OK)
|
||||
{
|
||||
LOGERROR("Failed to copy '%s' to '%s'", mod.string8().c_str(), modTemp.string8().c_str());
|
||||
return FAIL_ON_MOD_COPY;
|
||||
}
|
||||
}
|
||||
else if (RenameFile(mod, modTemp) != INFO::OK)
|
||||
{
|
||||
LOGERROR("Failed to rename '%s' into '%s'", mod.string8().c_str(), modTemp.string8().c_str());
|
||||
return FAIL_ON_MOD_MOVE;
|
||||
}
|
||||
|
||||
// Load the mod to VFS
|
||||
if (m_VFS->Mount(m_CacheDir, m_TempDir / "") != INFO::OK)
|
||||
@@ -88,8 +99,12 @@ CModInstaller::ModInstallationResult CModInstaller::Install(
|
||||
// mod-name.zip
|
||||
// mod.json
|
||||
CreateDirectories(modDir, 0700);
|
||||
if (wrename(modTemp, modPath) != 0)
|
||||
if (RenameFile(modTemp, modPath) != INFO::OK)
|
||||
{
|
||||
LOGERROR("Failed to rename '%s' into '%s'", modTemp.string8().c_str(), modPath.string8().c_str());
|
||||
return FAIL_ON_MOD_MOVE;
|
||||
}
|
||||
|
||||
DeleteDirectory(modTemp.Parent());
|
||||
|
||||
std::ofstream mod_json((modDir / "mod.json").string8());
|
||||
|
||||
@@ -39,7 +39,8 @@ public:
|
||||
FAIL_ON_PARSE_JSON,
|
||||
FAIL_ON_EXTRACT_NAME,
|
||||
FAIL_ON_MOD_MOVE,
|
||||
FAIL_ON_JSON_WRITE
|
||||
FAIL_ON_JSON_WRITE,
|
||||
FAIL_ON_MOD_COPY
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+4
-1
@@ -485,7 +485,10 @@ bool ModIo::AdvanceRequest(const ScriptInterface& scriptInterface)
|
||||
{
|
||||
Paths paths(g_CmdLineArgs);
|
||||
CModInstaller installer(paths.UserData() / "mods", paths.Cache());
|
||||
installer.Install(m_DownloadFilePath, g_ScriptContext, false);
|
||||
CModInstaller::ModInstallationResult result = installer.Install(m_DownloadFilePath, g_ScriptContext, false);
|
||||
if (result != CModInstaller::ModInstallationResult::SUCCESS)
|
||||
LOGERROR("Failed to install '%s'", m_DownloadFilePath.string8().c_str());
|
||||
g_Mods.UpdateAvailableMods(scriptInterface);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -233,7 +233,8 @@ void CReplayPlayer::Replay(const bool serializationtest, const int rejointesttur
|
||||
mods.emplace_back(data.m_Pathname);
|
||||
|
||||
// Ignore the return value, we check below.
|
||||
g_Mods.EnableMods(scriptInterface, mods, false);
|
||||
g_Mods.UpdateAvailableMods(scriptInterface);
|
||||
g_Mods.EnableMods(mods, false);
|
||||
CheckReplayMods(replayMods);
|
||||
|
||||
MountMods(Paths(g_CmdLineArgs), g_Mods.GetEnabledMods());
|
||||
|
||||
@@ -156,9 +156,9 @@ bool AreModsPlayCompatible(const std::vector<Mod::ModData>& a, const std::vector
|
||||
return Mod::AreModsPlayCompatible(modsA, modsB);
|
||||
}
|
||||
|
||||
bool SetModsAndRestartEngine(const ScriptInterface& scriptInterface, const std::vector<CStr>& mods)
|
||||
bool SetModsAndRestartEngine(const std::vector<CStr>& mods)
|
||||
{
|
||||
if (!g_Mods.EnableMods(scriptInterface, mods, false))
|
||||
if (!g_Mods.EnableMods(mods, false))
|
||||
return false;
|
||||
|
||||
RestartEngine();
|
||||
|
||||
Reference in New Issue
Block a user