diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 3a3e8363..ec4db510 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -111,6 +111,7 @@ Game::Game() : ProgramState(NULL) { currentAmbientSound=NULL; //printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound); + loadGameNode = NULL; lastNetworkPlayerConnectionCheck = time(NULL); fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str()); @@ -184,6 +185,8 @@ void Game::resetMembers() { currentAmbientSound=NULL; //printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound); + loadGameNode = NULL; + lastNetworkPlayerConnectionCheck = time(NULL); fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str()); @@ -843,6 +846,9 @@ void Game::init(bool initForPreviewOnly) { } world.init(this, gameSettings.getDefaultUnits()); + if(loadGameNode != NULL) { + //world.getMapPtr()->loadGame(loadGameNode,&world); + } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); @@ -3493,6 +3499,7 @@ void Game::saveGame(string name) { weatherParticleSystem->saveGame(gameNode); } //GameSettings gameSettings; + gameSettings.saveGame(gameNode); //Vec2i lastMousePos; gameNode->addAttribute("lastMousePos",lastMousePos.getString(), mapTagReplacements); //time_t lastRenderLog2d; @@ -3574,4 +3581,45 @@ void Game::saveGame(string name) { xmlTree.save(saveGameFile); } +void Game::loadGame(string name,Program *programPtr,bool isMasterserverMode) { + XmlTree xmlTree; + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Before load of XML\n"); + std::map mapExtraTagReplacementValues; + xmlTree.load(name, Properties::getTagReplacementValues(&mapExtraTagReplacementValues),true); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("After load of XML\n"); + + const XmlNode *rootNode= xmlTree.getRootNode(); + + //const XmlNode *versionNode= rootNode->getChild("megaglest-saved-game"); + const XmlNode *versionNode= rootNode; + + string gameVer = versionNode->getAttribute("version")->getValue(); + if(gameVer != glestVersionString) { + char szBuf[4096]=""; + sprintf(szBuf,"saved game version does match your application version: [%s] --> [%s]",gameVer.c_str(),glestVersionString.c_str()); + throw runtime_error(szBuf); + } + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Found saved game version that matches your application version: [%s] --> [%s]\n",gameVer.c_str(),glestVersionString.c_str()); + + XmlNode *gameNode = rootNode->getChild("Game"); + GameSettings newGameSettings; + newGameSettings.loadGame(gameNode); + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Game settings loaded\n"); + + NetworkManager &networkManager= NetworkManager::getInstance(); + networkManager.end(); + networkManager.init(nrServer,true); + + Game *newGame = new Game(programPtr, &newGameSettings, isMasterserverMode); + newGame->loadGameNode = gameNode; + + const XmlNode *worldNode = gameNode->getChild("World"); + newGame->world.loadGame(worldNode); + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Starting Game ...\n"); + programPtr->setState(newGame); +} + }}//end namespace diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h index 55e0cd61..82c7067b 100644 --- a/source/glest_game/game/game.h +++ b/source/glest_game/game/game.h @@ -149,6 +149,8 @@ private: time_t lastMasterServerGameStatsDump; + XmlNode *loadGameNode; + public: Game(); Game(Program *program, const GameSettings *gameSettings, bool masterserverMode); @@ -226,6 +228,7 @@ public: void endGame(); void saveGame(string name); + static void loadGame(string name,Program *programPtr,bool isMasterserverMode); private: //render diff --git a/source/glest_game/game/game_settings.h b/source/glest_game/game/game_settings.h index a6c8cfab..8d71f970 100644 --- a/source/glest_game/game/game_settings.h +++ b/source/glest_game/game/game_settings.h @@ -15,9 +15,11 @@ #include "game_constants.h" #include "conversion.h" #include +#include "xml_parser.h" #include "leak_dumper.h" using namespace Shared::Util; +using Shared::Xml::XmlNode; namespace Glest{ namespace Game{ @@ -292,6 +294,234 @@ public: return result; } + + void saveGame(XmlNode *rootNode) const { + std::map mapTagReplacements; + XmlNode *gameSettingsNode = rootNode->addChild("GameSettings"); + +// string description; + gameSettingsNode->addAttribute("description",description, mapTagReplacements); +// string map; + gameSettingsNode->addAttribute("map",map, mapTagReplacements); +// string tileset; + gameSettingsNode->addAttribute("tileset",tileset, mapTagReplacements); +// string tech; + gameSettingsNode->addAttribute("tech",tech, mapTagReplacements); +// string scenario; + gameSettingsNode->addAttribute("scenario",scenario, mapTagReplacements); +// string scenarioDir; + gameSettingsNode->addAttribute("scenarioDir",scenarioDir, mapTagReplacements); +// string factionTypeNames[GameConstants::maxPlayers]; //faction names + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *factionTypeNamesNode = gameSettingsNode->addChild("factionTypeNames"); + factionTypeNamesNode->addAttribute("name",factionTypeNames[idx], mapTagReplacements); + } + +// string networkPlayerNames[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *networkPlayerNamesNode = gameSettingsNode->addChild("networkPlayerNames"); + networkPlayerNamesNode->addAttribute("name",networkPlayerNames[idx], mapTagReplacements); + } + +// int networkPlayerStatuses[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *networkPlayerStatusesNode = gameSettingsNode->addChild("networkPlayerStatuses"); + networkPlayerStatusesNode->addAttribute("status",intToStr(networkPlayerStatuses[idx]), mapTagReplacements); + } + +// string networkPlayerLanguages[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *networkPlayerLanguagesNode = gameSettingsNode->addChild("networkPlayerLanguages"); + networkPlayerLanguagesNode->addAttribute("name",networkPlayerLanguages[idx], mapTagReplacements); + } + +// ControlType factionControls[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *factionControlsNode = gameSettingsNode->addChild("factionControls"); + factionControlsNode->addAttribute("control",intToStr(factionControls[idx]), mapTagReplacements); + } + +// int resourceMultiplierIndex[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *resourceMultiplierIndexNode = gameSettingsNode->addChild("resourceMultiplierIndex"); + resourceMultiplierIndexNode->addAttribute("multiplier",intToStr(resourceMultiplierIndex[idx]), mapTagReplacements); + } + +// int thisFactionIndex; + gameSettingsNode->addAttribute("thisFactionIndex",intToStr(thisFactionIndex), mapTagReplacements); +// int factionCount; + gameSettingsNode->addAttribute("factionCount",intToStr(factionCount), mapTagReplacements); +// int teams[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *teamsNode = gameSettingsNode->addChild("teams"); + teamsNode->addAttribute("team",intToStr(teams[idx]), mapTagReplacements); + } + +// int startLocationIndex[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + XmlNode *startLocationIndexNode = gameSettingsNode->addChild("startLocationIndex"); + startLocationIndexNode->addAttribute("location",intToStr(startLocationIndex[idx]), mapTagReplacements); + } + +// int mapFilterIndex; + gameSettingsNode->addAttribute("mapFilterIndex",intToStr(mapFilterIndex), mapTagReplacements); +// +// +// bool defaultUnits; + gameSettingsNode->addAttribute("defaultUnits",intToStr(defaultUnits), mapTagReplacements); +// bool defaultResources; + gameSettingsNode->addAttribute("defaultResources",intToStr(defaultResources), mapTagReplacements); +// bool defaultVictoryConditions; + gameSettingsNode->addAttribute("defaultVictoryConditions",intToStr(defaultVictoryConditions), mapTagReplacements); +// bool fogOfWar; + gameSettingsNode->addAttribute("fogOfWar",intToStr(fogOfWar), mapTagReplacements); +// bool allowObservers; + gameSettingsNode->addAttribute("allowObservers",intToStr(allowObservers), mapTagReplacements); +// bool enableObserverModeAtEndGame; + gameSettingsNode->addAttribute("enableObserverModeAtEndGame",intToStr(enableObserverModeAtEndGame), mapTagReplacements); +// bool enableServerControlledAI; + gameSettingsNode->addAttribute("enableServerControlledAI",intToStr(enableServerControlledAI), mapTagReplacements); +// int networkFramePeriod; + gameSettingsNode->addAttribute("networkFramePeriod",intToStr(networkFramePeriod), mapTagReplacements); +// bool networkPauseGameForLaggedClients; + gameSettingsNode->addAttribute("networkPauseGameForLaggedClients",intToStr(networkPauseGameForLaggedClients), mapTagReplacements); +// PathFinderType pathFinderType; + gameSettingsNode->addAttribute("pathFinderType",intToStr(pathFinderType), mapTagReplacements); +// uint32 flagTypes1; + gameSettingsNode->addAttribute("flagTypes1",intToStr(flagTypes1), mapTagReplacements); +// int32 mapCRC; + gameSettingsNode->addAttribute("mapCRC",intToStr(mapCRC), mapTagReplacements); +// int32 tilesetCRC; + gameSettingsNode->addAttribute("tilesetCRC",intToStr(tilesetCRC), mapTagReplacements); +// int32 techCRC; + gameSettingsNode->addAttribute("techCRC",intToStr(techCRC), mapTagReplacements); +// vector > factionCRCList; + for(unsigned int i = 0; i < factionCRCList.size(); ++i) { + const pair &item = factionCRCList[i]; + + XmlNode *factionCRCListNode = gameSettingsNode->addChild("factionCRCList"); + factionCRCListNode->addAttribute("key",item.first, mapTagReplacements); + factionCRCListNode->addAttribute("value",intToStr(item.second), mapTagReplacements); + } +// int aiAcceptSwitchTeamPercentChance; + gameSettingsNode->addAttribute("aiAcceptSwitchTeamPercentChance",intToStr(aiAcceptSwitchTeamPercentChance), mapTagReplacements); +// int masterserver_admin; + gameSettingsNode->addAttribute("masterserver_admin",intToStr(masterserver_admin), mapTagReplacements); + } + + void loadGame(const XmlNode *rootNode) { + const XmlNode *gameSettingsNode = rootNode->getChild("GameSettings"); + +// string description; + description = gameSettingsNode->getAttribute("description")->getValue(); +// string map; + map = gameSettingsNode->getAttribute("map")->getValue(); +// string tileset; + tileset = gameSettingsNode->getAttribute("tileset")->getValue(); +// string tech; + tech = gameSettingsNode->getAttribute("tech")->getValue(); +// string scenario; + scenario = gameSettingsNode->getAttribute("scenario")->getValue(); +// string scenarioDir; + scenarioDir = gameSettingsNode->getAttribute("scenarioDir")->getValue(); +// string factionTypeNames[GameConstants::maxPlayers]; //faction names + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *factionTypeNamesNode = gameSettingsNode->getChild("factionTypeNames",idx); + factionTypeNames[idx] = factionTypeNamesNode->getAttribute("name")->getValue(); + } + +// string networkPlayerNames[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *networkPlayerNamesNode = gameSettingsNode->getChild("networkPlayerNames",idx); + networkPlayerNames[idx] = networkPlayerNamesNode->getAttribute("name")->getValue(); + } + +// int networkPlayerStatuses[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *networkPlayerStatusesNode = gameSettingsNode->getChild("networkPlayerStatuses",idx); + networkPlayerStatuses[idx] = networkPlayerStatusesNode->getAttribute("status")->getIntValue(); + } + +// string networkPlayerLanguages[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *networkPlayerLanguagesNode = gameSettingsNode->getChild("networkPlayerLanguages",idx); + networkPlayerLanguages[idx] = networkPlayerLanguagesNode->getAttribute("name")->getValue(); + } + +// ControlType factionControls[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *factionControlsNode = gameSettingsNode->getChild("factionControls",idx); + factionControls[idx] = static_cast(factionControlsNode->getAttribute("control")->getIntValue()); + } + +// int resourceMultiplierIndex[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *resourceMultiplierIndexNode = gameSettingsNode->getChild("resourceMultiplierIndex",idx); + resourceMultiplierIndex[idx] = resourceMultiplierIndexNode->getAttribute("multiplier")->getIntValue(); + } + +// int thisFactionIndex; + thisFactionIndex = gameSettingsNode->getAttribute("thisFactionIndex")->getIntValue(); +// int factionCount; + factionCount = gameSettingsNode->getAttribute("factionCount")->getIntValue(); +// int teams[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *teamsNode = gameSettingsNode->getChild("teams",idx); + teams[idx] = teamsNode->getAttribute("team")->getIntValue(); + } + +// int startLocationIndex[GameConstants::maxPlayers]; + for(int idx =0; idx < GameConstants::maxPlayers; idx++) { + const XmlNode *startLocationIndexNode = gameSettingsNode->getChild("startLocationIndex",idx); + startLocationIndex[idx] = startLocationIndexNode->getAttribute("location")->getIntValue(); + } + +// int mapFilterIndex; + mapFilterIndex = gameSettingsNode->getAttribute("mapFilterIndex")->getIntValue(); +// +// +// bool defaultUnits; + defaultUnits = gameSettingsNode->getAttribute("defaultUnits")->getIntValue(); +// bool defaultResources; + defaultResources = gameSettingsNode->getAttribute("defaultResources")->getIntValue(); +// bool defaultVictoryConditions; + defaultVictoryConditions = gameSettingsNode->getAttribute("defaultVictoryConditions")->getIntValue(); +// bool fogOfWar; + fogOfWar = gameSettingsNode->getAttribute("fogOfWar")->getIntValue(); +// bool allowObservers; + allowObservers = gameSettingsNode->getAttribute("allowObservers")->getIntValue(); +// bool enableObserverModeAtEndGame; + enableObserverModeAtEndGame = gameSettingsNode->getAttribute("enableObserverModeAtEndGame")->getIntValue(); +// bool enableServerControlledAI; + enableServerControlledAI = gameSettingsNode->getAttribute("enableServerControlledAI")->getIntValue(); +// int networkFramePeriod; + networkFramePeriod = gameSettingsNode->getAttribute("networkFramePeriod")->getIntValue(); +// bool networkPauseGameForLaggedClients; + networkPauseGameForLaggedClients = gameSettingsNode->getAttribute("networkPauseGameForLaggedClients")->getIntValue(); +// PathFinderType pathFinderType; + pathFinderType = static_cast(gameSettingsNode->getAttribute("pathFinderType")->getIntValue()); +// uint32 flagTypes1; + flagTypes1 = gameSettingsNode->getAttribute("flagTypes1")->getIntValue(); +// int32 mapCRC; + mapCRC = gameSettingsNode->getAttribute("mapCRC")->getIntValue(); +// int32 tilesetCRC; + tilesetCRC = gameSettingsNode->getAttribute("tilesetCRC")->getIntValue(); +// int32 techCRC; + techCRC = gameSettingsNode->getAttribute("techCRC")->getIntValue(); +// vector > factionCRCList; +// for(unsigned int i = 0; i < factionCRCList.size(); ++i) { +// const pair &item = factionCRCList[i]; +// +// XmlNode *factionCRCListNode = gameSettingsNode->addChild("factionCRCList"); +// factionCRCListNode->addAttribute("key",item.first, mapTagReplacements); +// factionCRCListNode->addAttribute("value",intToStr(item.second), mapTagReplacements); +// } +// int aiAcceptSwitchTeamPercentChance; + aiAcceptSwitchTeamPercentChance = gameSettingsNode->getAttribute("aiAcceptSwitchTeamPercentChance")->getIntValue(); +// int masterserver_admin; + masterserver_admin = gameSettingsNode->getAttribute("masterserver_admin")->getIntValue(); + } + }; }}//end namespace diff --git a/source/glest_game/main/main.cpp b/source/glest_game/main/main.cpp index ba0fe93a..bfe693a0 100644 --- a/source/glest_game/main/main.cpp +++ b/source/glest_game/main/main.cpp @@ -3305,6 +3305,9 @@ int glestMain(int argc, char** argv) { else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LASTGAME])) == true) { program->initServer(mainWindow,true,false); } + else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME])) == true) { + program->initSavedGame(mainWindow,false); + } else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP])) == true) { int foundParamIndIndex = -1; hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP]) + string("="),&foundParamIndIndex); diff --git a/source/glest_game/main/program.cpp b/source/glest_game/main/program.cpp index bef6d720..7cde9854 100644 --- a/source/glest_game/main/program.cpp +++ b/source/glest_game/main/program.cpp @@ -200,6 +200,30 @@ void Program::initNormal(WindowGl *window){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } +void Program::initSavedGame(WindowGl *window,bool masterserverMode) { + MainMenu* mainMenu= NULL; + + init(window); + mainMenu= new MainMenu(this); + setState(mainMenu); + + string saveGameFile = GameConstants::saveGameFileDefault; + if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") { + saveGameFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFile; + } + else { + string userData = Config::getInstance().getString("UserData_Root",""); + if(userData != "") { + endPathWithSlash(userData); + } + saveGameFile = userData + saveGameFile; + } + + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Loading game from [%s]\n",saveGameFile.c_str()); + + Game::loadGame(saveGameFile,this,masterserverMode); +} + void Program::initServer(WindowGl *window, bool autostart,bool openNetworkSlots, bool masterserverMode) { MainMenu* mainMenu= NULL; diff --git a/source/glest_game/main/program.h b/source/glest_game/main/program.h index 3c723f0c..6c562d4e 100644 --- a/source/glest_game/main/program.h +++ b/source/glest_game/main/program.h @@ -167,6 +167,7 @@ public: void initNormal(WindowGl *window); void initServer(WindowGl *window,bool autostart=false,bool openNetworkSlots=false,bool masterserverMode=false); void initServer(WindowGl *window, GameSettings *settings); + void initSavedGame(WindowGl *window,bool masterserverMode=false); void initClient(WindowGl *window, const Ip &serverIp); void initScenario(WindowGl *window, string autoloadScenarioName); diff --git a/source/glest_game/type_instances/faction.cpp b/source/glest_game/type_instances/faction.cpp index f7b952d2..cc170fe5 100644 --- a/source/glest_game/type_instances/faction.cpp +++ b/source/glest_game/type_instances/faction.cpp @@ -382,6 +382,9 @@ Faction::Faction() { startLocationIndex=0; thisFaction=false; currentSwitchTeamVoteFactionIndex = -1; + + loadWorldNode = NULL; + techTree = NULL; } Faction::~Faction() { @@ -465,10 +468,13 @@ bool Faction::isWorkerThreadSignalCompleted(int frameIndex) { void Faction::init( FactionType *factionType, ControlType control, TechTree *techTree, Game *game, - int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources) + int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources, + const XmlNode *loadWorldNode) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + this->techTree = techTree; + this->loadWorldNode = loadWorldNode; this->control= control; this->factionType= factionType; this->startLocationIndex= startLocationIndex; @@ -481,11 +487,14 @@ void Faction::init( resources.resize(techTree->getResourceTypeCount()); store.resize(techTree->getResourceTypeCount()); - for(int i=0; igetResourceTypeCount(); ++i){ - const ResourceType *rt= techTree->getResourceType(i); - int resourceAmount= giveResources? factionType->getStartingResourceAmount(rt): 0; - resources[i].init(rt, resourceAmount); - store[i].init(rt, 0); + + if(loadWorldNode == NULL) { + for(int i=0; igetResourceTypeCount(); ++i){ + const ResourceType *rt= techTree->getResourceType(i); + int resourceAmount= giveResources? factionType->getStartingResourceAmount(rt): 0; + resources[i].init(rt, resourceAmount); + store[i].init(rt, 0); + } } texture= Renderer::getInstance().newTexture2D(rsGame); @@ -495,6 +504,10 @@ void Faction::init( texture->load(playerTexture); } + if(loadWorldNode != NULL) { + loadGame(loadWorldNode, factionIndex,game->getGameSettings(),game->getWorld()); + } + if( game->getGameSettings()->getPathFinderType() == pfBasic && Config::getInstance().getBool("EnableFactionWorkerThreads","true") == true) { if(workerThread != NULL) { @@ -520,6 +533,11 @@ const Resource *Faction::getResource(const ResourceType *rt) const{ return &resources[i]; } } + printf("ERROR cannot find resource type [%s] in list:\n",(rt != NULL ? rt->getName().c_str() : "null")); + for(int i=0; igetName().c_str()); + } + assert(false); return NULL; } @@ -530,6 +548,11 @@ int Faction::getStoreAmount(const ResourceType *rt) const{ return store[i].getAmount(); } } + printf("ERROR cannot find store type [%s] in list:\n",(rt != NULL ? rt->getName().c_str() : "null")); + for(int i=0; igetName().c_str()); + } + assert(false); return 0; } @@ -1773,6 +1796,12 @@ void Faction::saveGame(XmlNode *rootNode) { resource.saveGame(factionNode); } // Store store; + XmlNode *storeNode = factionNode->addChild("Store"); + for(unsigned int i = 0; i < store.size(); ++i) { + Resource &resource = store[i]; + resource.saveGame(storeNode); + } + // Allies allies; for(unsigned int i = 0; i < allies.size(); ++i) { Faction *ally = allies[i]; @@ -1834,4 +1863,47 @@ void Faction::saveGame(XmlNode *rootNode) { } +void Faction::loadGame(const XmlNode *rootNode, int index,GameSettings *settings,World *world) { + XmlNode *factionNode = NULL; + vector factionNodeList = rootNode->getChildList("Faction"); + for(unsigned int i = 0; i < factionNodeList.size(); ++i) { + XmlNode *node = factionNodeList[i]; + if(node->getAttribute("index")->getIntValue() == index) { + factionNode = node; + break; + } + } + + if(factionNode != NULL) { + vector unitNodeList = factionNode->getChildList("Unit"); + for(unsigned int i = 0; i < unitNodeList.size(); ++i) { + XmlNode *unitNode = unitNodeList[i]; + Unit *unit = Unit::loadGame(unitNode,settings,this, world); + this->addUnit(unit); + } + + //description = gameSettingsNode->getAttribute("description")->getValue(); + } + + //resources.resize(techTree->getResourceTypeCount()); + //store.resize(techTree->getResourceTypeCount()); + +// for(int i=0; igetResourceTypeCount(); ++i){ +// const ResourceType *rt= techTree->getResourceType(i); +// int resourceAmount= giveResources? factionType->getStartingResourceAmount(rt): 0; +// resources[i].init(rt, resourceAmount); +// store[i].init(rt, 0); +// } + + for(unsigned int i = 0; i < resources.size(); ++i) { + Resource &resource = resources[i]; + resource.loadGame(factionNode,i,techTree); + } + XmlNode *storeNode = factionNode->getChild("Store"); + for(unsigned int i = 0; i < store.size(); ++i) { + Resource &resource = store[i]; + resource.loadGame(storeNode,i,techTree); + } +} + }}//end namespace diff --git a/source/glest_game/type_instances/faction.h b/source/glest_game/type_instances/faction.h index f907825a..ea3abcd0 100644 --- a/source/glest_game/type_instances/faction.h +++ b/source/glest_game/type_instances/faction.h @@ -44,6 +44,7 @@ class Game; class ScriptManager; class World; class Faction; +class GameSettings; // ===================================================== // class Faction @@ -138,6 +139,9 @@ private: set livingUnits; set livingUnitsp; + TechTree *techTree; + const XmlNode *loadWorldNode; + public: Faction(); ~Faction(); @@ -151,7 +155,8 @@ public: void init( FactionType *factionType, ControlType control, TechTree *techTree, Game *game, - int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, bool giveResources); + int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, + bool giveResources, const XmlNode *loadWorldNode=NULL); void end(); bool getFactionDisconnectHandled() const { return factionDisconnectHandled;} @@ -257,6 +262,7 @@ public: std::string toString() const; void saveGame(XmlNode *rootNode); + void loadGame(const XmlNode *rootNode, int index,GameSettings *settings,World *world); private: void resetResourceAmount(const ResourceType *rt); diff --git a/source/glest_game/type_instances/object.cpp b/source/glest_game/type_instances/object.cpp index 31ce9b54..22670722 100644 --- a/source/glest_game/type_instances/object.cpp +++ b/source/glest_game/type_instances/object.cpp @@ -181,4 +181,36 @@ string Object::getUniquePickName() const { return result; } +void Object::saveGame(XmlNode *rootNode) { + std::map mapTagReplacements; + XmlNode *objectNode = rootNode->addChild("Object"); + +// ObjectType *objectType; + if(objectType != NULL) { + objectNode->addAttribute("objectType",intToStr(objectType->getClass()), mapTagReplacements); + } +// vector unitParticleSystems; + for(unsigned int i = 0; i < unitParticleSystems.size(); ++i) { + UnitParticleSystem *ptr= unitParticleSystems[i]; + if(ptr != NULL) { + ptr->saveGame(objectNode); + } + } +// Resource *resource; + if(resource != NULL) { + resource->saveGame(objectNode); + } +// Vec3f pos; + objectNode->addAttribute("pos",pos.getString(), mapTagReplacements); +// float rotation; + objectNode->addAttribute("rotation",floatToStr(rotation), mapTagReplacements); +// int variation; + objectNode->addAttribute("variation",intToStr(variation), mapTagReplacements); +// int lastRenderFrame; + objectNode->addAttribute("lastRenderFrame",intToStr(lastRenderFrame), mapTagReplacements); +// Vec2i mapPos; + objectNode->addAttribute("mapPos",mapPos.getString(), mapTagReplacements); +// bool visible; + objectNode->addAttribute("visible",intToStr(visible), mapTagReplacements); +} }}//end namespace diff --git a/source/glest_game/type_instances/object.h b/source/glest_game/type_instances/object.h index a0a722c9..63127abe 100644 --- a/source/glest_game/type_instances/object.h +++ b/source/glest_game/type_instances/object.h @@ -88,6 +88,7 @@ public: const Vec2i & getMapPos() const { return mapPos; } virtual string getUniquePickName() const; + void saveGame(XmlNode *rootNode); }; }}//end namespace diff --git a/source/glest_game/type_instances/resource.cpp b/source/glest_game/type_instances/resource.cpp index 7417082d..a062a20c 100644 --- a/source/glest_game/type_instances/resource.cpp +++ b/source/glest_game/type_instances/resource.cpp @@ -16,6 +16,7 @@ #include "checksum.h" #include #include "util.h" +#include "tech_tree.h" #include "leak_dumper.h" using namespace Shared::Graphics; @@ -115,4 +116,17 @@ void Resource::saveGame(XmlNode *rootNode) const { resourceNode->addAttribute("balance",intToStr(balance), mapTagReplacements); } +void Resource::loadGame(const XmlNode *rootNode, int index,TechTree *techTree) { + vector resourceNodeList = rootNode->getChildList("Resource"); + + if(index < resourceNodeList.size()) { + XmlNode *resourceNode = resourceNodeList[index]; + + amount = resourceNode->getAttribute("amount")->getIntValue(); + type = techTree->getResourceType(resourceNode->getAttribute("type")->getValue()); + pos = Vec2i::strToVec2(resourceNode->getAttribute("pos")->getValue()); + balance = resourceNode->getAttribute("balance")->getIntValue(); + } +} + }}//end namespace diff --git a/source/glest_game/type_instances/resource.h b/source/glest_game/type_instances/resource.h index 9fa41b90..ddd3ff9b 100644 --- a/source/glest_game/type_instances/resource.h +++ b/source/glest_game/type_instances/resource.h @@ -27,7 +27,7 @@ using Shared::Graphics::Vec2i; using Shared::PlatformCommon::ValueCheckerVault; class ResourceType; - +class TechTree; // ===================================================== // class Resource // @@ -59,6 +59,7 @@ public: bool decAmount(int i); void saveGame(XmlNode *rootNode) const; + void loadGame(const XmlNode *rootNode, int index,TechTree *techTree); }; }}// end namespace diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index 0b3f0c64..d938b349 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -3530,9 +3530,9 @@ void Unit::saveGame(XmlNode *rootNode) { (*it)->saveGame(unitNode); } // Observers observers; - for(Observers::iterator it = observers.begin(); it != observers.end(); ++it) { - (*it)->saveGame(unitNode); - } + //for(Observers::iterator it = observers.begin(); it != observers.end(); ++it) { + // (*it)->saveGame(unitNode); + //} // vector unitParticleSystems; for(unsigned int i = 0; i < unitParticleSystems.size(); ++i) { @@ -3651,4 +3651,44 @@ void Unit::saveGame(XmlNode *rootNode) { unitNode->addAttribute("causeOfDeath",intToStr(causeOfDeath), mapTagReplacements); } +Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *faction, World *world) { + const XmlNode *unitNode = rootNode; + + int newUnitId = unitNode->getAttribute("id")->getIntValue(); + Vec2i newUnitPos = Vec2i::strToVec2(unitNode->getAttribute("pos")->getValue()); + string newUnitType = unitNode->getAttribute("type")->getValue(); + const UnitType *ut = faction->getType()->getUnitType(newUnitType); + CardinalDir newModelFacing = static_cast(unitNode->getAttribute("modelFacing")->getIntValue()); + +// Unit *result = new Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos, +// const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing) : BaseColorPickEntity(), id(id) { + + UnitPathInterface *newpath = NULL; + switch(settings->getPathFinderType()) { + case pfBasic: + newpath = new UnitPathBasic(); + break; + case pfRoutePlanner: + newpath = new UnitPath(); + break; + default: + throw runtime_error("detected unsupported pathfinder type!"); + } + + //Unit *result = new Unit(getNextUnitId(f), newpath, Vec2i(0), ut, f, &map, CardinalDir::NORTH); + //Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); + Unit *result = new Unit(newUnitId, newpath, newUnitPos, ut, faction, world->getMapPtr(), newModelFacing); + + result->lastRotation = unitNode->getAttribute("lastRotation")->getFloatValue(); + result->targetRotation = unitNode->getAttribute("targetRotation")->getFloatValue(); + result->rotation = unitNode->getAttribute("rotation")->getFloatValue(); + + //world->placeUnitAtLocation(newUnitPos, generationArea, unit, true); + result->setPos(newUnitPos); + Vec2i meetingPos = newUnitPos-Vec2i(1); + result->setMeetingPos(meetingPos); + + return result; +} + }}//end namespace diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index b24570e0..ff3ff694 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -49,6 +49,8 @@ class Level; class MorphCommandType; class Game; class Unit; +class GameSettings; +class World; enum CommandResult { crSuccess, @@ -641,6 +643,7 @@ public: virtual string getUniquePickName() const; void saveGame(XmlNode *rootNode); + static Unit * loadGame(const XmlNode *rootNode,GameSettings *settings,Faction *faction, World *world); private: float computeHeight(const Vec2i &pos) const; diff --git a/source/glest_game/types/tech_tree.cpp b/source/glest_game/types/tech_tree.cpp index 5c5b1308..be5496f3 100644 --- a/source/glest_game/types/tech_tree.cpp +++ b/source/glest_game/types/tech_tree.cpp @@ -378,37 +378,37 @@ void TechTree::saveGame(XmlNode *rootNode) { techTreeNode->addAttribute("name",name, mapTagReplacements); // //string desc; // string treePath; - techTreeNode->addAttribute("treePath",treePath, mapTagReplacements); + //techTreeNode->addAttribute("treePath",treePath, mapTagReplacements); // vector pathList; - for(unsigned int i = 0; i < pathList.size(); ++i) { - XmlNode *pathListNode = techTreeNode->addChild("pathList"); - pathListNode->addAttribute("value",pathList[i], mapTagReplacements); - } +// for(unsigned int i = 0; i < pathList.size(); ++i) { +// XmlNode *pathListNode = techTreeNode->addChild("pathList"); +// pathListNode->addAttribute("value",pathList[i], mapTagReplacements); +// } // ResourceTypes resourceTypes; - for(unsigned int i = 0; i < resourceTypes.size(); ++i) { - ResourceType &rt = resourceTypes[i]; - rt.saveGame(techTreeNode); - } +// for(unsigned int i = 0; i < resourceTypes.size(); ++i) { +// ResourceType &rt = resourceTypes[i]; +// rt.saveGame(techTreeNode); +// } // FactionTypes factionTypes; - for(unsigned int i = 0; i < factionTypes.size(); ++i) { - FactionType &ft = factionTypes[i]; - ft.saveGame(techTreeNode); - } +// for(unsigned int i = 0; i < factionTypes.size(); ++i) { +// FactionType &ft = factionTypes[i]; +// ft.saveGame(techTreeNode); +// } // ArmorTypes armorTypes; - for(unsigned int i = 0; i < armorTypes.size(); ++i) { - ArmorType &at = armorTypes[i]; - at.saveGame(techTreeNode); - } +// for(unsigned int i = 0; i < armorTypes.size(); ++i) { +// ArmorType &at = armorTypes[i]; +// at.saveGame(techTreeNode); +// } // AttackTypes attackTypes; - for(unsigned int i = 0; i < attackTypes.size(); ++i) { - AttackType &at = attackTypes[i]; - at.saveGame(techTreeNode); - } +// for(unsigned int i = 0; i < attackTypes.size(); ++i) { +// AttackType &at = attackTypes[i]; +// at.saveGame(techTreeNode); +// } // DamageMultiplierTable damageMultiplierTable; - damageMultiplierTable.saveGame(techTreeNode); +// damageMultiplierTable.saveGame(techTreeNode); // Checksum checksumValue; techTreeNode->addAttribute("checksumValue",intToStr(checksumValue.getSum()), mapTagReplacements); diff --git a/source/glest_game/world/map.cpp b/source/glest_game/world/map.cpp index c7a12ad4..14420290 100644 --- a/source/glest_game/world/map.cpp +++ b/source/glest_game/world/map.cpp @@ -26,8 +26,10 @@ #include "pos_iterator.h" #include "faction.h" #include "command.h" -#include "leak_dumper.h" #include "map_preview.h" +#include "world.h" + +#include "leak_dumper.h" using namespace Shared::Graphics; using namespace Shared::Util; @@ -76,6 +78,70 @@ bool Cell::isFreeOrMightBeFreeSoon(Vec2i originPos, Vec2i cellPos, Field field) return result; } +void Cell::saveGame(XmlNode *rootNode, int index) const { + bool saveCell = false; + if(saveCell == false) { + for(unsigned int i = 0; i < fieldCount; ++i) { + if(units[i] != NULL) { + saveCell = true; + break; + } + if(unitsWithEmptyCellMap[i] != NULL) { + saveCell = true; + break; + } + } + } + + if(saveCell == true) { + std::map mapTagReplacements; + XmlNode *cellNode = rootNode->addChild("Cell" + intToStr(index)); + cellNode->addAttribute("index",intToStr(index), mapTagReplacements); + + // Unit *units[fieldCount]; //units on this cell + for(unsigned int i = 0; i < fieldCount; ++i) { + if(units[i] != NULL) { + XmlNode *unitsNode = cellNode->addChild("units"); + unitsNode->addAttribute("field",intToStr(i), mapTagReplacements); + unitsNode->addAttribute("unitid",intToStr(units[i]->getId()), mapTagReplacements); + } + } + // Unit *unitsWithEmptyCellMap[fieldCount]; //units with an empty cellmap on this cell + for(unsigned int i = 0; i < fieldCount; ++i) { + if(unitsWithEmptyCellMap[i] != NULL) { + XmlNode *unitsWithEmptyCellMapNode = cellNode->addChild("unitsWithEmptyCellMap"); + unitsWithEmptyCellMapNode->addAttribute("field",intToStr(i), mapTagReplacements); + unitsWithEmptyCellMapNode->addAttribute("unitid",intToStr(unitsWithEmptyCellMap[i]->getId()), mapTagReplacements); + } + } + + // float height; + cellNode->addAttribute("height",floatToStr(height), mapTagReplacements); + } +} + +void Cell::loadGame(const XmlNode *rootNode, int index, World *world) { + if(rootNode->hasChild("Cell" + intToStr(index)) == true) { + const XmlNode *cellNode = rootNode->getChild("Cell" + intToStr(index)); + + int unitCount = cellNode->getChildCount(); + for(unsigned int i = 0; i < unitCount; ++i) { + if(cellNode->hasChildAtIndex("units",i) == true) { + const XmlNode *unitsNode = cellNode->getChild("units",i); + int field = unitsNode->getAttribute("field")->getIntValue(); + int unitId = unitsNode->getAttribute("unitid")->getIntValue(); + units[field] = world->findUnitById(unitId); + } + if(cellNode->hasChildAtIndex("unitsWithEmptyCellMap",i) == true) { + const XmlNode *unitsNode = cellNode->getChild("unitsWithEmptyCellMap",i); + int field = unitsNode->getAttribute("field")->getIntValue(); + int unitId = unitsNode->getAttribute("unitid")->getIntValue(); + unitsWithEmptyCellMap[field] = world->findUnitById(unitId); + } + } + } +} + // ===================================================== // class SurfaceCell // ===================================================== @@ -127,6 +193,95 @@ void SurfaceCell::setVisible(int teamIndex, bool visible) { this->visible[teamIndex]= visible; } +void SurfaceCell::saveGame(XmlNode *rootNode,int index) const { + bool saveCell = (object != NULL); + if(saveCell == false) { + for(unsigned int i = 0; i < GameConstants::maxPlayers; ++i) { + if(visible[i] == true || explored[i] == true) { + saveCell = true; + } + } + } + + if(saveCell == true) { + std::map mapTagReplacements; + XmlNode *surfaceCellNode = rootNode->addChild("SurfaceCell" + intToStr(index)); + surfaceCellNode->addAttribute("index",intToStr(index), mapTagReplacements); + + // //geometry + // Vec3f vertex; + //surfaceCellNode->addAttribute("vertex",vertex.getString(), mapTagReplacements); + // Vec3f normal; + //surfaceCellNode->addAttribute("normal",normal.getString(), mapTagReplacements); + // Vec3f color; + //surfaceCellNode->addAttribute("color",color.getString(), mapTagReplacements); + // + // //tex coords + // Vec2f fowTexCoord; //tex coords for TEXTURE1 when multitexturing and fogOfWar + //surfaceCellNode->addAttribute("fowTexCoord",fowTexCoord.getString(), mapTagReplacements); + // Vec2f surfTexCoord; //tex coords for TEXTURE0 + //surfaceCellNode->addAttribute("surfTexCoord",surfTexCoord.getString(), mapTagReplacements); + // //surface + // int surfaceType; + //surfaceCellNode->addAttribute("surfaceType",intToStr(surfaceType), mapTagReplacements); + // const Texture2D *surfaceTexture; + // + // //object & resource + // Object *object; + if(object != NULL) { + object->saveGame(surfaceCellNode); + } + // //visibility + // bool visible[GameConstants::maxPlayers + GameConstants::specialFactions]; + for(unsigned int i = 0; i < GameConstants::maxPlayers; ++i) { + if(visible[i] == true) { + XmlNode *visibleNode = surfaceCellNode->addChild("visible"); + visibleNode->addAttribute("index",intToStr(i), mapTagReplacements); + visibleNode->addAttribute("value",intToStr(visible[i]), mapTagReplacements); + } + } + // bool explored[GameConstants::maxPlayers + GameConstants::specialFactions]; + for(unsigned int i = 0; i < GameConstants::maxPlayers; ++i) { + if(explored[i] == true) { + XmlNode *exploredNode = surfaceCellNode->addChild("explored"); + exploredNode->addAttribute("index",intToStr(i), mapTagReplacements); + exploredNode->addAttribute("value",intToStr(explored[i]), mapTagReplacements); + } + } + + // //cache + // bool nearSubmerged; + //surfaceCellNode->addAttribute("nearSubmerged",intToStr(nearSubmerged), mapTagReplacements); + } +} + +void SurfaceCell::loadGame(const XmlNode *rootNode, int index, World *world) { + if(rootNode->hasChild("SurfaceCell" + intToStr(index)) == true) { + const XmlNode *cellNode = rootNode->getChild("SurfaceCell" + intToStr(index)); + int visibleCount = cellNode->getChildCount(); + + //printf("Loading game, sc index [%d][%d]\n",index,visibleCount); + + for(unsigned int i = 0; i < visibleCount; ++i) { + if(cellNode->hasChildAtIndex("visible",i) == true) { + const XmlNode *visibleNode = cellNode->getChild("visible",i); + int indexCell = visibleNode->getAttribute("index")->getIntValue(); + bool value = visibleNode->getAttribute("value")->getIntValue(); + visible[indexCell] = value; + + //printf("Loading game, sc visible index [%d][%d][%d]\n",index,indexCell,value); + } + if(cellNode->hasChildAtIndex("explored",i) == true) { + const XmlNode *exploredNode = cellNode->getChild("explored",i); + int indexCell = exploredNode->getAttribute("index")->getIntValue(); + bool value = exploredNode->getAttribute("value")->getIntValue(); + explored[indexCell] = value; + + //printf("Loading game, sc explored index [%d][%d][%d]\n",index,indexCell,value); + } + } + } +} // ===================================================== // class Map // ===================================================== @@ -1649,6 +1804,84 @@ string Map::getMapPath(const string &mapName, string scenarioDir, bool errorOnNo return ""; } +void Map::saveGame(XmlNode *rootNode) const { + std::map mapTagReplacements; + XmlNode *mapNode = rootNode->addChild("Map"); + +// string title; + mapNode->addAttribute("title",title, mapTagReplacements); +// float waterLevel; + mapNode->addAttribute("waterLevel",floatToStr(waterLevel), mapTagReplacements); +// float heightFactor; + mapNode->addAttribute("heightFactor",floatToStr(heightFactor), mapTagReplacements); +// float cliffLevel; + mapNode->addAttribute("cliffLevel",floatToStr(cliffLevel), mapTagReplacements); +// int cameraHeight; + mapNode->addAttribute("cameraHeight",intToStr(cameraHeight), mapTagReplacements); +// int w; + mapNode->addAttribute("w",intToStr(w), mapTagReplacements); +// int h; + mapNode->addAttribute("h",intToStr(h), mapTagReplacements); +// int surfaceW; + mapNode->addAttribute("surfaceW",intToStr(surfaceW), mapTagReplacements); +// int surfaceH; + mapNode->addAttribute("surfaceH",intToStr(surfaceH), mapTagReplacements); +// int maxPlayers; + mapNode->addAttribute("maxPlayers",intToStr(maxPlayers), mapTagReplacements); +// Cell *cells; + //printf("getCellArraySize() = %d\n",getCellArraySize()); + for(unsigned int i = 0; i < getCellArraySize(); ++i) { + Cell &cell = cells[i]; + cell.saveGame(mapNode,i); + } +// SurfaceCell *surfaceCells; + //printf("getSurfaceCellArraySize() = %d\n",getSurfaceCellArraySize()); + for(unsigned int i = 0; i < getSurfaceCellArraySize(); ++i) { + SurfaceCell &surfaceCell = surfaceCells[i]; + surfaceCell.saveGame(mapNode,i); + } + +// Vec2i *startLocations; + for(unsigned int i = 0; i < maxPlayers; ++i) { + XmlNode *startLocationsNode = mapNode->addChild("startLocations"); + startLocationsNode->addAttribute("location",startLocations[i].getString(), mapTagReplacements); + } +// Checksum checksumValue; +// mapNode->addAttribute("checksumValue",intToStr(checksumValue.getSum()), mapTagReplacements); +// float maxMapHeight; + mapNode->addAttribute("maxMapHeight",floatToStr(maxMapHeight), mapTagReplacements); +// string mapFile; + mapNode->addAttribute("mapFile",mapFile, mapTagReplacements); +} + +void Map::loadGame(const XmlNode *rootNode, World *world) { + const XmlNode *mapNode = rootNode->getChild("World")->getChild("Map"); + + //description = gameSettingsNode->getAttribute("description")->getValue(); + +// for(unsigned int i = 0; i < getCellArraySize(); ++i) { +// Cell &cell = cells[i]; +// cell.saveGame(mapNode,i); +// } +// for(unsigned int i = 0; i < getSurfaceCellArraySize(); ++i) { +// SurfaceCell &surfaceCell = surfaceCells[i]; +// surfaceCell.saveGame(mapNode,i); +// } + + printf("getCellArraySize() = %d\n",getCellArraySize()); + for(unsigned int i = 0; i < getCellArraySize(); ++i) { + Cell &cell = cells[i]; + cell.loadGame(mapNode,i,world); + } + + printf("getSurfaceCellArraySize() = %d\n",getSurfaceCellArraySize()); + for(unsigned int i = 0; i < getSurfaceCellArraySize(); ++i) { + SurfaceCell &surfaceCell = surfaceCells[i]; + surfaceCell.loadGame(mapNode,i,world); + } + +} + // ===================================================== // class PosCircularIterator // ===================================================== diff --git a/source/glest_game/world/map.h b/source/glest_game/world/map.h index fa976844..a78b225b 100644 --- a/source/glest_game/world/map.h +++ b/source/glest_game/world/map.h @@ -38,7 +38,7 @@ class Unit; class Resource; class TechTree; class GameSettings; - +class World; // ===================================================== // class Cell // @@ -70,6 +70,9 @@ public: bool isFree(Field field) const; bool isFreeOrMightBeFreeSoon(Vec2i originPos, Vec2i cellPos, Field field) const; + + void saveGame(XmlNode *rootNode,int index) const; + void loadGame(const XmlNode *rootNode, int index, World *world); }; // ===================================================== @@ -141,6 +144,9 @@ public: //misc void deleteResource(); bool isFree() const; + + void saveGame(XmlNode *rootNode,int index) const; + void loadGame(const XmlNode *rootNode, int index, World *world); }; @@ -266,6 +272,9 @@ public: string getMapFile() const { return mapFile; } + void saveGame(XmlNode *rootNode) const; + void loadGame(const XmlNode *rootNode,World *world); + private: //compute void smoothSurface(Tileset *tileset); diff --git a/source/glest_game/world/time_flow.cpp b/source/glest_game/world/time_flow.cpp index dd312f83..41b62d61 100644 --- a/source/glest_game/world/time_flow.cpp +++ b/source/glest_game/world/time_flow.cpp @@ -134,11 +134,20 @@ void TimeFlow::saveGame(XmlNode *rootNode) { // bool firstTime; // Tileset *tileset; // float time; - timeflowNode->addAttribute("time",intToStr(time), mapTagReplacements); + timeflowNode->addAttribute("time",floatToStr(time), mapTagReplacements); // float lastTime; - timeflowNode->addAttribute("lastTime",intToStr(lastTime), mapTagReplacements); + timeflowNode->addAttribute("lastTime",floatToStr(lastTime), mapTagReplacements); // float timeInc; - timeflowNode->addAttribute("timeInc",intToStr(timeInc), mapTagReplacements); + timeflowNode->addAttribute("timeInc",floatToStr(timeInc), mapTagReplacements); +} + +void TimeFlow::loadGame(const XmlNode *rootNode) { + const XmlNode *timeflowNode = rootNode->getChild("TimeFlow"); + + firstTime = timeflowNode->getAttribute("firstTime")->getFloatValue(); + time = timeflowNode->getAttribute("time")->getIntValue(); + lastTime = timeflowNode->getAttribute("lastTime")->getFloatValue(); + timeInc = timeflowNode->getAttribute("timeInc")->getFloatValue(); } }}//end namespace diff --git a/source/glest_game/world/time_flow.h b/source/glest_game/world/time_flow.h index 2ed3d699..8d166daa 100644 --- a/source/glest_game/world/time_flow.h +++ b/source/glest_game/world/time_flow.h @@ -61,6 +61,7 @@ public: void update(); void saveGame(XmlNode *rootNode); + void loadGame(const XmlNode *rootNode); private: //bool isAproxTime(float time) const; diff --git a/source/glest_game/world/world.cpp b/source/glest_game/world/world.cpp index 7533aa72..c33762c1 100644 --- a/source/glest_game/world/world.cpp +++ b/source/glest_game/world/world.cpp @@ -82,6 +82,8 @@ World::World(){ queuedScenarioName=""; queuedScenarioKeepFactions=false; + loadWorldNode = NULL; + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -228,6 +230,10 @@ void World::init(Game *game, bool createUnits, bool initFactions){ fogOfWar = gs->getFogOfWar(); } + if(loadWorldNode != NULL) { + timeFlow.loadGame(loadWorldNode); + } + if(initFactions == true) { initFactionTypes(gs); } @@ -1311,7 +1317,8 @@ void World::initFactionTypes(GameSettings *gs) { throw runtime_error("ft == NULL"); } factions[i]->init(ft, gs->getFactionControl(i), techTree, game, i, gs->getTeam(i), - gs->getStartLocationIndex(i), i==thisFactionIndex, gs->getDefaultResources()); + gs->getStartLocationIndex(i), i==thisFactionIndex, + gs->getDefaultResources(),loadWorldNode); stats.setTeam(i, gs->getTeam(i)); stats.setFactionTypeName(i, formatString(gs->getFactionTypeName(i))); @@ -1385,60 +1392,87 @@ void World::initUnitsForScenario() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } +void World::placeUnitAtLocation(const Vec2i &location, int radius, Unit *unit, bool spaciated) { + if(placeUnit(location, generationArea, unit, spaciated)) { + unit->create(true); + unit->born(); + } + else { + string unitName = unit->getType()->getName(); + delete unit; + unit = NULL; + + char szBuf[4096]=""; + sprintf(szBuf,"Unit: [%s] can't be placed, this error is caused because there\nis not enough room to put all units near their start location.\nmake a better/larger map. Faction: #%d name: [%s]", + unitName.c_str(),unit->getFactionIndex(),unit->getFaction()->getType()->getName().c_str()); + throw runtime_error(szBuf); + } + if (unit->getType()->hasSkillClass(scBeBuilt)) { + map.flatternTerrain(unit); + if(cartographer != NULL) { + cartographer->updateMapMetrics(unit->getPos(), unit->getType()->getSize()); + } + } + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); + +} + //place units randomly aroud start location void World::initUnits() { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); Logger::getInstance().add(Lang::getInstance().get("LogScreenGameLoadingGenerateGameElements","",true), true); //put starting units - for(int i = 0; i < getFactionCount(); ++i) { - Faction *f= factions[i]; - const FactionType *ft= f->getType(); + if(loadWorldNode == NULL) { + for(int i = 0; i < getFactionCount(); ++i) { + Faction *f= factions[i]; + const FactionType *ft= f->getType(); + for(int j = 0; j < ft->getStartingUnitCount(); ++j) { + const UnitType *ut= ft->getStartingUnit(j); + int initNumber= ft->getStartingUnitAmount(j); - for(int j = 0; j < ft->getStartingUnitCount(); ++j) { - const UnitType *ut= ft->getStartingUnit(j); - int initNumber= ft->getStartingUnitAmount(j); + for(int l = 0; l < initNumber; l++) { - for(int l = 0; l < initNumber; l++) { - - UnitPathInterface *newpath = NULL; - switch(game->getGameSettings()->getPathFinderType()) { - case pfBasic: - newpath = new UnitPathBasic(); - break; - case pfRoutePlanner: - newpath = new UnitPath(); - break; - default: - throw runtime_error("detected unsupported pathfinder type!"); - } - - Unit *unit= new Unit(getNextUnitId(f), newpath, Vec2i(0), ut, f, &map, CardinalDir::NORTH); - - int startLocationIndex= f->getStartLocationIndex(); - - if(placeUnit(map.getStartLocation(startLocationIndex), generationArea, unit, true)) { - unit->create(true); - unit->born(); - } - else { - string unitName = unit->getType()->getName(); - delete unit; - unit = NULL; - throw runtime_error("Unit: " + unitName + " can't be placed, this error is caused because there\nis not enough room to put all units near their start location.\nmake a better/larger map. Faction: #" + intToStr(i) + " name: " + ft->getName()); - } - if (unit->getType()->hasSkillClass(scBeBuilt)) { - map.flatternTerrain(unit); - if(cartographer != NULL) { - cartographer->updateMapMetrics(unit->getPos(), unit->getType()->getSize()); + UnitPathInterface *newpath = NULL; + switch(game->getGameSettings()->getPathFinderType()) { + case pfBasic: + newpath = new UnitPathBasic(); + break; + case pfRoutePlanner: + newpath = new UnitPath(); + break; + default: + throw runtime_error("detected unsupported pathfinder type!"); } - } - if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); - } - } - // Ensure Starting Resource Amount are adjusted to max store levels - f->limitResourcesToStore(); + Unit *unit= new Unit(getNextUnitId(f), newpath, Vec2i(0), ut, f, &map, CardinalDir::NORTH); + + int startLocationIndex= f->getStartLocationIndex(); + + // if(placeUnit(map.getStartLocation(startLocationIndex), generationArea, unit, true)) { + // unit->create(true); + // unit->born(); + // } + // else { + // string unitName = unit->getType()->getName(); + // delete unit; + // unit = NULL; + // throw runtime_error("Unit: " + unitName + " can't be placed, this error is caused because there\nis not enough room to put all units near their start location.\nmake a better/larger map. Faction: #" + intToStr(i) + " name: " + ft->getName()); + // } + // if (unit->getType()->hasSkillClass(scBeBuilt)) { + // map.flatternTerrain(unit); + // if(cartographer != NULL) { + // cartographer->updateMapMetrics(unit->getPos(), unit->getType()->getSize()); + // } + // } + placeUnitAtLocation(map.getStartLocation(startLocationIndex), generationArea, unit, true); + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit created for unit [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); + } + } + + // Ensure Starting Resource Amount are adjusted to max store levels + f->limitResourcesToStore(); + } } map.computeNormals(); map.computeInterpolatedHeights(); @@ -1999,7 +2033,7 @@ void World::saveGame(XmlNode *rootNode) { XmlNode *worldNode = rootNode->addChild("World"); // Map map; - worldNode->addAttribute("map",extractFileFromDirectoryPath(map.getMapFile()), mapTagReplacements); + //map.saveGame(worldNode); // Tileset tileset; worldNode->addAttribute("tileset",tileset.getName(), mapTagReplacements); // //TechTree techTree; @@ -2074,4 +2108,8 @@ void World::saveGame(XmlNode *rootNode) { worldNode->addAttribute("queuedScenarioKeepFactions",intToStr(queuedScenarioKeepFactions), mapTagReplacements); } +void World::loadGame(const XmlNode *rootNode) { + loadWorldNode = rootNode; +} + }}//end namespace diff --git a/source/glest_game/world/world.h b/source/glest_game/world/world.h index 33fb8285..f91c8a33 100644 --- a/source/glest_game/world/world.h +++ b/source/glest_game/world/world.h @@ -146,6 +146,8 @@ private: string queuedScenarioName; bool queuedScenarioKeepFactions; + const XmlNode *loadWorldNode; + public: World(); ~World(); @@ -267,7 +269,9 @@ public: string getFowAlphaCellsLookupItemCacheStats(); string getAllFactionsCacheStats(); + void placeUnitAtLocation(const Vec2i &location, int radius, Unit *unit, bool spaciated); void saveGame(XmlNode *rootNode); + void loadGame(const XmlNode *rootNode); private: diff --git a/source/shared_lib/include/graphics/vec.h b/source/shared_lib/include/graphics/vec.h index cecd3e97..02b4930e 100644 --- a/source/shared_lib/include/graphics/vec.h +++ b/source/shared_lib/include/graphics/vec.h @@ -16,10 +16,48 @@ #include "math_wrapper.h" #include #include +#include +#include +#include +#include #include "leak_dumper.h" namespace Shared{ namespace Graphics{ +inline std::vector TokenizeString(const std::string str,const std::string delimiters) { + std::vector tokens; + // Assume textLine contains the line of text to parse. + std::string textLine = str; + + std::size_t pos = 0; + while( true ) { + std::size_t nextPos = textLine.find( delimiters, pos ); + if( nextPos == textLine.npos ) { + tokens.push_back(textLine.substr(pos, textLine.length( ))); + break; + } + tokens.push_back( std::string( textLine.substr( pos, nextPos - pos ) ) ); + pos = nextPos + 1; + } + + return tokens; +} + +template +inline T strToType(const std::string &s) { + char *endChar=NULL; + + setlocale(LC_NUMERIC, "C"); + T value= static_cast(strtod(s.c_str(), &endChar)); + + if(*endChar!='\0'){ + throw std::runtime_error("Error converting from string to type, found: [" + s + "]"); + } + + return value; +} + + template class Vec2; template class Vec3; template class Vec4; @@ -179,6 +217,35 @@ public: streamOut << "] y [" << y << "]"; std::string result = streamOut.str(); streamOut.str(std::string()); + return result; + } + // meetingPos="x [32] y [120]" + static inline Vec2 strToVec2(std::string value) { + Vec2 result; + + std::vector tokens = TokenizeString(value,"["); + //for(unsigned int i = 0; i < tokens.size(); ++i) { + //printf("#1 Vec2T i = %d [%s]\n",i,tokens[i].c_str()); + //} + if(tokens.size() == 3) { + std::vector tokens2 = TokenizeString(tokens[1],"]"); + //for(unsigned int i = 0; i < tokens2.size(); ++i) { + //printf("#2 Vec2T i = %d [%s]\n",i,tokens2[i].c_str()); + //} + std::vector tokens3 = TokenizeString(tokens[2],"]"); + //for(unsigned int i = 0; i < tokens3.size(); ++i) { + //printf("#3 Vec2T i = %d [%s]\n",i,tokens3[i].c_str()); + //} + + if(tokens2.size() == 2 && tokens3.size() == 2) { + result.x = (T)strToType(tokens2[0]); + result.y = (T)strToType(tokens3[0]); + + //printf("#3 Vec2T [%s]\n",result.getString().c_str()); + } + } + + return result; } }; diff --git a/source/shared_lib/include/platform/sdl/platform_main.h b/source/shared_lib/include/platform/sdl/platform_main.h index 37586caf..abe23e48 100644 --- a/source/shared_lib/include/platform/sdl/platform_main.h +++ b/source/shared_lib/include/platform/sdl/platform_main.h @@ -26,6 +26,7 @@ const char *GAME_ARGS[] = { "--help", "--autostart-lastgame", + "--load-saved-game", "--connecthost", "--starthost", "--headless-server-mode", @@ -76,6 +77,7 @@ enum GAME_ARG_TYPE { GAME_ARG_HELP = 0, GAME_ARG_AUTOSTART_LASTGAME, + GAME_ARG_AUTOSTART_LAST_SAVED_GAME, GAME_ARG_CLIENT, GAME_ARG_SERVER, GAME_ARG_MASTERSERVER_MODE, @@ -135,8 +137,12 @@ void printParameterHelp(const char *argv0, bool foundInvalidArgs) { printf("Commandline Parameter:\t\tDescription:"); printf("\n----------------------\t\t------------"); printf("\n%s\t\t\t\tdisplays this help text.",GAME_ARGS[GAME_ARG_HELP]); + printf("\n%s\t\tAutomatically starts a game with the last game",GAME_ARGS[GAME_ARG_AUTOSTART_LASTGAME]); printf("\n\t\t\t\tsettings you played."); + + printf("\n%s\t\tLoads the last saved game.",GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME]); + printf("\n%s=x\t\t\tAuto connect to host server at IP or hostname x",GAME_ARGS[GAME_ARG_CLIENT]); printf("\n%s\t\t\tAuto create a host server.",GAME_ARGS[GAME_ARG_SERVER]); @@ -377,7 +383,7 @@ int mainSetup(int argc, char **argv) { if(knownArgCount != GAME_ARG_END) { char szBuf[1024]=""; sprintf(szBuf,"Internal arg count mismatch knownArgCount = %d, GAME_ARG_END = %d",knownArgCount,GAME_ARG_END); - throw runtime_error(""); + throw runtime_error(szBuf); } if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true || diff --git a/source/shared_lib/include/xml/xml_parser.h b/source/shared_lib/include/xml/xml_parser.h index 9f68d121..82a201bf 100644 --- a/source/shared_lib/include/xml/xml_parser.h +++ b/source/shared_lib/include/xml/xml_parser.h @@ -55,7 +55,7 @@ public: ~XmlIo(); void cleanup(); - XmlNode *load(const string &path, std::map mapTagReplacementValues); + XmlNode *load(const string &path, std::map mapTagReplacementValues,bool noValidation=false); void save(const string &path, const XmlNode *node); }; @@ -76,7 +76,7 @@ public: ~XmlTree(); void init(const string &name); - void load(const string &path, std::map mapTagReplacementValues); + void load(const string &path, std::map mapTagReplacementValues, bool noValidation=false); void save(const string &path); XmlNode *getRootNode() const {return rootNode;} diff --git a/source/shared_lib/sources/xml/xml_parser.cpp b/source/shared_lib/sources/xml/xml_parser.cpp index 3b733b07..f81fd339 100644 --- a/source/shared_lib/sources/xml/xml_parser.cpp +++ b/source/shared_lib/sources/xml/xml_parser.cpp @@ -103,22 +103,52 @@ XmlIo::~XmlIo() { cleanup(); } -XmlNode *XmlIo::load(const string &path, std::map mapTagReplacementValues) { +XmlNode *XmlIo::load(const string &path, std::map mapTagReplacementValues,bool noValidation) { + + try { + if(SystemFlags::VERBOSE_MODE_ENABLED) printf("XERCES_FULLVERSIONDOT [%s]\nnoValidation = %d\npath [%s]\n",XERCES_FULLVERSIONDOT,noValidation,path.c_str()); - try{ ErrorHandler errorHandler; #if XERCES_VERSION_MAJOR < 3 DOMBuilder *parser= (static_cast(implementation))->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0); parser->setErrorHandler(&errorHandler); - parser->setFeature(XMLUni::fgXercesSchema, true); - parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); - parser->setFeature(XMLUni::fgDOMValidation, true); + if(noValidation == false) { + parser->setFeature(XMLUni::fgXercesSchema, true); + parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true); + //parser->setFeature(XMLUni::fgDOMValidateIfSchema, true); + parser->setFeature(XMLUni::fgDOMValidation, true); + } + else { + //parser->setFeature(XMLUni::fgSAX2CoreValidation, false); + //parser->setFeature(XMLUni::fgXercesDynamic, true); + + //parser->setFeature(XMLUni::fgXercesSchema, false); + //parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false); + //parser->setFeature(XMLUni::fgDOMValidateIfSchema, true); + //parser->setFeature(XMLUni::fgDOMValidation, false); + + parser->setFeature(XMLUni::fgXercesSchemaFullChecking, false); + parser->setFeature(XMLUni::fgXercesLoadExternalDTD, false); + parser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true); + parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true); + } #else DOMLSParser *parser = (static_cast(implementation))->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, 0); DOMConfiguration *config = parser->getDomConfig(); - config->setParameter(XMLUni::fgXercesSchema, true); - config->setParameter(XMLUni::fgXercesSchemaFullChecking, true); - config->setParameter(XMLUni::fgDOMValidate, true); + if(noValidation == false) { + config->setParameter(XMLUni::fgXercesSchema, true); + config->setParameter(XMLUni::fgXercesSchemaFullChecking, true); + //config->setParameter(XMLUni::fgDOMValidateIfSchema, true); + config->setParameter(XMLUni::fgDOMValidate, true); + } + else { + config->setParameter(XMLUni::fgXercesSchema, false); + config->setParameter(XMLUni::fgXercesSchemaFullChecking, false); + //config->setParameter(XMLUni::fgDOMValidateIfSchema, true); + config->setParameter(XMLUni::fgDOMValidate, false); + config->setParameter(XMLUni::fgSAX2CoreValidation, true); + config->setParameter(XMLUni::fgXercesDynamic, true); + } #endif XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *document= parser->parseURI(path.c_str()); #ifdef WIN32 @@ -200,7 +230,7 @@ typedef std::vector LoadStack; //static LoadStack loadStack; static string loadStackCacheName = string(__FILE__) + string("_loadStackCacheName"); -void XmlTree::load(const string &path, std::map mapTagReplacementValues) { +void XmlTree::load(const string &path, std::map mapTagReplacementValues, bool noValidation) { if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] about to load [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str()); //printf("XmlTree::load p [%p]\n",this); @@ -219,7 +249,7 @@ void XmlTree::load(const string &path, std::map mapTagReplacement safeMutex.ReleaseLock(); loadPath = path; - this->rootNode= XmlIo::getInstance().load(path, mapTagReplacementValues); + this->rootNode= XmlIo::getInstance().load(path, mapTagReplacementValues, noValidation); if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] about to load [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str()); }