18 #include "precompiled.h" 
   47 #define getpid _getpid // use the non-deprecated function name 
   50 static std::string 
Hexify(
const std::string& s) 
 
   52     std::stringstream str;
 
   54     for (
size_t i = 0; i < s.size(); ++i)
 
   55         str << std::setfill(
'0') << std::setw(2) << (int)(
unsigned char)s[i];
 
   85     void ResetState(
bool skipScriptedComponents, 
bool skipAI)
 
  118         if (!skipScriptedComponents)
 
  122 #define LOAD_SCRIPTED_COMPONENT(name) \ 
  123             cid = componentManager.LookupCID(name); \ 
  124             if (cid == CID__Invalid) \ 
  125                 LOGERROR(L"Can't find component type " L##name); \ 
  126             componentManager.AddComponent(systemEntity, cid, noParam) 
  136 #undef LOAD_SCRIPTED_COMPONENT 
  156     void Update(
int turnLength, 
const std::vector<SimulationCommand>& commands);
 
  158     void Interpolate(
float simFrameLength, 
float frameOffset, 
float realFrameLength);
 
  196         const std::vector<SimulationCommand>& commands)
 
  198         std::vector<SimulationCommand> newCommands = commands;
 
  199         for (
size_t i = 0; i < newCommands.size(); ++i)
 
  211         LoadScripts(componentManager, loadedScripts, L
"simulation/components/interfaces/") &&
 
  212         LoadScripts(componentManager, loadedScripts, L
"simulation/helpers/") &&
 
  213         LoadScripts(componentManager, loadedScripts, L
"simulation/components/")
 
  224     for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
 
  228             loadedScripts->insert(filename);
 
  259     const double end_time = 
timer_Time() + 200e-3;
 
  265         bool progressed = 
false;
 
  273         if (!progressed || total == 0)
 
  276         ret = 
Clamp(100*progress / total, 1, 100);
 
  285     if (!state.
hash.empty())
 
  291     if (!state.
debug.str().empty())
 
  294         file << state.
debug.str();
 
  297     if (!state.
state.str().empty())
 
  299         std::ofstream file (
OsString(path / (L
"state." + suffix)).c_str(), 
std::ofstream::out | std::ofstream::trunc | std::ofstream::binary);
 
  300         file << state.
state.str();
 
  312     wunlink(path / 
"hash.before.a");
 
  313     wunlink(path / 
"hash.before.b");
 
  314     wunlink(path / 
"debug.before.a");
 
  315     wunlink(path / 
"debug.before.b");
 
  316     wunlink(path / 
"state.before.a");
 
  317     wunlink(path / 
"state.before.b");
 
  318     wunlink(path / 
"hash.after.a");
 
  319     wunlink(path / 
"hash.after.b");
 
  320     wunlink(path / 
"debug.after.a");
 
  321     wunlink(path / 
"debug.after.b");
 
  322     wunlink(path / 
"state.after.a");
 
  323     wunlink(path / 
"state.after.b");
 
  325     if (primaryStateBefore)
 
  327     if (primaryStateAfter)
 
  329     if (secondaryStateBefore)
 
  331     if (secondaryStateAfter)
 
  354     const bool serializationTestDebugDump = 
false; 
 
  355     const bool serializationTestHash = 
true; 
 
  361         if (serializationTestDebugDump)
 
  363         if (serializationTestHash)
 
  376         secondaryContext.
m_Terrain = &secondaryTerrain;
 
  390         if (mapType == 
"random")
 
  393             debug_warn(L
"Serialization test mode only supports scenarios");
 
  397             std::wstring mapFile;
 
  411         if (serializationTestDebugDump)
 
  413         if (serializationTestHash)
 
  416         if (primaryStateBefore.
state.str() != secondaryStateBefore.state.str() ||
 
  417             primaryStateBefore.
hash != secondaryStateBefore.hash)
 
  424         if (serializationTestHash)
 
  432         if (serializationTestHash)
 
  435         if (primaryStateAfter.
state.str() != secondaryStateAfter.
state.str() ||
 
  436             primaryStateAfter.
hash != secondaryStateAfter.
hash)
 
  452     if (m_TurnNumber % 10 == 0)
 
  541     std::stringstream pid;
 
  543     std::stringstream name;\
 
  544     name << std::setw(5) << std::setfill(
'0') << 
m_TurnNumber << 
".txt";
 
  549     file << 
"State hash: " << std::hex;
 
  552     for (
size_t i = 0; i < hashRaw.size(); ++i)
 
  553         file << std::setfill(
'0') << std::setw(2) << (int)(
unsigned char)hashRaw[i];
 
  554     file << std::dec << 
"\n";
 
  660     std::vector<SimulationCommand> commands;
 
  661     m->
Update(turnLength, commands);
 
  666     m->
Update(turnLength, commands);
 
  671     m->
Interpolate(simFrameLength, frameOffset, realFrameLength);
 
  797     std::vector<std::string> data;
 
  803         for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
 
  833     std::vector<std::string> data;
 
  839         for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
 
  866     return ReadJSON(L
"simulation/data/player_defaults.json");
 
  871     return ReadJSON(L
"simulation/data/map_sizes.json");
 
  907     if (!scriptInterface.
Eval(
"({})", ais) || !scriptInterface.
SetProperty(ais.
get(), 
"AIData", aiData))
 
  908         return std::string();
 
An entity initialisation parameter node. 
A simple fixed-point number class. 
virtual void FlushTurn(const std::vector< SimulationCommand > &commands)=0
Calls the ProcessCommand(player, cmd) global script function for each command in the local queue and ...
CStr DecodeUTF8() const 
Returns contents of a UTF-8 encoded file as a string with optional BOM removed. 
CSimulation2(CUnitManager *, CTerrain *)
void FlushDestroyedComponents()
Does the actual destruction of components from DestroyComponentsSoon. 
static Status ReloadChangedFileCB(void *param, const VfsPath &path)
void ResetState()
Resets the dynamic simulation state (deletes all entities, resets entity ID counters; doesn't unload/...
void Interpolate(float simFrameLength, float frameOffset, float realFrameLength)
Generic per-turn update message, for things that don't care much about ordering. 
std::string ReadJSON(VfsPath path)
const CSimContext & GetSimContext() const 
Path VfsPath
VFS path of the form "(dir/)*file?". 
static std::string Hexify(const std::string &s)
static std::vector< CScriptValRooted > GetAIs(ScriptInterface &scriptInterface)
Returns a vector of {"id":"value-for-AddPlayer", "name":"Human readable name"} objects, based on all the available AI scripts. 
entity_id_t AddEntity(const std::wstring &templateName, entity_id_t ent)
Constructs an entity based on the given template, and adds it the world with entity ID ent...
void SetInitAttributes(const CScriptValRooted &settings)
Set the attributes identifying the scenario/RMS used to initialise this simulation. 
IComponent * QueryInterface(entity_id_t ent, int iid) const 
virtual void ProcessSameTurnMoves()=0
Process moves during the same turn they were created in to improve responsiveness. 
const OsPath & psLogDir()
Status LDR_NonprogressiveLoad()
const PSRETURN PSRETURN_OK
Reads a file, then gives read-only access to the contents. 
virtual void FinishAsyncRequests()=0
Finish computing asynchronous path requests and send the CMessagePathResult messages. 
bool DeserializeState(std::istream &stream)
IComponent * QueryInterface(entity_id_t ent, InterfaceId iid) const 
Add renderable objects to the scene collector. 
#define CFG_GET_VAL(name, type, destination)
entity_id_t AddLocalEntity(const std::wstring &templateName)
static void out(const wchar_t *fmt,...)
bool CallFunctionVoid(jsval val, const char *name)
Call the named property on the given object, with void return type and 0 arguments. 
Object wrapping an entity_id_t, with a SEntityComponentCache to support fast QueryInterface() / CmpPt...
void Interpolate(float simFrameLength, float frameOffset, float realFrameLength)
std::string m_StartupScript
void Update(int turnLength, const std::vector< SimulationCommand > &commands)
void ResetState(bool skipScriptedComponents=false, bool skipAI=false)
Initialise (or re-initialise) the complete simulation state. 
bool m_EnableSerializationTest
ScriptInterface & GetScriptInterface()
A trivial wrapper around a jsval. 
std::string GenerateSchema()
Update phase for non-formation-controller unit movement. 
void RenderSubmit(SceneCollector &collector, const CFrustum &frustum, bool culling)
bool LoadScript(const VfsPath &filename, const std::string &code)
Load and execute the given script in a new function scope. 
T Clamp(T val, T min, T max)
low-level aka "lib" 
std::string StringifyJSON(jsval obj, bool indent=true)
Stringify to a JSON string, UTF-8 encoded. 
const InterfaceListUnordered & GetEntitiesWithInterfaceUnordered(int iid)
Returns a list of components implementing the given interface, and their associated entities...
Contains pointers to various 'global' objects that are needed by the simulation code, to allow easy access without using real (evil) global variables. 
bool SerializeState(std::ostream &stream)
void LoadComponentTypes()
CScriptValRooted ParseJSON(const std::string &string_utf8)
Parse a UTF-8-encoded JSON string. 
std::vector< std::string > GetRMSData()
Get random map script data. 
bool LoadDefaultScripts()
Call LoadScripts for each of the game's standard simulation script paths. 
std::string GetMapSettingsString()
Get the current map settings as a UTF-8 JSON string. 
void Update(int turnLength)
float GetLastFrameOffset() const 
Returns the last frame offset passed to Interpolate(), i.e. 
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton 'system' components. 
Status ReloadChangedFile(const VfsPath &path)
Reload any scripts that were loaded from the given filename. 
void InitGame(const CScriptVal &data)
Initialise a new game, based on some script data. 
This interface accepts renderable objects. 
void SetMapSettings(const std::string &settings)
Set the initial map settings (as a UTF-8-encoded JSON string), which will be used to set up the simul...
std::vector< std::pair< entity_id_t, IComponent * > > InterfaceList
const InterfaceListUnordered & GetEntitiesWithInterfaceUnordered(InterfaceId iid) const 
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero. 
std::set< VfsPath > m_LoadedScripts
InterfaceList GetEntitiesWithInterface(InterfaceId iid) const 
Final update phase, after all other updates. 
#define LOAD_SCRIPTED_COMPONENT(name)
static bool LoadScripts(CComponentManager &componentManager, std::set< VfsPath > *loadedScripts, const VfsPath &path)
void UnregisterFileReloadFunc(FileReloadFunc func, void *obj)
delete a callback function registered with RegisterFileReloadFunc (removes any with the same func and...
void BroadcastMessage(const CMessage &msg) const 
LIB_API int wunlink(const OsPath &pathname)
void RegisterFileReloadFunc(FileReloadFunc func, void *obj)
register a callback function to be called by ReloadChangedFiles 
virtual void PushCommands()=0
Call this at the start of a turn, to push the computed AI commands into the command queue...
const String & string() const 
bool ComputeStateHash(std::string &outHash, bool quick)
std::string GetPlayerDefaults()
Get player default data. 
ScriptInterface & GetScriptInterface() const 
bool Eval(const char *code)
bool LoadScripts(const VfsPath &path)
Load all scripts in the specified directory (non-recursively), so they can register new component typ...
void LoadMap(const VfsPath &pathname, const CScriptValRooted &settings, CTerrain *, WaterManager *, SkyManager *, CLightEnv *, CGameView *, CCinemaManager *, CTriggerManager *, CPostprocManager *pPostproc, CSimulation2 *, const CSimContext *, int playerID, bool skipEntities)
bool ComputeStateHash(std::string &outHash, bool quick)
i64 Status
Error handling system. 
static bool IsInitialised()
void InitSystemEntity()
Set up an empty SYSTEM_ENTITY. 
std::string GetAIData()
Get AI data. 
entity_id_t AllocateNewLocalEntity()
Returns a new local entity ID that has never been used before. 
A simplified syntax for accessing entity components. 
bool SerializeState(std::ostream &stream)
bool DeserializeState(std::istream &stream)
jsval CloneValueFromOtherContext(ScriptInterface &otherContext, jsval val)
Construct a new value (usable in this ScriptInterface's context) by cloning a value from a different ...
void ReportSerializationFailure(SerializationTestState *primaryStateBefore, SerializationTestState *primaryStateAfter, SerializationTestState *secondaryStateBefore, SerializationTestState *secondaryStateAfter)
const char * GetErrorString(PSRETURN code)
bool GetProperty(jsval obj, const char *name, T &out)
Get the named property on the given object. 
virtual void StartComputation()=0
Call this at the end of a turn, to trigger AI computation which will be ready for the next turn...
static CFixed FromInt(int n)
CComponentManager m_ComponentManager
Status ReloadChangedFile(const VfsPath &path)
#define PROFILE2_ATTR
Associates a string (with printf-style formatting) with the current region or event. 
void PostMessage(entity_id_t ent, const CMessage &msg) const 
Send a message, targeted at a particular entity. 
void LoadMapSettings()
Loads the map settings script (called after map is loaded) 
bool AddComponent(CEntityHandle ent, ComponentTypeId cid, const CParamNode ¶mNode)
Constructs a component of type 'cid', initialised with data 'paramNode', and attaches it to entity 'e...
bool DumpDebugState(std::ostream &stream, bool includeDebugInfo)
bool LoadScript(const VfsPath &filename, bool hotload=false)
Load a script and execute it in a new function scope. 
std::string GetMapSizes()
Get map sizes data. 
Path ChangeExtension(Path extension) const 
Handle progressive loading of resources. 
void ResetState(bool skipScriptedComponents, bool skipAI)
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Returns either PSRETURN_OK or PSRETURN_CVFSFile_LoadFailed. 
InterfaceList GetEntitiesWithInterface(int iid)
Returns a list of components implementing the given interface, and their associated entities...
wchar_t * StatusDescription(Status status, wchar_t *buf, size_t max_chars)
generate textual description of a Status. 
static std::vector< SimulationCommand > CloneCommandsFromOtherContext(ScriptInterface &oldScript, ScriptInterface &newScript, const std::vector< SimulationCommand > &commands)
void LDR_EndRegistering()
std::vector< std::string > GetCivData()
Get civilization data. 
void BroadcastMessage(const CMessage &msg) const 
Send a message, not targeted at any particular entity. 
CScriptVal GetMapSettings()
Get the current map settings. 
void FlushDestroyedEntities()
Does the actual destruction of entities from DestroyEntity. 
bool VfsFileExists(const VfsPath &pathname)
CScriptValRooted m_InitAttributes
entity_id_t AddEntity(const std::wstring &templateName)
Construct a new entity and add it to the world. 
boost::unordered_map< entity_id_t, IComponent * > InterfaceListUnordered
void DestroyEntity(entity_id_t ent)
Destroys the specified entity, once FlushDestroyedEntities is called. 
std::vector< VfsPath > VfsPaths
JSBool error(JSContext *cx, uintN argc, jsval *vp)
std::string GenerateSchema()
jsval get() const 
Returns the current value (or JSVAL_VOID if uninitialised). 
static void UpdateComponents(CSimContext &simContext, fixed turnLengthFixed, const std::vector< SimulationCommand > &commands)
CEntityHandle GetSystemEntity()
Returns a CEntityHandle with id SYSTEM_ENTITY. 
Abstraction around a SpiderMonkey JSContext. 
#define debug_warn(expr)
display the error dialog with the given text. 
void DestroyComponentsSoon(entity_id_t ent)
Destroys all the components belonging to the specified entity when FlushDestroyedComponents is called...
bool SetProperty(jsval obj, const char *name, const T &value, bool constant=false, bool enumerate=true)
Set the named property on the given object. 
int ProgressiveLoad()
RegMemFun incremental loader function. 
Prepare for rendering a new frame (set up model positions etc). 
CSimulation2Impl(CUnitManager *unitManager, CTerrain *terrain)
Status CreateDirectories(const OsPath &path, mode_t mode)
void SetStartupScript(const std::string &script)
Set a startup script, which will get executed before the first turn. 
u32 entity_id_t
Entity ID type. 
CUnitManager * m_UnitManager
const std::string & GetStartupScript()
Get the current startup script. 
static const player_id_t INVALID_PLAYER
void EnableSerializationTest()
static void ResetComponentState(CComponentManager &componentManager, bool skipScriptedComponents, bool skipAI)
CScriptValRooted GetInitAttributes()
Get the data passed to SetInitAttributes. 
Status GetPathnames(const PIVFS &fs, const VfsPath &path, const wchar_t *filter, VfsPaths &pathnames)
bool DumpDebugState(std::ostream &stream)
JSContext * GetContext() const 
void MaybeGC()
MaybeGC tries to determine whether garbage collection in cx's runtime would free up enough memory to ...
void DumpSerializationTestState(SerializationTestState &state, const OsPath &path, const OsPath::String &suffix)
void PostMessage(entity_id_t ent, const CMessage &msg) const 
static bool LoadDefaultScripts(CComponentManager &componentManager, std::set< VfsPath > *loadedScripts)
CComponentManager & GetComponentManager() const 
void LDR_BeginRegistering()
static std::string OsString(const OsPath &path)
void LoadPlayerSettings(bool newPlayers)
Loads the player settings script (called before map is loaded) 
entity_id_t AllocateNewEntity()
Returns a new entity ID that has never been used before. 
CScriptValRooted m_MapSettings