예제 #1
0
bool CMapGeneratorWorker::Run()
{
	m_ScriptInterface->SetCallbackData(static_cast<void*> (this));

	// Replace RNG with a seeded deterministic function
	m_ScriptInterface->ReplaceNondeterministicRNG(m_MapGenRNG);
	m_ScriptInterface->LoadGlobalScripts();

	// Functions for RMS
	m_ScriptInterface->RegisterFunction<bool, std::wstring, CMapGeneratorWorker::LoadLibrary>("LoadLibrary");
	m_ScriptInterface->RegisterFunction<void, CScriptValRooted, CMapGeneratorWorker::ExportMap>("ExportMap");
	m_ScriptInterface->RegisterFunction<void, int, CMapGeneratorWorker::SetProgress>("SetProgress");
	m_ScriptInterface->RegisterFunction<void, CMapGeneratorWorker::MaybeGC>("MaybeGC");
	m_ScriptInterface->RegisterFunction<std::vector<std::string>, CMapGeneratorWorker::GetCivData>("GetCivData");

	// Parse settings
	CScriptValRooted settingsVal = m_ScriptInterface->ParseJSON(m_Settings);
	if (settingsVal.undefined())
	{
		LOGERROR(L"CMapGeneratorWorker::Run: Failed to parse settings");
		return false;
	}

	// Init RNG seed
	uint32_t seed;
	if (!m_ScriptInterface->GetProperty(settingsVal.get(), "Seed", seed))
	{	// No seed specified
		LOGWARNING(L"CMapGeneratorWorker::Run: No seed value specified - using 0");
		seed = 0;
	}

	m_MapGenRNG.seed((int32_t)seed);

	// Copy settings to global variable
	if (!m_ScriptInterface->SetProperty(m_ScriptInterface->GetGlobalObject(), "g_MapSettings", settingsVal))
	{
		LOGERROR(L"CMapGeneratorWorker::Run: Failed to define g_MapSettings");
		return false;
	}

	// Load RMS
	LOGMESSAGE(L"Loading RMS '%ls'", m_ScriptPath.string().c_str());
	if (!m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath))
	{
		LOGERROR(L"CMapGeneratorWorker::Run: Failed to load RMS '%ls'", m_ScriptPath.string().c_str());
		return false;
	}

	return true;
}
예제 #2
0
bool Autostart(const CmdLineArgs& args)
{
	/*
	 * Handle various command-line options, for quick testing of various features:
	 * -autostart=name					-- map name for scenario, or rms name for random map
	 * -autostart-ai=1:dummybot			-- adds the dummybot AI to player 1
	 * -autostart-playername=name		-- multiplayer player name
	 * -autostart-host					-- multiplayer host mode
	 * -autostart-players=2				-- number of players
	 * -autostart-client				-- multiplayer client mode
	 * -autostart-ip=127.0.0.1			-- multiplayer connect to 127.0.0.1
	 * -autostart-random=104			-- random map, optional seed value = 104 (default is 0, random is -1)
	 * -autostart-size=192				-- random map size in tiles = 192 (default is 192)
	 *
	 * Examples:
	 * -autostart=Acropolis -autostart-host -autostart-players=2		-- Host game on Acropolis map, 2 players
	 * -autostart=latium -autostart-random=-1							-- Start single player game on latium random map, random rng seed
	 */

	CStr autoStartName = args.Get("autostart");

#if OS_ANDROID
	// HACK: currently the most convenient way to test maps on Android;
	// should find a better solution
	autoStartName = "Oasis";
#endif

	if (autoStartName.empty())
	{
		return false;
	}

	g_Game = new CGame();

	ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface();

	CScriptValRooted attrs;
	scriptInterface.Eval("({})", attrs);
	CScriptVal settings;
	scriptInterface.Eval("({})", settings);
	CScriptVal playerData;
	scriptInterface.Eval("([])", playerData);

	// Set different attributes for random or scenario game
	if (args.Has("autostart-random"))
	{
		CStr seedArg = args.Get("autostart-random");

		// Default seed is 0
		uint32 seed = 0;
		if (!seedArg.empty())
		{
			if (seedArg.compare("-1") == 0)
			{	// Random seed value
				seed = rand();
			}
			else
			{
				seed = seedArg.ToULong();
			}
		}
		
		// Random map definition will be loaded from JSON file, so we need to parse it
		std::wstring mapPath = L"maps/random/";
		std::wstring scriptPath = mapPath + autoStartName.FromUTF8() + L".json";
		CScriptValRooted scriptData = scriptInterface.ReadJSONFile(scriptPath);
		if (!scriptData.undefined() && scriptInterface.GetProperty(scriptData.get(), "settings", settings))
		{
			// JSON loaded ok - copy script name over to game attributes
			std::wstring scriptFile;
			scriptInterface.GetProperty(settings.get(), "Script", scriptFile);
			scriptInterface.SetProperty(attrs.get(), "script", scriptFile);				// RMS filename
		}
		else
		{
			// Problem with JSON file
			LOGERROR(L"Error reading random map script '%ls'", scriptPath.c_str());
			throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details.");
		}

		// Get optional map size argument (default 192)
		uint mapSize = 192;
		if (args.Has("autostart-size"))
		{
			CStr size = args.Get("autostart-size");
			mapSize = size.ToUInt();
		}

		scriptInterface.SetProperty(attrs.get(), "map", std::string(autoStartName));
		scriptInterface.SetProperty(attrs.get(), "mapPath", mapPath);
		scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"));
		scriptInterface.SetProperty(settings.get(), "Seed", seed);									// Random seed
		scriptInterface.SetProperty(settings.get(), "Size", mapSize);								// Random map size (in patches)

		// Get optional number of players (default 2)
		size_t numPlayers = 2;
		if (args.Has("autostart-players"))
		{
			CStr num = args.Get("autostart-players");
			numPlayers = num.ToUInt();
		}

		// Set up player data
		for (size_t i = 0; i < numPlayers; ++i)
		{
			CScriptVal player;
			scriptInterface.Eval("({})", player);

			// We could load player_defaults.json here, but that would complicate the logic
			//	even more and autostart is only intended for developers anyway
			scriptInterface.SetProperty(player.get(), "Civ", std::string("athen"));
			scriptInterface.SetPropertyInt(playerData.get(), i, player);
		}
	}
	else
	{
		scriptInterface.SetProperty(attrs.get(), "map", std::string(autoStartName));
		scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"));
	}

	// Set player data for AIs
	//		attrs.settings = { PlayerData: [ { AI: ... }, ... ] }:
	if (args.Has("autostart-ai"))
	{
		std::vector<CStr> aiArgs = args.GetMultiple("autostart-ai");
		for (size_t i = 0; i < aiArgs.size(); ++i)
		{
			// Instead of overwriting existing player data, modify the array
			CScriptVal player;
			if (!scriptInterface.GetPropertyInt(playerData.get(), i, player) || player.undefined())
			{
				scriptInterface.Eval("({})", player);
			}

			int playerID = aiArgs[i].BeforeFirst(":").ToInt();
			CStr name = aiArgs[i].AfterFirst(":");

			scriptInterface.SetProperty(player.get(), "AI", std::string(name));
			scriptInterface.SetPropertyInt(playerData.get(), playerID-1, player);
		}
	}

	// Add player data to map settings
	scriptInterface.SetProperty(settings.get(), "PlayerData", playerData);

	// Add map settings to game attributes
	scriptInterface.SetProperty(attrs.get(), "settings", settings);

	CScriptVal mpInitData;
	g_GUI->GetScriptInterface().Eval("({isNetworked:true, playerAssignments:{}})", mpInitData);
	g_GUI->GetScriptInterface().SetProperty(mpInitData.get(), "attribs",
			CScriptVal(g_GUI->GetScriptInterface().CloneValueFromOtherContext(scriptInterface, attrs.get())));

	// Get optional playername
	CStrW userName = L"anonymous";
	if (args.Has("autostart-playername"))
	{
		userName = args.Get("autostart-playername").FromUTF8();
	}

	if (args.Has("autostart-host"))
	{
		InitPs(true, L"page_loading.xml", mpInitData.get());

		size_t maxPlayers = 2;
		if (args.Has("autostart-players"))
		{
			maxPlayers = args.Get("autostart-players").ToUInt();
		}

		g_NetServer = new CNetServer(maxPlayers);

		g_NetServer->UpdateGameAttributes(attrs.get(), scriptInterface);

		bool ok = g_NetServer->SetupConnection();
		ENSURE(ok);

		g_NetClient = new CNetClient(g_Game);
		g_NetClient->SetUserName(userName);
		g_NetClient->SetupConnection("127.0.0.1");
	}
	else if (args.Has("autostart-client"))
	{
		InitPs(true, L"page_loading.xml", mpInitData.get());

		g_NetClient = new CNetClient(g_Game);
		g_NetClient->SetUserName(userName);

		CStr ip = "127.0.0.1";
		if (args.Has("autostart-ip"))
		{
			ip = args.Get("autostart-ip");
		}

		bool ok = g_NetClient->SetupConnection(ip);
		ENSURE(ok);
	}
	else
	{
		g_Game->SetPlayerID(1);
		g_Game->StartGame(attrs, "");

		LDR_NonprogressiveLoad();

		PSRETURN ret = g_Game->ReallyStartGame();
		ENSURE(ret == PSRETURN_OK);

		InitPs(true, L"page_session.xml", JSVAL_VOID);
	}

	return true;
}
예제 #3
0
bool CMapGeneratorWorker::Run()
{
    m_ScriptInterface->SetCallbackData(static_cast<void*> (this));

    // Replace RNG with a seeded deterministic function
    m_ScriptInterface->ReplaceNondeterministicRNG(m_MapGenRNG);
    m_ScriptInterface->LoadGlobalScripts();

    // Functions for RMS
    m_ScriptInterface->RegisterFunction<bool, std::wstring, CMapGeneratorWorker::LoadLibrary>("LoadLibrary");
    m_ScriptInterface->RegisterFunction<void, CScriptValRooted, CMapGeneratorWorker::ExportMap>("ExportMap");
    m_ScriptInterface->RegisterFunction<void, int, CMapGeneratorWorker::SetProgress>("SetProgress");
    m_ScriptInterface->RegisterFunction<void, CMapGeneratorWorker::MaybeGC>("MaybeGC");
    m_ScriptInterface->RegisterFunction<std::vector<std::string>, CMapGeneratorWorker::GetCivData>("GetCivData");

    // TODO: This code is a bit ugly because we have to ensure that CScriptValRooted gets destroyed before the ScriptInterface.
    // In the future we should work more with the standard JSAPI types for rooting on the stack, which should avoid such problems.
    bool ret = true;
    {
        // Parse settings
        CScriptValRooted settingsVal = m_ScriptInterface->ParseJSON(m_Settings);
        if (settingsVal.undefined())
        {
            LOGERROR(L"CMapGeneratorWorker::Run: Failed to parse settings");
            ret = false;
        }
        else
        {
            // Init RNG seed
            u32 seed;
            if (!m_ScriptInterface->GetProperty(settingsVal.get(), "Seed", seed))
            {   // No seed specified
                LOGWARNING(L"CMapGeneratorWorker::Run: No seed value specified - using 0");
                seed = 0;
            }

            m_MapGenRNG.seed(seed);

            // Copy settings to global variable
            if (!m_ScriptInterface->SetProperty(m_ScriptInterface->GetGlobalObject(), "g_MapSettings", settingsVal))
            {
                LOGERROR(L"CMapGeneratorWorker::Run: Failed to define g_MapSettings");
                ret = false;
            }
            else
            {
                // Load RMS
                LOGMESSAGE(L"Loading RMS '%ls'", m_ScriptPath.string().c_str());
                if (!m_ScriptInterface->LoadGlobalScriptFile(m_ScriptPath))
                {
                    LOGERROR(L"CMapGeneratorWorker::Run: Failed to load RMS '%ls'", m_ScriptPath.string().c_str());
                    ret = false;
                }
            }
        }
    }

    // We must destroy the ScriptInterface in the same thread because the JSAPI requires that!
    SAFE_DELETE(m_ScriptInterface);

    return ret;
}
예제 #4
0
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
void CMapReader::LoadMap(const VfsPath& pathname,  const CScriptValRooted& settings, CTerrain *pTerrain_,
						 WaterManager* pWaterMan_, SkyManager* pSkyMan_,
						 CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
						 CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities)
{
	// latch parameters (held until DelayedLoadFinished)
	pTerrain = pTerrain_;
	pLightEnv = pLightEnv_;
	pGameView = pGameView_;
	pWaterMan = pWaterMan_;
	pSkyMan = pSkyMan_;
	pCinema = pCinema_;
	pTrigMan = pTrigMan_;
	pPostproc = pPostproc_;
	pSimulation2 = pSimulation2_;
	pSimContext = pSimContext_;
	m_PlayerID = playerID_;
	m_SkipEntities = skipEntities;
	m_StartingCameraTarget = INVALID_ENTITY;
	m_ScriptSettings = settings;

	filename_xml = pathname.ChangeExtension(L".xml");

	// In some cases (particularly tests) we don't want to bother storing a large
	// mostly-empty .pmp file, so we let the XML file specify basic terrain instead.
	// If there's an .xml file and no .pmp, then we're probably in this XML-only mode
	only_xml = false;
	if (!VfsFileExists(pathname) && VfsFileExists(filename_xml))
	{
		only_xml = true;
	}

	file_format_version = CMapIO::FILE_VERSION; // default if there's no .pmp

	if (!only_xml)
	{
		// [25ms]
		unpacker.Read(pathname, "PSMP");
		file_format_version = unpacker.GetVersion();
	}

	// check oldest supported version
	if (file_format_version < FILE_READ_VERSION)
		throw PSERROR_File_InvalidVersion();

	// delete all existing entities
	if (pSimulation2)
		pSimulation2->ResetState();
	
	// reset post effects
	if (pPostproc)
		pPostproc->SetPostEffect(L"default");

	// load map or script settings script
	if (settings.undefined())
		RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);
	else
		RegMemFun(this, &CMapReader::LoadRMSettings, L"CMapReader::LoadRMSettings", 50);

	// load player settings script (must be done before reading map)
	RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);

	// unpack the data
	if (!only_xml)
		RegMemFun(this, &CMapReader::UnpackMap, L"CMapReader::UnpackMap", 1200);

	// read the corresponding XML file
	RegMemFun(this, &CMapReader::ReadXML, L"CMapReader::ReadXML", 5800);

	// apply data to the world
	RegMemFun(this, &CMapReader::ApplyData, L"CMapReader::ApplyData", 5);

	// load map settings script (must be done after reading map)
	RegMemFun(this, &CMapReader::LoadMapSettings, L"CMapReader::LoadMapSettings", 5);

	RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
}