Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpAIManager.cpp
/* Copyright (C) 2020 Wildfire Games. | /* Copyright (C) 2021 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
▲ Show 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | |||||
public: | public: | ||||
struct SCommandSets | struct SCommandSets | ||||
{ | { | ||||
player_id_t player; | player_id_t player; | ||||
std::vector<ScriptInterface::StructuredClone > commands; | std::vector<ScriptInterface::StructuredClone > commands; | ||||
}; | }; | ||||
CAIWorker() : | CAIWorker() : | ||||
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->GetGeneralJSContext()), | |||||
m_SharedAIObj(g_ScriptContext->GetGeneralJSContext()), | |||||
m_PassabilityMapVal(g_ScriptContext->GetGeneralJSContext()), | |||||
m_TerritoryMapVal(g_ScriptContext->GetGeneralJSContext()) | |||||
{ | { | ||||
} | |||||
~CAIWorker() | |||||
{ | |||||
JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); | |||||
} | |||||
void Init(CComponentManager* compMan) | |||||
{ | |||||
m_ComponentManager = compMan; | |||||
// Create the script interface in the same compartment as the simulation interface. | |||||
// This will allow us to directly share data from the sim to the AI (and vice versa, should the need arise). | |||||
m_ScriptInterface = std::make_shared<ScriptInterface>("Engine", "AI", compMan->GetScriptInterface()); | |||||
ScriptRequest rq(m_ScriptInterface); | |||||
m_EntityTemplates.init(rq.cx); | |||||
m_SharedAIObj.init(rq.cx); | |||||
m_PassabilityMapVal.init(rq.cx); | |||||
m_TerritoryMapVal.init(rq.cx); | |||||
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->GetGeneralJSContext(), Trace, this); | JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); | ||||
ScriptRequest rq(m_ScriptInterface); | { | ||||
ScriptRequest simrq(m_ComponentManager->GetScriptInterface()); | |||||
// Register the sim globals for easy & explicit access. Mark it replaceable for hotloading. | |||||
JS::RootedValue global(rq.cx, simrq.globalValue()); | |||||
m_ScriptInterface->SetGlobal("Sim", global, true); | |||||
JS::RootedValue scope(rq.cx, JS::ObjectValue(*simrq.nativeScope.get())); | |||||
m_ScriptInterface->SetGlobal("SimEngine", scope, true); | |||||
} | |||||
#define REGISTER_FUNC_NAME(func, name) \ | #define REGISTER_FUNC_NAME(func, name) \ | ||||
ScriptFunction::Register<&CAIWorker::func, ScriptFunction::ObjectFromCBData<CAIWorker>>(rq, name); | ScriptFunction::Register<&CAIWorker::func, ScriptFunction::ObjectFromCBData<CAIWorker>>(rq, name); | ||||
REGISTER_FUNC_NAME(PostCommand, "PostCommand"); | REGISTER_FUNC_NAME(PostCommand, "PostCommand"); | ||||
REGISTER_FUNC_NAME(LoadScripts, "IncludeModule"); | REGISTER_FUNC_NAME(LoadScripts, "IncludeModule"); | ||||
ScriptFunction::Register<QuitEngine>(rq, "Exit"); | ScriptFunction::Register<QuitEngine>(rq, "Exit"); | ||||
REGISTER_FUNC_NAME(ComputePathScript, "ComputePath"); | REGISTER_FUNC_NAME(ComputePathScript, "ComputePath"); | ||||
REGISTER_FUNC_NAME(DumpImage, "DumpImage"); | REGISTER_FUNC_NAME(DumpImage, "DumpImage"); | ||||
REGISTER_FUNC_NAME(GetTemplate, "GetTemplate"); | REGISTER_FUNC_NAME(GetTemplate, "GetTemplate"); | ||||
#undef REGISTER_FUNC_NAME | #undef REGISTER_FUNC_NAME | ||||
JSI_VFS::RegisterScriptFunctions_Simulation(rq); | JSI_VFS::RegisterScriptFunctions_Simulation(rq); | ||||
// Globalscripts may use VFS script functions | // Globalscripts may use VFS script functions | ||||
m_ScriptInterface->LoadGlobalScripts(); | m_ScriptInterface->LoadGlobalScripts(); | ||||
} | |||||
~CAIWorker() | |||||
{ | |||||
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 20 Lines • Show All 539 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < m_Players.size(); ++i) | ||||
if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent) | if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent) | ||||
m_Players[i]->Run(state, m_Players[i]->m_Player, m_SharedAIObj); | m_Players[i]->Run(state, m_Players[i]->m_Player, m_SharedAIObj); | ||||
else | else | ||||
m_Players[i]->Run(state, m_Players[i]->m_Player); | m_Players[i]->Run(state, m_Players[i]->m_Player); | ||||
} | } | ||||
} | } | ||||
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted | |||||
// members have to be called before the context destructor. | |||||
shared_ptr<ScriptContext> m_ScriptContext; | |||||
shared_ptr<ScriptInterface> m_ScriptInterface; | shared_ptr<ScriptInterface> m_ScriptInterface; | ||||
boost::rand48 m_RNG; | boost::rand48 m_RNG; | ||||
u32 m_TurnNum; | u32 m_TurnNum; | ||||
CComponentManager* m_ComponentManager = nullptr; | |||||
JS::PersistentRootedValue m_EntityTemplates; | JS::PersistentRootedValue m_EntityTemplates; | ||||
bool m_HasLoadedEntityTemplates; | bool m_HasLoadedEntityTemplates; | ||||
std::map<VfsPath, JS::Heap<JS::Value> > m_PlayerMetadata; | std::map<VfsPath, JS::Heap<JS::Value> > m_PlayerMetadata; | ||||
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; | ||||
Show All 32 Lines | public: | ||||
static std::string GetSchema() | static std::string GetSchema() | ||||
{ | { | ||||
return "<a:component type='system'/><empty/>"; | return "<a:component type='system'/><empty/>"; | ||||
} | } | ||||
virtual void Init(const CParamNode& UNUSED(paramNode)) | virtual void Init(const CParamNode& UNUSED(paramNode)) | ||||
{ | { | ||||
m_Worker.Init(&GetSimContext().GetComponentManager()); | |||||
m_TerritoriesDirtyID = 0; | m_TerritoriesDirtyID = 0; | ||||
m_TerritoriesDirtyBlinkingID = 0; | m_TerritoriesDirtyBlinkingID = 0; | ||||
m_JustDeserialized = false; | m_JustDeserialized = false; | ||||
} | } | ||||
virtual void Deinit() | virtual void Deinit() | ||||
{ | { | ||||
} | } | ||||
▲ Show 20 Lines • Show All 225 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator