18 #include "precompiled.h"
81 const shared_ptr<ScriptRuntime>& runtime, boost::rand48&
rng) :
123 JS_GC(self->m_ScriptInterface.GetContext());
129 self->
m_Commands.push_back(self->m_ScriptInterface.WriteStructuredClone(cmd.
get()));
140 VfsPath filename = L
"screenshots/aidump/" + name;
142 if (data.size() != w*h)
144 debug_warn(L
"DumpImage: data size doesn't match w*h");
154 const size_t bpp = 8;
157 const size_t img_size = w * h * bpp/8;
162 if (
tex_wrap(w, h, bpp, flags, buf, hdr_size, &t) < 0)
165 u8* img = buf.get() + hdr_size;
166 for (
size_t i = 0; i < data.size(); ++i)
167 img[i] = (
u8)((data[i] * 255) / max);
180 std::wstringstream protoID;
181 protoID <<
self->
m_Player << L
"." << name.c_str();
182 self->m_Worker.RegisterSerializablePrototype(protoID.str(), proto);
197 for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
201 LOGERROR(L
"Failed to load script %ls", it->string().c_str());
218 LOGERROR(L
"Failed to create AI player: can't find %ls", path.
string().c_str());
223 std::string constructor;
226 LOGERROR(L
"Failed to create AI player: %ls: missing 'constructor'", path.
string().c_str());
235 LOGERROR(L
"Failed to create AI player: %ls: can't find constructor '%hs'", path.
string().c_str(), constructor.c_str());
265 LOGERROR(L
"Failed to create AI player: %ls: error calling constructor '%hs'", path.
string().c_str(), constructor.c_str());
299 std::vector<shared_ptr<ScriptInterface::StructuredClone> >
m_Commands;
307 std::vector<shared_ptr<ScriptInterface::StructuredClone> >
commands;
352 if (cbdata == NULL) {
353 debug_warn(L
"Warning: the shared component has tried to push an engine command. Ignoring.");
357 self->
m_Commands.push_back(self->m_ScriptInterface.WriteStructuredClone(cmd.
get()));
362 if (cbdata == NULL) {
363 debug_warn(L
"Warning: the shared component has asked for DumpHeap. Ignoring.");
371 if (cbdata == NULL) {
372 debug_warn(L
"Warning: the shared component has asked for ForceGC. Ignoring.");
377 JS_GC(self->m_ScriptInterface.GetContext());
386 VfsPath filename = L
"screenshots/aidump/" + name;
388 if (data.size() != w*h)
390 debug_warn(L
"DumpImage: data size doesn't match w*h");
400 const size_t bpp = 8;
403 const size_t img_size = w * h * bpp/8;
408 if (
tex_wrap(w, h, bpp, flags, buf, hdr_size, &t) < 0)
411 u8* img = buf.get() + hdr_size;
412 for (
size_t i = 0; i < data.size(); ++i)
413 img[i] = (
u8)((data[i] * 255) / max);
431 for (VfsPaths::iterator it = sharedPathnames.begin(); it != sharedPathnames.end(); ++it)
435 LOGERROR(L
"Failed to load shared script %ls", it->string().c_str());
444 OsPath path = L
"simulation/ai/common-api-v2/";
451 LOGERROR(L
"Failed to create shared AI component: %ls: can't find constructor '%hs'", path.
string().c_str(),
"SharedScript");
463 for (
size_t i = 0; i <
m_Players.size(); ++i)
486 for (
size_t i = 0; i <
m_Players.size(); ++i)
505 LOGERROR(L
"Failed to create shared AI component: %ls: error calling constructor '%hs'", path.
string().c_str(),
"SharedScript");
515 if (!ai->Initialise(callConstructor))
547 for (
size_t i = 0; i <
m_Players.size(); ++i)
570 if (territoryMapDirty)
596 for (
size_t i = 0; i <
m_Players.size(); ++i)
598 commands[i].player =
m_Players[i]->m_Player;
599 commands[i].commands =
m_Players[i]->m_Commands;
614 for (
size_t i = 0; i < templates.size(); ++i)
646 std::stringstream rngStream;
648 serializer.
StringASCII(
"rng", rngStream.str(), 0, 32);
659 LOGERROR(L
"AI shared script Serialize call failed");
660 serializer.
ScriptVal(
"sharedData", sharedData);
662 for (
size_t i = 0; i <
m_Players.size(); ++i)
669 for (
size_t j = 0; j <
m_Players[i]->m_Commands.size(); ++j)
676 if (hasCustomSerialize)
680 LOGERROR(L
"AI script Serialize call failed");
681 serializer.
ScriptVal(
"data", scriptData);
699 std::string rngString;
700 std::stringstream rngStream;
702 rngStream << rngString;
715 deserializer.
ScriptVal(
"sharedData", sharedData);
717 LOGERROR(L
"AI shared script Deserialize call failed");
720 for (
size_t i = 0; i < numAis; ++i)
725 deserializer.
String(
"name", name, 1, 256);
728 if (!
AddPlayer(name, player, difficulty,
true))
733 m_Players.back()->m_Commands.reserve(numCommands);
734 for (
size_t j = 0; j < numCommands; ++j)
748 if (hasCustomDeserialize)
751 deserializer.
ScriptVal(
"data", scriptData);
755 LOGERROR(L
"AI script Deserialize call failed");
759 LOGERROR(L
"AI script deserialize() call failed");
778 JSObject* obj = JSVAL_TO_OBJECT(proto.
get());
779 std::pair<std::map<JSObject*, std::wstring>::iterator,
bool> ret1 =
m_SerializablePrototypes.insert(std::make_pair(obj, name));
780 std::pair<std::map<std::wstring, JSObject*>::iterator,
bool> ret2 =
m_DeserializablePrototypes.insert(std::make_pair(name, obj));
781 if (!ret1.second || !ret2.second)
782 LOGERROR(L
"RegisterSerializablePrototype called with same prototype multiple times: p=%p n='%ls'", obj, name.c_str());
830 PROFILE3(
"AI run shared component");
834 for (
size_t i = 0; i <
m_Players.size(); ++i)
907 return "<a:component type='system'/><empty/>";
980 ENSURE(cmpTechTemplateManager);
1001 const Grid<u16>* passabilityMap = &dummyGrid;
1009 const Grid<u8>* territoryMap = &dummyGrid2;
1040 const Grid<u16>* passabilityMap = &dummyGrid;
1047 bool territoryMapDirty =
false;
1049 const Grid<u8>* territoryMap = &dummyGrid2;
1054 territoryMapDirty =
true;
1066 std::vector<CAIWorker::SCommandSets> commands;
1070 if (!cmpCommandQueue)
1073 for (
size_t i = 0; i < commands.size(); ++i)
1075 for (
size_t j = 0; j < commands[i].commands.size(); ++j)
1092 ENSURE(cmpTemplateManager);
1106 ENSURE(cmpTemplateManager);
1112 m_TemplateLoadedIdx++;
1137 scriptInterface.
Eval(
"({ pathfinderObstruction: 1, foundationObstruction: 2 })", classesVal);
1139 std::map<std::string, ICmpPathfinder::pass_class_t> classes = cmpPathfinder->
GetPassabilityClasses();
1140 for (std::map<std::string, ICmpPathfinder::pass_class_t>::iterator it = classes.begin(); it != classes.end(); ++it)
1141 scriptInterface.
SetProperty(classesVal.
get(), it->first.c_str(), it->second,
true);
1143 scriptInterface.
SetProperty(state.
get(),
"passabilityClasses", classesVal,
true);
void GetCommands(std::vector< SCommandSets > &commands)
An entity initialisation parameter node.
void SubscribeToMessageType(MessageTypeId mtid)
Subscribe the current component type to the given message type.
virtual void StringASCII(const char *name, std::string &out, uint32_t minlength, uint32_t maxlength)
virtual std::map< std::string, pass_class_t > GetPassabilityClasses()=0
Get the list of all known passability classes.
void Serialize(std::ostream &stream, bool isDebug)
bool Initialise(bool callConstructor)
bool ReplaceNondeterministicRNG(boost::rand48 &rng)
Replace the default JS random number geenrator with a seeded, network-sync'd one. ...
bool uninitialised() const
Returns whether the value is uninitialised.
Grid< u16 > m_PassabilityMap
virtual const Grid< u16 > & GetPassabilityGrid()=0
#define REGISTER_COMPONENT_TYPE(cname)
virtual void Bool(const char *name, bool &out)
Helper templates for serializing/deserializing common objects.
static void PostCommand(void *cbdata, CScriptValRooted cmd)
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
std::map< std::wstring, JSObject * > m_DeserializablePrototypes
static void ForceGC(void *cbdata)
virtual bool IsDebug() const
Returns true if the serializer is being used in debug mode.
bool HasProperty(jsval obj, const char *name)
Check the named property has been defined on the given object.
void SetCallbackData(void *cbdata)
virtual CScriptVal GetAllTechs()=0
Serialization interface; see serialization overview.
static const uintptr_t maxSectorSize
bool AddPlayer(const std::wstring &aiName, player_id_t player, uint8_t difficulty, bool callConstructor)
bool CallFunctionVoid(jsval val, const char *name)
Call the named property on the given object, with void return type and 0 arguments.
virtual void Serialize(ISerializer &serialize)
indicates the image is 8bpp greyscale.
CScriptValRooted m_SharedAIObj
static void PostCommand(void *cbdata, CScriptValRooted cmd)
void NumberU8_Unbounded(const char *name, uint8_t value)
Serialize a number.
static void IncludeModule(void *cbdata, std::wstring name)
const jsval & get() const
Returns the current value.
ScriptInterface m_ScriptInterface
void WaitToFinishComputation()
virtual void NumberU32_Unbounded(const char *name, uint32_t &out)
Serialize to a human-readable YAML-like format.
size_t tex_hdr_size(const VfsPath &filename)
return the minimum header size (i.e.
A trivial wrapper around a jsval.
virtual const Grid< u8 > & GetTerritoryGrid()=0
For each tile, the TERRITORY_PLAYER_MASK bits are player ID; TERRITORY_CONNECTED_MASK is set if the t...
void ScriptVal(const char *name, jsval value)
Serialize a jsval.
JSRuntime * GetRuntime() const
virtual bool NeedUpdate(size_t *dirtyID)=0
bool FreezeObject(jsval obj, bool deep)
std::set< std::wstring > m_LoadedModules
bool LoadGlobalScripts()
Load global scripts that most script contexts need, located in the /globalscripts directory...
virtual CScriptVal GetFullRepresentation()=0
Returns a script object that represents the current world state, to be passed to AI scripts...
void StartComputation(const shared_ptr< ScriptInterface::StructuredClone > &gameState, const Grid< u16 > &passabilityMap, const Grid< u8 > &territoryMap, bool territoryMapDirty)
virtual void NumberU8_Unbounded(const char *name, uint8_t &out)
virtual void ScriptVal(const char *name, jsval &out)
Deserialize a jsval, replacing 'out'.
virtual void AddPlayer(std::wstring id, player_id_t player, uint8_t difficulty)
Add a new AI player into the world, based on the AI script identified by id (corresponding to a subdi...
bool SetPropertyInt(jsval obj, int name, const T &value, bool constant=false, bool enumerate=true)
Set the integer-named property on the given object.
virtual void PushLocalCommand(player_id_t player, CScriptVal cmd)=0
Pushes a new command onto the local queue.
void Run(CScriptVal state)
flags & TEX_ORIENTATION is a field indicating orientation, i.e.
static void DumpImage(void *cbdata, std::wstring name, std::vector< u32 > data, u32 w, u32 h, u32 max)
Debug function for AI scripts to dump 2D array data (e.g.
int32_t player_id_t
valid player IDs are non-negative (see ICmpOwnership)
ScriptInterface m_ScriptInterface
void DumpHeap()
Dump some memory heap debugging information to stderr.
virtual void Init(const CParamNode ¶mNode)
jsval NewObjectFromConstructor(jsval ctor)
Create an object as with CallConstructor except don't actually execute the constructor function...
std::vector< std::pair< std::string, const CParamNode * > > m_Templates
void LoadPathfinderClasses(CScriptVal state)
ScriptInterface & GetScriptInterface() const
bool LoadScripts(const std::wstring &moduleName)
std::vector< std::string > m_TemplateNames
#define ENSURE(expr)
ensure the expression <expr> evaluates to non-zero.
virtual void SetLosRevealAll(player_id_t player, bool enabled)=0
Set whether the whole map should be made visible to the given player.
size_t m_TemplateLoadedIdx
virtual int GetType() const =0
static void DumpHeap(void *cbdata)
void StringASCII(const char *name, const std::string &value, uint32_t minlength, uint32_t maxlength)
Serialize an ASCII string.
Implementation of ICmpAIManager.
CScriptValRooted m_TerritoryMapVal
void LoadEntityTemplates(const std::vector< std::pair< std::string, const CParamNode * > > &templates)
void SerializeState(ISerializer &serializer)
virtual const CParamNode * GetTemplateWithoutValidation(std::string templateName)=0
Like GetTemplate, except without doing the XML validation (so it's faster but may return invalid temp...
boost::mt19937 rng
Random number generator (Boost Mersenne Twister)
shared_ptr< ScriptRuntime > m_ScriptRuntime
CScriptValRooted ReadJSONFile(const VfsPath &path)
Read a JSON file.
const String & string() const
bool LoadGlobalScriptFile(const VfsPath &path)
Load and execute the given script in the global scope.
std::map< VfsPath, CScriptValRooted > m_PlayerMetadata
virtual std::istream & GetStream()=0
Returns a stream which can be used to deserialize data directly.
static void ForceGC(void *cbdata)
std::vector< SCommandSets > m_Commands
virtual void TryLoadSharedComponent()
std::vector< shared_ptr< CAIPlayer > > m_Players
bool undefined() const
Returns whether the value is uninitialised or is JSVAL_VOID.
bool Eval(const char *code)
static jsval ToJSVal(JSContext *cx, T const &val)
Convert a C++ type to a jsval.
virtual void SetSerializablePrototypes(std::map< JSObject *, std::wstring > &prototypes)
void Bool(const char *name, bool value)
Serialize a boolean.
void Run(CScriptVal state, CScriptValRooted SharedAI)
static void DumpImage(void *cbdata, std::wstring name, std::vector< u32 > data, u32 w, u32 h, u32 max)
Debug function for AI scripts to dump 2D array data (e.g.
std::vector< shared_ptr< ScriptInterface::StructuredClone > > commands
virtual void Deserialize(const CParamNode ¶mNode, IDeserializer &deserialize)
#define DEFAULT_COMPONENT_ALLOCATOR(cname)
const CSimContext & GetSimContext() const
virtual void PushCommands()
Call this at the start of a turn, to push the computed AI commands into the command queue...
void RegisterTechTemplates(const shared_ptr< ScriptInterface::StructuredClone > &techTemplates)
size_t m_TerritoriesDirtyID
CScriptValRooted m_EntityTemplates
void NumberU32_Unbounded(const char *name, uint32_t value)
Serialize a number.
static void RegisterSerializablePrototype(void *cbdata, std::wstring name, CScriptVal proto)
stores all data describing an image.
Status tex_write(Tex *t, const VfsPath &filename)
CScriptValRooted m_PassabilityMapVal
CScriptValRooted m_TechTemplates
A simplified syntax for accessing entity components.
bool RunGamestateInit(const shared_ptr< ScriptInterface::StructuredClone > &gameState, const Grid< u16 > &passabilityMap, const Grid< u8 > &territoryMap)
virtual void HandleMessage(const CMessage &msg, bool global)
virtual std::vector< std::string > FindAllTemplates(bool includeActors)=0
Returns a list of strings that could be validly passed as templateName to LoadTemplate.
void String(const char *name, const std::wstring &value, uint32_t minlength, uint32_t maxlength)
Serialize a Unicode string.
void Deserialize(std::istream &stream)
bool GetProperty(jsval obj, const char *name, T &out)
Get the named property on the given object.
void ForceLoadEntityTemplates()
CScriptValRooted LoadMetadata(const VfsPath &path)
CEntityHandle GetSystemEntity() const
bool CallFunction(jsval val, const char *name, R &ret)
Call the named property on the given object, with return type R and 0 arguments.
shared_ptr< ScriptInterface::StructuredClone > m_GameState
#define PROFILE2_ATTR
Associates a string (with printf-style formatting) with the current region or event.
std::map< JSObject *, std::wstring > m_SerializablePrototypes
static void DumpHeap(void *cbdata)
virtual void RunGamestateInit()
static Status AllocateAligned(shared_ptr< T > &p, size_t size, size_t alignment=cacheLineSize)
Handle progressive loading of resources.
Grid< u8 > m_TerritoryMap
static void ClassInit(CComponentManager &componentManager)
virtual void String(const char *name, std::wstring &out, uint32_t minlength, uint32_t maxlength)
bool ContinueLoadEntityTemplates()
void StartLoadEntityTemplates()
jsval CallConstructor(jsval ctor, jsval arg)
Call a constructor function, equivalent to JS "new ctor(arg)".
bool m_HasLoadedEntityTemplates
Status tex_wrap(size_t w, size_t h, size_t bpp, size_t flags, const shared_ptr< u8 > &data, size_t ofs, Tex *t)
store the given image data into a Tex object; this will be as if it had been loaded via tex_load...
std::vector< VfsPath > VfsPaths
jsval get() const
Returns the current value (or JSVAL_VOID if uninitialised).
Implements worker thread for CCmpAIManager.
Abstraction around a SpiderMonkey JSContext.
void NumberI32_Unbounded(const char *name, int32_t value)
Serialize a number.
#define debug_warn(expr)
display the error dialog with the given text.
virtual void StartComputation()
Call this at the end of a turn, to trigger AI computation which will be ready for the next turn...
bool undefined() const
Returns whether the value is JSVAL_VOID.
virtual std::ostream & GetStream()=0
Returns a stream which can be used to serialize data directly.
void RegisterSerializablePrototype(std::wstring name, CScriptVal proto)
bool SetProperty(jsval obj, const char *name, const T &value, bool constant=false, bool enumerate=true)
Set the named property on the given object.
CAIPlayer(CAIWorker &worker, const std::wstring &aiName, player_id_t player, uint8_t difficulty, const shared_ptr< ScriptRuntime > &runtime, boost::rand48 &rng)
jsval ReadStructuredClone(const shared_ptr< StructuredClone > &ptr)
bool TryLoadSharedComponent(bool hasTechs)
void InitWithSharedScript(CScriptVal state, CScriptValRooted SharedAI)
void PerformComputation()
bool m_HasSharedComponent
Status GetPathnames(const PIVFS &fs, const VfsPath &path, const wchar_t *filter, VfsPaths &pathnames)
virtual void SetSerializablePrototypes(std::map< std::wstring, JSObject * > &prototypes)
virtual CScriptVal GetRepresentation()=0
Returns a script object that represents the current world state, to be passed to AI scripts...
JSContext * GetContext() const
void MaybeGC()
MaybeGC tries to determine whether garbage collection in cx's runtime would free up enough memory to ...
void tex_free(Tex *t)
free all resources associated with the image and make further use of it impossible.
std::vector< shared_ptr< ScriptInterface::StructuredClone > > m_Commands
Deserialization interface; see serialization overview.
virtual void NumberI32_Unbounded(const char *name, int32_t &out)
bool m_UseSharedComponent
static std::string GetSchema()
shared_ptr< StructuredClone > WriteStructuredClone(jsval v)