Example #1
0
		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;
		}
Example #2
0
		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;
		}