bool Initialise(bool callConstructor) { if (!LoadScripts(m_AIName)) return false; OsPath path = L"simulation/ai/" + m_AIName + L"/data.json"; CScriptValRooted metadata = m_Worker.LoadMetadata(path); if (metadata.uninitialised()) { LOGERROR(L"Failed to create AI player: can't find %ls", path.string().c_str()); return false; } // Get the constructor name from the metadata std::string constructor; if (!m_ScriptInterface.GetProperty(metadata.get(), "constructor", constructor)) { LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str()); return false; } // Get the constructor function from the loaded scripts CScriptVal ctor; if (!m_ScriptInterface.GetProperty(m_ScriptInterface.GetGlobalObject(), constructor.c_str(), ctor) || ctor.undefined()) { LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str()); return false; } CScriptVal obj; if (callConstructor) { // Set up the data to pass as the constructor argument CScriptVal settings; m_ScriptInterface.Eval(L"({})", settings); m_ScriptInterface.SetProperty(settings.get(), "player", m_Player, false); ENSURE(m_Worker.m_HasLoadedEntityTemplates); m_ScriptInterface.SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false); obj = m_ScriptInterface.CallConstructor(ctor.get(), settings.get()); } else { // For deserialization, we want to create the object with the correct prototype // but don't want to actually run the constructor again // XXX: actually we don't currently use this path for deserialization - maybe delete it? obj = m_ScriptInterface.NewObjectFromConstructor(ctor.get()); } if (obj.undefined()) { LOGERROR(L"Failed to create AI player: %ls: error calling constructor '%hs'", path.string().c_str(), constructor.c_str()); return false; } m_Obj = CScriptValRooted(m_ScriptInterface.GetContext(), obj); return true; }
bool Initialise(bool callConstructor) { // LoadScripts will only load each script once even though we call it for each player if (!m_Worker.LoadScripts(m_AIName)) return false; OsPath path = L"simulation/ai/" + m_AIName + L"/data.json"; CScriptValRooted metadata = m_Worker.LoadMetadata(path); if (metadata.uninitialised()) { LOGERROR(L"Failed to create AI player: can't find %ls", path.string().c_str()); return false; } // Get the constructor name from the metadata // If the AI doesn't use modules, we look for the constructor in the global object // TODO: All AIs should use modules. Remove the condition if this requirement is met. std::string moduleName; std::string constructor; CScriptVal objectWithConstructor; // object that should contain the constructor function CScriptVal ctor; if (!m_ScriptInterface->HasProperty(metadata.get(), "moduleName")) { objectWithConstructor = m_ScriptInterface->GetGlobalObject(); } else { m_ScriptInterface->GetProperty(metadata.get(), "moduleName", moduleName); if(!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), moduleName.c_str(), objectWithConstructor) || objectWithConstructor.undefined()) { LOGERROR(L"Failed to create AI player: %ls: can't find the module that should contain the constructor: '%hs'", path.string().c_str(), moduleName.c_str()); return false; } } if (!m_ScriptInterface->GetProperty(metadata.get(), "constructor", constructor)) { LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str()); return false; } // Get the constructor function from the loaded scripts if (!m_ScriptInterface->GetProperty(objectWithConstructor.get(), constructor.c_str(), ctor) || ctor.undefined()) { LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str()); return false; } m_ScriptInterface->GetProperty(metadata.get(), "useShared", m_UseSharedComponent); CScriptVal obj; if (callConstructor) { // Set up the data to pass as the constructor argument CScriptVal settings; m_ScriptInterface->Eval(L"({})", settings); m_ScriptInterface->SetProperty(settings.get(), "player", m_Player, false); m_ScriptInterface->SetProperty(settings.get(), "difficulty", m_Difficulty, false); ENSURE(m_Worker.m_HasLoadedEntityTemplates); m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false); obj = m_ScriptInterface->CallConstructor(ctor.get(), settings.get()); } else { // For deserialization, we want to create the object with the correct prototype // but don't want to actually run the constructor again // XXX: actually we don't currently use this path for deserialization - maybe delete it? obj = m_ScriptInterface->NewObjectFromConstructor(ctor.get()); } if (obj.undefined()) { LOGERROR(L"Failed to create AI player: %ls: error calling constructor '%hs'", path.string().c_str(), constructor.c_str()); return false; } m_Obj = CScriptValRooted(m_ScriptInterface->GetContext(), obj); return true; }