Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpAIManager.cpp
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | |||||
private: | private: | ||||
class CAIPlayer | class CAIPlayer | ||||
{ | { | ||||
NONCOPYABLE(CAIPlayer); | NONCOPYABLE(CAIPlayer); | ||||
public: | public: | ||||
CAIPlayer(CAIWorker& worker, const std::wstring& aiName, player_id_t player, u8 difficulty, const std::wstring& behavior, | CAIPlayer(CAIWorker& worker, const std::wstring& aiName, player_id_t player, u8 difficulty, const std::wstring& behavior, | ||||
shared_ptr<ScriptInterface> scriptInterface) : | shared_ptr<ScriptInterface> scriptInterface) : | ||||
m_Worker(worker), m_AIName(aiName), m_Player(player), m_Difficulty(difficulty), m_Behavior(behavior), | m_Worker(worker), m_AIName(aiName), m_Player(player), m_Difficulty(difficulty), m_Behavior(behavior), | ||||
m_ScriptInterface(scriptInterface), m_Obj(scriptInterface->GetJSRuntime()) | m_ScriptInterface(scriptInterface), m_Obj(scriptInterface->GetGeneralJSContext()) | ||||
{ | { | ||||
} | } | ||||
bool Initialise() | bool Initialise() | ||||
{ | { | ||||
// LoadScripts will only load each script once even though we call it for each player | // LoadScripts will only load each script once even though we call it for each player | ||||
if (!m_Worker.LoadScripts(m_AIName)) | if (!m_Worker.LoadScripts(m_AIName)) | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | public: | ||||
std::wstring m_Behavior; | std::wstring m_Behavior; | ||||
bool m_UseSharedComponent; | bool m_UseSharedComponent; | ||||
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted | // Take care to keep this declaration before heap rooted members. Destructors of heap rooted | ||||
// members have to be called before the context destructor. | // members have to be called before the context destructor. | ||||
shared_ptr<ScriptInterface> m_ScriptInterface; | shared_ptr<ScriptInterface> m_ScriptInterface; | ||||
JS::PersistentRootedValue m_Obj; | JS::PersistentRootedValue m_Obj; | ||||
std::vector<shared_ptr<ScriptInterface::StructuredClone> > m_Commands; | std::vector<ScriptInterface::StructuredClone > m_Commands; | ||||
}; | }; | ||||
public: | public: | ||||
struct SCommandSets | struct SCommandSets | ||||
{ | { | ||||
player_id_t player; | player_id_t player; | ||||
std::vector<shared_ptr<ScriptInterface::StructuredClone> > commands; | std::vector<ScriptInterface::StructuredClone > commands; | ||||
}; | }; | ||||
CAIWorker() : | CAIWorker() : | ||||
m_ScriptInterface(new ScriptInterface("Engine", "AI", g_ScriptContext)), | m_ScriptInterface(new ScriptInterface("Engine", "AI", g_ScriptContext)), | ||||
m_TurnNum(0), | m_TurnNum(0), | ||||
m_CommandsComputed(true), | m_CommandsComputed(true), | ||||
m_HasLoadedEntityTemplates(false), | m_HasLoadedEntityTemplates(false), | ||||
m_HasSharedComponent(false), | m_HasSharedComponent(false), | ||||
m_EntityTemplates(g_ScriptContext->GetJSRuntime()), | m_EntityTemplates(g_ScriptContext->GetGeneralJSContext()), | ||||
m_SharedAIObj(g_ScriptContext->GetJSRuntime()), | m_SharedAIObj(g_ScriptContext->GetGeneralJSContext()), | ||||
m_PassabilityMapVal(g_ScriptContext->GetJSRuntime()), | m_PassabilityMapVal(g_ScriptContext->GetGeneralJSContext()), | ||||
m_TerritoryMapVal(g_ScriptContext->GetJSRuntime()) | m_TerritoryMapVal(g_ScriptContext->GetGeneralJSContext()) | ||||
{ | { | ||||
m_ScriptInterface->ReplaceNondeterministicRNG(m_RNG); | m_ScriptInterface->ReplaceNondeterministicRNG(m_RNG); | ||||
m_ScriptInterface->SetCallbackData(static_cast<void*> (this)); | m_ScriptInterface->SetCallbackData(static_cast<void*> (this)); | ||||
JS_AddExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this); | JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); | ||||
m_ScriptInterface->RegisterFunction<void, int, JS::HandleValue, CAIWorker::PostCommand>("PostCommand"); | m_ScriptInterface->RegisterFunction<void, int, JS::HandleValue, CAIWorker::PostCommand>("PostCommand"); | ||||
m_ScriptInterface->RegisterFunction<void, std::wstring, CAIWorker::IncludeModule>("IncludeModule"); | m_ScriptInterface->RegisterFunction<void, std::wstring, CAIWorker::IncludeModule>("IncludeModule"); | ||||
m_ScriptInterface->RegisterFunction<void, CAIWorker::ExitProgram>("Exit"); | m_ScriptInterface->RegisterFunction<void, CAIWorker::ExitProgram>("Exit"); | ||||
m_ScriptInterface->RegisterFunction<JS::Value, JS::HandleValue, JS::HandleValue, pass_class_t, CAIWorker::ComputePath>("ComputePath"); | m_ScriptInterface->RegisterFunction<JS::Value, JS::HandleValue, JS::HandleValue, pass_class_t, CAIWorker::ComputePath>("ComputePath"); | ||||
m_ScriptInterface->RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage"); | m_ScriptInterface->RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage"); | ||||
m_ScriptInterface->RegisterFunction<CParamNode, std::string, CAIWorker::GetTemplate>("GetTemplate"); | m_ScriptInterface->RegisterFunction<CParamNode, std::string, CAIWorker::GetTemplate>("GetTemplate"); | ||||
JSI_VFS::RegisterScriptFunctions_Simulation(*(m_ScriptInterface.get())); | JSI_VFS::RegisterScriptFunctions_Simulation(*(m_ScriptInterface.get())); | ||||
// Globalscripts may use VFS script functions | // Globalscripts may use VFS script functions | ||||
m_ScriptInterface->LoadGlobalScripts(); | m_ScriptInterface->LoadGlobalScripts(); | ||||
} | } | ||||
~CAIWorker() | ~CAIWorker() | ||||
{ | { | ||||
JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this); | JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); | ||||
} | } | ||||
bool HasLoadedEntityTemplates() const { return m_HasLoadedEntityTemplates; } | bool HasLoadedEntityTemplates() const { return m_HasLoadedEntityTemplates; } | ||||
bool LoadScripts(const std::wstring& moduleName) | bool LoadScripts(const std::wstring& moduleName) | ||||
{ | { | ||||
// Ignore modules that are already loaded | // Ignore modules that are already loaded | ||||
if (m_LoadedModules.find(moduleName) != m_LoadedModules.end()) | if (m_LoadedModules.find(moduleName) != m_LoadedModules.end()) | ||||
Show All 37 Lines | public: | ||||
} | } | ||||
void PostCommand(int playerid, JS::HandleValue cmd) | void PostCommand(int playerid, JS::HandleValue cmd) | ||||
{ | { | ||||
for (size_t i=0; i<m_Players.size(); i++) | for (size_t i=0; i<m_Players.size(); i++) | ||||
{ | { | ||||
if (m_Players[i]->m_Player == playerid) | if (m_Players[i]->m_Player == playerid) | ||||
{ | { | ||||
m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd)); | m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd, false)); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
LOGERROR("Invalid playerid in PostCommand!"); | LOGERROR("Invalid playerid in PostCommand!"); | ||||
} | } | ||||
static JS::Value ComputePath(ScriptInterface::CmptPrivate* pCmptPrivate, | static JS::Value ComputePath(ScriptInterface::CmptPrivate* pCmptPrivate, | ||||
▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | bool AddPlayer(const std::wstring& aiName, player_id_t player, u8 difficulty, const std::wstring& behavior) | ||||
if (!m_HasSharedComponent) | if (!m_HasSharedComponent) | ||||
m_HasSharedComponent = ai->m_UseSharedComponent; | m_HasSharedComponent = ai->m_UseSharedComponent; | ||||
m_Players.push_back(ai); | m_Players.push_back(ai); | ||||
return true; | return true; | ||||
} | } | ||||
bool RunGamestateInit(const shared_ptr<ScriptInterface::StructuredClone>& gameState, const Grid<NavcellData>& passabilityMap, const Grid<u8>& territoryMap, | bool RunGamestateInit(const ScriptInterface::StructuredClone& gameState, const Grid<NavcellData>& passabilityMap, const Grid<u8>& territoryMap, | ||||
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks) | const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks) | ||||
{ | { | ||||
// this will be run last by InitGame.js, passing the full game representation. | // this will be run last by InitGame.js, passing the full game representation. | ||||
// For now it will run for the shared Component. | // For now it will run for the shared Component. | ||||
// This is NOT run during deserialization. | // This is NOT run during deserialization. | ||||
ScriptRequest rq(m_ScriptInterface); | ScriptRequest rq(m_ScriptInterface); | ||||
JS::RootedValue state(rq.cx); | JS::RootedValue state(rq.cx); | ||||
Show All 19 Lines | if (m_HasSharedComponent) | ||||
if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent) | if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent) | ||||
m_Players[i]->InitAI(state, m_SharedAIObj); | m_Players[i]->InitAI(state, m_SharedAIObj); | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void UpdateGameState(const shared_ptr<ScriptInterface::StructuredClone>& gameState) | void UpdateGameState(const ScriptInterface::StructuredClone& gameState) | ||||
{ | { | ||||
ENSURE(m_CommandsComputed); | ENSURE(m_CommandsComputed); | ||||
m_GameState = gameState; | m_GameState = gameState; | ||||
} | } | ||||
void UpdatePathfinder(const Grid<NavcellData>& passabilityMap, bool globallyDirty, const Grid<u8>& dirtinessGrid, bool justDeserialized, | void UpdatePathfinder(const Grid<NavcellData>& passabilityMap, bool globallyDirty, const Grid<u8>& dirtinessGrid, bool justDeserialized, | ||||
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks) | const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < numAis; ++i) | ||||
u32 numCommands; | u32 numCommands; | ||||
deserializer.NumberU32_Unbounded("num commands", numCommands); | deserializer.NumberU32_Unbounded("num commands", numCommands); | ||||
m_Players.back()->m_Commands.reserve(numCommands); | m_Players.back()->m_Commands.reserve(numCommands); | ||||
for (size_t j = 0; j < numCommands; ++j) | for (size_t j = 0; j < numCommands; ++j) | ||||
{ | { | ||||
JS::RootedValue val(rq.cx); | JS::RootedValue val(rq.cx); | ||||
deserializer.ScriptVal("command", &val); | deserializer.ScriptVal("command", &val); | ||||
m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val)); | m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val, false)); | ||||
} | } | ||||
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj, "Deserialize"); | bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj, "Deserialize"); | ||||
if (hasCustomDeserialize) | if (hasCustomDeserialize) | ||||
{ | { | ||||
JS::RootedValue scriptData(rq.cx); | JS::RootedValue scriptData(rq.cx); | ||||
deserializer.ScriptVal("data", &scriptData); | deserializer.ScriptVal("data", &scriptData); | ||||
if (m_Players[i]->m_UseSharedComponent) | if (m_Players[i]->m_UseSharedComponent) | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | private: | ||||
std::vector<shared_ptr<CAIPlayer> > m_Players; // use shared_ptr just to avoid copying | std::vector<shared_ptr<CAIPlayer> > m_Players; // use shared_ptr just to avoid copying | ||||
bool m_HasSharedComponent; | bool m_HasSharedComponent; | ||||
JS::PersistentRootedValue m_SharedAIObj; | JS::PersistentRootedValue m_SharedAIObj; | ||||
std::vector<SCommandSets> m_Commands; | std::vector<SCommandSets> m_Commands; | ||||
std::set<std::wstring> m_LoadedModules; | std::set<std::wstring> m_LoadedModules; | ||||
shared_ptr<ScriptInterface::StructuredClone> m_GameState; | ScriptInterface::StructuredClone m_GameState; | ||||
Grid<NavcellData> m_PassabilityMap; | Grid<NavcellData> m_PassabilityMap; | ||||
JS::PersistentRootedValue m_PassabilityMapVal; | JS::PersistentRootedValue m_PassabilityMapVal; | ||||
Grid<u8> m_TerritoryMap; | Grid<u8> m_TerritoryMap; | ||||
JS::PersistentRootedValue m_TerritoryMapVal; | JS::PersistentRootedValue m_TerritoryMapVal; | ||||
std::map<std::string, pass_class_t> m_NonPathfindingPassClasses; | std::map<std::string, pass_class_t> m_NonPathfindingPassClasses; | ||||
std::map<std::string, pass_class_t> m_PathfindingPassClasses; | std::map<std::string, pass_class_t> m_PathfindingPassClasses; | ||||
HierarchicalPathfinder m_HierarchicalPathfinder; | HierarchicalPathfinder m_HierarchicalPathfinder; | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | virtual void RunGamestateInit() | ||||
if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdateAI(&m_TerritoriesDirtyID, &m_TerritoriesDirtyBlinkingID)) | if (cmpTerritoryManager && cmpTerritoryManager->NeedUpdateAI(&m_TerritoriesDirtyID, &m_TerritoriesDirtyBlinkingID)) | ||||
territoryMap = &cmpTerritoryManager->GetTerritoryGrid(); | territoryMap = &cmpTerritoryManager->GetTerritoryGrid(); | ||||
LoadPathfinderClasses(state); | LoadPathfinderClasses(state); | ||||
std::map<std::string, pass_class_t> nonPathfindingPassClassMasks, pathfindingPassClassMasks; | std::map<std::string, pass_class_t> nonPathfindingPassClassMasks, pathfindingPassClassMasks; | ||||
if (cmpPathfinder) | if (cmpPathfinder) | ||||
cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks); | cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks); | ||||
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks); | m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state, false), | ||||
*passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks); | |||||
} | } | ||||
virtual void StartComputation() | virtual void StartComputation() | ||||
{ | { | ||||
PROFILE("AI setup"); | PROFILE("AI setup"); | ||||
const ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); | const ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
if (m_Worker.getPlayerSize() == 0) | if (m_Worker.getPlayerSize() == 0) | ||||
return; | return; | ||||
CmpPtr<ICmpAIInterface> cmpAIInterface(GetSystemEntity()); | CmpPtr<ICmpAIInterface> cmpAIInterface(GetSystemEntity()); | ||||
ENSURE(cmpAIInterface); | ENSURE(cmpAIInterface); | ||||
// Get the game state from AIInterface | // Get the game state from AIInterface | ||||
JS::RootedValue state(rq.cx); | JS::RootedValue state(rq.cx); | ||||
if (m_JustDeserialized) | if (m_JustDeserialized) | ||||
cmpAIInterface->GetFullRepresentation(&state, false); | cmpAIInterface->GetFullRepresentation(&state, false); | ||||
else | else | ||||
cmpAIInterface->GetRepresentation(&state); | cmpAIInterface->GetRepresentation(&state); | ||||
LoadPathfinderClasses(state); // add the pathfinding classes to it | LoadPathfinderClasses(state); // add the pathfinding classes to it | ||||
// Update the game state | // Update the game state | ||||
m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state)); | m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state, false)); | ||||
// Update the pathfinding data | // Update the pathfinding data | ||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); | ||||
if (cmpPathfinder) | if (cmpPathfinder) | ||||
{ | { | ||||
const GridUpdateInformation& dirtinessInformations = cmpPathfinder->GetAIPathfinderDirtinessInformation(); | const GridUpdateInformation& dirtinessInformations = cmpPathfinder->GetAIPathfinderDirtinessInformation(); | ||||
if (dirtinessInformations.dirty || m_JustDeserialized) | if (dirtinessInformations.dirty || m_JustDeserialized) | ||||
▲ Show 20 Lines • Show All 106 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator