# HG changeset patch # User Bradley Arsenault # Date 1177626584 14400 # Node ID ddbedd4025c4ace6cb838174164a1a49e181ec86 # Parent b371d8df4dc99047cd7b06583d397af3ccc06d38 New MapHeader & GameHeader based backend is started. diff -r b371d8df4dc9 -r ddbedd4025c4 src/AICastor.cpp --- a/src/AICastor.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/AICastor.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -1115,7 +1115,7 @@ Order *AICastor::controlStrikes() if (!strikeTeamSelected) { int bestLevel=-1; - for (int ti=0; tisession.numberOfTeam; ti++) + for (int ti=0; timapHeader.getNumberOfTeams(); ti++) { Team *enemyTeam=game->teams[ti]; Uint32 me=team->me; @@ -1134,7 +1134,7 @@ Order *AICastor::controlStrikes() } int bestTeam=0; int bestScore=-1; - for (int ti=0; tisession.numberOfTeam; ti++) + for (int ti=0; timapHeader.getNumberOfTeams(); ti++) { int score=0; Team *enemyTeam=game->teams[ti]; @@ -2272,7 +2272,7 @@ void AICastor::computeBuildingNeighbourM } Game *game=team->game; - for (Sint32 ti=0; tisession.numberOfTeam; ti++) + for (Sint32 ti=0; timapHeader.getNumberOfTeams(); ti++) { Team *team=game->teams[ti]; assert(team); @@ -2609,7 +2609,7 @@ void AICastor::computeEnemyPowerMap() memset(gradient, 0, size); - for (int ti=0; tisession.numberOfTeam; ti++) + for (int ti=0; timapHeader.getNumberOfTeams(); ti++) { Team *enemyTeam=game->teams[ti]; Uint32 me=team->me; @@ -2688,7 +2688,7 @@ void AICastor::computeEnemyRangeMap() memcpy(gradient, obstacleUnitMap, size); - for (int ti=0; tisession.numberOfTeam; ti++) + for (int ti=0; timapHeader.getNumberOfTeams(); ti++) { Team *enemyTeam=game->teams[ti]; Uint32 me=team->me; diff -r b371d8df4dc9 -r ddbedd4025c4 src/AINumbi.cpp --- a/src/AINumbi.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/AINumbi.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -834,7 +834,7 @@ Order *AINumbi::mayAttack(int critticalM // We look for a specific enemy: Uint32 enemies=player->team->enemies; int e=-1; - for (int i=0; isession.numberOfTeam; i++) + for (int i=0; imapHeader.getNumberOfTeams(); i++) if (game->teams[i]->me & enemies) e=i; if (e==-1) diff -r b371d8df4dc9 -r ddbedd4025c4 src/CampaignEditor.cpp --- a/src/CampaignEditor.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/CampaignEditor.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -71,13 +71,14 @@ void CampaignEditor::onAction(Widget *so int rcms=cms.execute(gfx, 40); if(rcms==ChooseMapScreen::OK) { - CampaignMapEntry cme(cms.sessionInfo.getMapName(), glob2NameToFilename("campaigns", cms.sessionInfo.getMapName().c_str(), "map")); + MapHeader& mapHeader = cms.getMapHeader(); + CampaignMapEntry cme(mapHeader.getMapName(), glob2NameToFilename("campaigns", mapHeader.getMapName(), "map")); CampaignMapEntryEditor cmee(campaign, cme); int rcmee = cmee.execute(gfx, 40); if(rcmee==CampaignMapEntryEditor::OK) { campaign.appendMap(cme); - mapList->addText(cms.sessionInfo.getMapName()); + mapList->addText(mapHeader.getMapName()); } else if(rcmee==CampaignMapEntryEditor::CANCEL) { diff -r b371d8df4dc9 -r ddbedd4025c4 src/ChooseMapScreen.cpp --- a/src/ChooseMapScreen.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/ChooseMapScreen.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -20,7 +20,6 @@ #include "ChooseMapScreen.h" #include "GUIGlob2FileList.h" #include "GUIMapPreview.h" -#include "Session.h" #include "GlobalContainer.h" #include #include @@ -71,40 +70,6 @@ ChooseMapScreen::ChooseMapScreen(const c mapDate=new Text(440, 60+128+125, ALIGN_SCREEN_CENTERED, ALIGN_SCREEN_CENTERED, "standard", "", 180); addWidget(mapDate); - globalContainer->settings.tempVarPrestige = 0; - useNewPrestige = false; - useVarPrestige=new OnOffButton(466, 37, 20, 20, ALIGN_SCREEN_CENTERED, ALIGN_SCREEN_CENTERED, useNewPrestige, useNewPrestige); - addWidget(useVarPrestige); - varPrestigeText=new Text(460, 37, ALIGN_FILL, ALIGN_SCREEN_CENTERED, "standard", "Custom Prestige"); - addWidget(varPrestigeText); - - prestigeRatio=new Number(466, 15, 100, 18, ALIGN_SCREEN_CENTERED, ALIGN_SCREEN_CENTERED, 18, "menu"); - prestigeRatio->add(0); - prestigeRatio->add(0); - prestigeRatio->add(100); - prestigeRatio->add(200); - prestigeRatio->add(300); - prestigeRatio->add(400); - prestigeRatio->add(500); - prestigeRatio->add(600); - prestigeRatio->add(700); - prestigeRatio->add(800); - prestigeRatio->add(900); - prestigeRatio->add(1000); - prestigeRatio->add(1100); - prestigeRatio->add(1200); - prestigeRatio->add(1300); - prestigeRatio->add(1400); - prestigeRatio->add(1500); - prestigeRatio->add(1600); - prestigeRatio->add(1700); - prestigeRatio->add(1800); - prestigeRatio->add(1900); - prestigeRatio->add(2000); - prestigeRatio->setNth(1); - prestigeRatio->visible=false; - addWidget(prestigeRatio); - validMapSelected = false; } @@ -127,49 +92,24 @@ void ChooseMapScreen::onAction(Widget *s { if (verbose) std::cout << "ChooseMapScreen::onAction : loading map " << mapFileName << std::endl; - validMapSelected = sessionInfo.load(stream); + validMapSelected = mapHeader.load(stream); if (validMapSelected) { - // update map name & info - mapName->setText(sessionInfo.getMapName()); - std::string textTemp; - textTemp = FormatableString("%0%1").arg(sessionInfo.numberOfTeam).arg(Toolkit::getStringTable()->getString("[teams]")); - mapInfo->setText(textTemp); - textTemp = FormatableString("%0 %1.%2").arg(Toolkit::getStringTable()->getString("[Version]")).arg(sessionInfo.versionMajor).arg(sessionInfo.versionMinor); - mapVersion->setText(textTemp); - textTemp = FormatableString("%0 x %1").arg(mapPreview->getLastWidth()).arg(mapPreview->getLastHeight()); - mapSize->setText(textTemp); - std::time_t mtime = Toolkit::getFileManager()->mtime(mapFileName); - mapDate->setText(std::ctime(&mtime)); - - // call subclass handler - validMapSelectedhandler(); + validMapSelected = gameHeader.load(stream, mapHeader.getVersionMinor()); + if (validMapSelected) + { + updateMapInformation(); + + std::time_t mtime = Toolkit::getFileManager()->mtime(mapFileName); + mapDate->setText(std::ctime(&mtime)); + } + else + std::cerr << "ChooseMapScreen::onAction : invalid game header for map " << mapFileName << std::endl; } else - std::cerr << "ChooseMapScreen::onAction : invalid Session info for map " << mapFileName << std::endl; + std::cerr << "ChooseMapScreen::onAction : invalid map header for map " << mapFileName << std::endl; } delete stream; - } - else if (action==BUTTON_STATE_CHANGED) - { - if (useVarPrestige->getState() == false) - { - prestigeRatio->visible=false; - globalContainer->settings.tempVarPrestige = 3000; - } - else if (useVarPrestige->getState() == true) - { - prestigeRatio->visible=true; - globalContainer->settings.tempVarPrestige=(prestigeRatio->getNth() - 1) * 100; - } - } - else if (action==NUMBER_ELEMENT_SELECTED) - { - if (prestigeRatio->getNth() == 0) - { - prestigeRatio->setNth(1); - } - globalContainer->settings.tempVarPrestige=(prestigeRatio->getNth() - 1) * 100; } else if ((action == BUTTON_RELEASED) || (action == BUTTON_SHORTCUT)) { @@ -195,3 +135,34 @@ void ChooseMapScreen::onAction(Widget *s } } } + + +void ChooseMapScreen::updateMapInformation() +{ + // update map name & info + mapName->setText(mapHeader.getMapName()); + std::string textTemp; + textTemp = FormatableString("%0%1").arg(mapHeader.getNumberOfTeams()).arg(Toolkit::getStringTable()->getString("[teams]")); + mapInfo->setText(textTemp); + textTemp = FormatableString("%0 %1.%2").arg(Toolkit::getStringTable()->getString("[Version]")).arg(mapHeader.getVersionMajor()).arg(mapHeader.getVersionMinor()); + mapVersion->setText(textTemp); + textTemp = FormatableString("%0 x %1").arg(mapPreview->getLastWidth()).arg(mapPreview->getLastHeight()); + mapSize->setText(textTemp); + + // call subclass handler + validMapSelectedhandler(); +} + + +MapHeader& ChooseMapScreen::getMapHeader() +{ + return mapHeader; +} + + +GameHeader& ChooseMapScreen::getGameHeader() +{ + return gameHeader; +} + + diff -r b371d8df4dc9 -r ddbedd4025c4 src/ChooseMapScreen.h --- a/src/ChooseMapScreen.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/ChooseMapScreen.h Thu Apr 26 18:29:44 2007 -0400 @@ -20,7 +20,8 @@ #ifndef __CHOOSE_MAP_SCREEN_H #define __CHOOSE_MAP_SCREEN_H -#include "Session.h" +#include "MapHeader.h" +#include "GameHeader.h" #include "Glob2Screen.h" #include @@ -37,8 +38,22 @@ class MapPreview; //! This screen is the basic screen used to selected map and games class ChooseMapScreen : public Glob2Screen { - static const bool verbose = false; public: + /// Constructor. Directory is the source of the listed files. + /// extension is the file extension to show. If recurse is true, + /// subdirectoried are shown and can be opened. + ChooseMapScreen(const char *directory, const char *extension, bool recurse); + //! Destructor + virtual ~ChooseMapScreen(); + virtual void onAction(Widget *source, Action action, int par1, int par2); + + /// Returns the mapHeader of the map that is currently selected + MapHeader& getMapHeader(); + + /// Returns the gameHeader, with all of the customized options, + /// for the currently selected map. + GameHeader& getGameHeader(); + enum { //! Value returned upon screen execution completion when a valid map/game is selected @@ -48,11 +63,20 @@ public: //! Value returned if screen is for games and delete button has been pressed DELETEGAME = 3, }; - - //! Session info, will be used by caller upen screen execution completion - SessionInfo sessionInfo; + protected: + /// Handle called when a valid map has been selected. + /// This is to be overwritten by the derived class. + virtual void validMapSelectedhandler(void) { } + + /// The map header of the currently selected map + MapHeader mapHeader; + /// The game header of the currently selected map + GameHeader gameHeader; + +private: + //! Title of the screen, depends on the directory given in parameter Text *title; //! The ok button @@ -67,24 +91,14 @@ protected: MapPreview *mapPreview; //! The textual informations about the selected map Text *mapName, *mapInfo, *mapVersion, *mapSize, *mapDate, *varPrestigeText; - // The number information about selected map - Number *prestigeRatio; //! True when the selected map is valid bool validMapSelected; - OnOffButton *useVarPrestige; //determines if custom prestige will be used - bool useNewPrestige; - SessionGame session; -public: - //! Constructor. Directory is the source of the listed files. extension is the file extension to show. If recurse is true, subdirectoried are shown and can be opened. - ChooseMapScreen(const char *directory, const char *extension, bool recurse); - //! Destructor - virtual ~ChooseMapScreen(); - virtual void onAction(Widget *source, Action action, int par1, int par2); - -protected: - //! Handle called when a valid map has been selected. Tp be overriden by subclasses - virtual void validMapSelectedhandler(void) { } + /// Called after a new mapHeader and gameHeader have been loaded. + void updateMapInformation(); + + /// Designates whether there will be verbose debugging output. + static const bool verbose = false; }; #endif diff -r b371d8df4dc9 -r ddbedd4025c4 src/CustomGameScreen.cpp --- a/src/CustomGameScreen.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/CustomGameScreen.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -28,14 +28,15 @@ #include #include #include +#include CustomGameScreen::CustomGameScreen() : ChooseMapScreen("maps", "map", true) { for (int i=0; iclearColors(); - for (int j = 0; jaddColor(sessionInfo.teams[j].colorR, sessionInfo.teams[j].colorG, sessionInfo.teams[j].colorB); + for (int j = 0; jaddColor(mapHeader.getBaseTeam(j).colorR, mapHeader.getBaseTeam(j).colorG, mapHeader.getBaseTeam(j).colorB); color[i]->setSelectedColor(); } // find team for human player, not in every map - for (i = 0; isetSelectedColor(i); break; @@ -88,24 +93,26 @@ void CustomGameScreen::validMapSelectedh } // Fill the others int c = color[0]->getSelectedColor(); - for (i = 1; isetSelectedColor(c); color[i]->show(); - isAI[i]->setState(true); + isPlayerActive[i]->setState(true); closedText[i]->hide(); aiSelector[i]->show(); } // Close the rest for (; isetState(false); + isPlayerActive[i]->setState(false); color[i]->hide(); aiSelector[i]->hide(); closedText[i]->show(); } } + + void CustomGameScreen::onAction(Widget *source, Action action, int par1, int par2) { @@ -115,12 +122,12 @@ void CustomGameScreen::onAction(Widget * { if (par1==100) { - isAI[0]->setState(true); + isPlayerActive[0]->setState(true); } else if ((par1>100) && (par1<200)) { int n=par1-100; - if (isAI[n]->getState()) + if (isPlayerActive[n]->getState()) { color[n]->show(); closedText[n]->hide(); @@ -136,18 +143,54 @@ void CustomGameScreen::onAction(Widget * } } -bool CustomGameScreen::isAIactive(int i) + + +bool CustomGameScreen::isActive(int i) { - return isAI[i]->getState(); + return isPlayerActive[i]->getState(); } + + AI::ImplementitionID CustomGameScreen::getAiImplementation(int i) { return (AI::ImplementitionID)aiSelector[i]->getIndex(); } + + int CustomGameScreen::getSelectedColor(int i) { return color[i]->getSelectedColor(); } + + +void CustomGameScreen::updatePlayers() +{ + for (int i=0; igetUsername().c_str(), teamColor, BasePlayer::P_LOCAL); + } + else + { + AI::ImplementitionID iid=getAiImplementation(i); + FormatableString name("%0 %1"); + name.arg(Toolkit::getStringTable()->getString("[AI]", iid)).arg(i-1); + gameHeader.getBasePlayer(i) = BasePlayer(i, name.c_str(), teamColor, Player::playerTypeFromImplementitionID(iid)); + } + } + else + { + gameHeader.getBasePlayer(i) = BasePlayer(); + } + } +} + + + diff -r b371d8df4dc9 -r ddbedd4025c4 src/CustomGameScreen.h --- a/src/CustomGameScreen.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/CustomGameScreen.h Thu Apr 26 18:29:44 2007 -0400 @@ -42,15 +42,6 @@ const int NumberOfPlayerSelectors=16; //! This screen is used to setup a custom game. AI can be set. Map choosing functionnalities are inherited from ChooseMapScreen class CustomGameScreen : public ChooseMapScreen { -private: - //! AI enable/disable buttons - OnOffButton *isAI[NumberOfPlayerSelectors]; - //! Team color buttons - ColorButton *color[NumberOfPlayerSelectors]; - //! Text shown when entry is disabled - Text *closedText[NumberOfPlayerSelectors]; - //! Multi-text button containing names of availables AIs - MultiTextButton *aiSelector[NumberOfPlayerSelectors]; public: //! Constructor, builds a ChooseMapScreen for maps @@ -60,11 +51,25 @@ public: virtual void onAction(Widget *source, Action action, int par1, int par2); virtual void validMapSelectedhandler(void); //! Returns true if AI i is enabled - bool isAIactive(int i); + bool isActive(int i); //! Returns the implementation of AI i. If AI is disabled, result is undefined AI::ImplementitionID getAiImplementation(int i); //! Returns the color of AI i. If AI is disabled, result is undefined int getSelectedColor(int i); + +private: + ///Updates the gameHeader with the chosen players for the map + void updatePlayers(); + + //! Player enable/disable buttons + OnOffButton *isPlayerActive[NumberOfPlayerSelectors]; + //! Team color buttons + ColorButton *color[NumberOfPlayerSelectors]; + //! Text shown when entry is disabled + Text *closedText[NumberOfPlayerSelectors]; + //! Multi-text button containing names of availables Player + MultiTextButton *aiSelector[NumberOfPlayerSelectors]; + }; #endif diff -r b371d8df4dc9 -r ddbedd4025c4 src/EndGameScreen.cpp --- a/src/EndGameScreen.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/EndGameScreen.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -79,7 +79,7 @@ void EndGameStat::paint(void) // find maximum int team, maxValue = 0; unsigned int pos=0; - for (team=0; team < game->session.numberOfTeam; team++) + for (team=0; team < game->mapHeader.getNumberOfTeams(); team++) for (pos=0; posteams[team]->stats.endOfGameStats.size(); pos++) maxValue = std::max(maxValue, game->teams[team]->stats.endOfGameStats[pos].value[type]); @@ -145,7 +145,7 @@ void EndGameStat::paint(void) // draw curve if (maxValue) { - for (team=0; team < game->session.numberOfTeam; team++) + for (team=0; team < game->mapHeader.getNumberOfTeams(); team++) { if(!isTeamEnabled[team]) continue; @@ -292,10 +292,10 @@ EndGameScreen::EndGameScreen(GameGUI *gu // add players name Text *text; - int inc = (gui->game.session.numberOfTeam < 16) ? 20 : 10; + int inc = (gui->game.mapHeader.getNumberOfTeams() < 16) ? 20 : 10; // set teams entries for later sort - for (int i=0; igame.session.numberOfTeam; i++) + for (int i=0; igame.mapHeader.getNumberOfTeams(); i++) { Team *t=gui->game.teams[i]; int endIndex=t->stats.endOfGameStats.size()-1; diff -r b371d8df4dc9 -r ddbedd4025c4 src/Engine.cpp --- a/src/Engine.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Engine.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -105,77 +105,28 @@ Engine::~Engine() } } -int Engine::initCampaign(const std::string &mapName) -{ - if (!loadGame(mapName)) - return EE_CANT_LOAD_MAP; - - // we make a player for each team - int playerNumber=0; - bool wasHuman=false; - char name[BasePlayer::MAX_NAME_LENGTH]; - for (int i=0; itype==BaseTeam::T_AI) - { - snprintf(name, BasePlayer::MAX_NAME_LENGTH, "AI Player %d", playerNumber); - gui.game.players[playerNumber]=new Player(playerNumber, name, gui.game.teams[i], BasePlayer::P_AI); - } - else if (gui.game.teams[i]->type==BaseTeam::T_HUMAN) - { - if (!wasHuman) - { - gui.localPlayer=playerNumber; - gui.localTeamNo=i; - snprintf(name, BasePlayer::MAX_NAME_LENGTH, "Player %d", playerNumber); - wasHuman=true; - gui.game.players[playerNumber]=new Player(playerNumber, name, gui.game.teams[i], BasePlayer::P_LOCAL); - } - else - { - snprintf(name, BasePlayer::MAX_NAME_LENGTH, "AI Player %d", playerNumber); - gui.game.players[playerNumber]=new Player(playerNumber, name, gui.game.teams[i], BasePlayer::P_AI); - } - } - else - assert(false); - gui.game.teams[i]->numberOfPlayer=1; - gui.game.teams[i]->playersMask=(1< 0) - { - CampaignScreen campaignScreen(gui.game.campaignText); - int retVal = campaignScreen.execute(globalContainer->gfx, 40); - if (retVal) - return EE_CANCEL; - } - - // We do some cosmetic fix - finalAdjustements(); - - // we create the net game - net=new NetGame(NULL, gui.game.session.numberOfPlayer, gui.game.players); - - return EE_NO_ERROR; -} + int Engine::initCampaign(const std::string &mapName, Campaign& campaign, const std::string& missionName) { - int end=initCampaign(mapName); + MapHeader mapHeader = loadMapHeader(mapName); + GameHeader gameHeader = prepareCampaign(mapHeader); + int end=initGame(mapHeader, gameHeader); gui.setCampaignGame(campaign, missionName); return end; } + + + +int Engine::initCampaign(const std::string &mapName) +{ + MapHeader mapHeader = loadMapHeader(mapName); + GameHeader gameHeader = prepareCampaign(mapHeader); + int end=initGame(mapHeader, gameHeader); + return end; +} + + int Engine::initCustom(void) { @@ -187,91 +138,37 @@ int Engine::initCustom(void) return EE_CANCEL; if (cgs==-1) return -1; - - if (!gui.loadBase(&(customGameScreen.sessionInfo))) - { - if (verbose) - printf("Engine : Can't load map\n"); - return EE_CANCEL; - } - int nbTeam=gui.game.session.numberOfTeam; - if (nbTeam==0) - return EE_CANCEL; - - int i; - int nbPlayer=0; - - for (i=0; igetUsername().c_str(), gui.game.teams[teamColor], BasePlayer::P_LOCAL); - gui.localPlayer=nbPlayer; - gui.localTeamNo=teamColor; - } - else - { - AI::ImplementitionID iid=customGameScreen.getAiImplementation(i); - FormatableString name("%0 %1"); - name.arg(Toolkit::getStringTable()->getString("[AI]", iid)).arg(nbPlayer-1); - gui.game.players[nbPlayer]=new Player(i, name.c_str(), gui.game.teams[teamColor], Player::playerTypeFromImplementitionID(iid)); - } - gui.game.teams[teamColor]->numberOfPlayer++; - gui.game.teams[teamColor]->playersMask|=(1<type); - if (gui.game.players[p]->type==BasePlayer::P_IP) - { - gui.game.players[p]->makeItAI(AI::toggleAI); + printf("Engine::initCustom::player[%d].type=%d.\n", p, gameHeader.getBasePlayer(p).type); + if (gameHeader.getBasePlayer(p).type==BasePlayer::P_IP) + { + gameHeader.getBasePlayer(p).makeItAI(AI::toggleAI); if (verbose) printf("Engine::initCustom::net player (id %d) was made ai.\n", p); } } - // We do some cosmetic fix - gui.adjustLocalTeam(); - if (!globalContainer->runNoX) - { - gui.game.renderMiniMap(gui.localTeamNo); - gui.adjustInitialViewport(); - } - + initGame(mapHeader, gameHeader); + // set the correct alliance gui.game.setAIAlliance(); - - // we create the net game - net=new NetGame(NULL, gui.game.session.numberOfPlayer, gui.game.players); return EE_NO_ERROR; } @@ -283,7 +180,7 @@ int Engine::initLoadGame() if (lgs == ChooseMapScreen::CANCEL) return EE_CANCEL; - return initCustom(loadGameScreen.sessionInfo.getFileName()); + return initCustom(loadGameScreen.getMapHeader().getFileName()); } void Engine::startMultiplayer(MultiplayersJoin *multiplayersJoin) @@ -313,7 +210,7 @@ void Engine::startMultiplayer(Multiplaye finalAdjustements(); // we create the net game - net=new NetGame(multiplayersJoin->socket, gui.game.session.numberOfPlayer, gui.game.players); + net=new NetGame(multiplayersJoin->socket, gui.game.gameHeader.getNumberOfPlayers(), gui.game.players); if (verbose) printf("Engine::localPlayer=%d, localTeamNb=%d\n", gui.localPlayer, gui.localTeamNo); @@ -584,6 +481,67 @@ int Engine::run(void) } } + + +int Engine::initGame(MapHeader& mapHeader, GameHeader& gameHeader) +{ + if (gui.loadFromHeaders(mapHeader, gameHeader)) + return EE_CANT_LOAD_MAP; + + // if this has campaign text information, show a screen for it. + if (gui.game.campaignText.length() > 0) + { + CampaignScreen campaignScreen(gui.game.campaignText); + int retVal = campaignScreen.execute(globalContainer->gfx, 40); + if (retVal) + return EE_CANCEL; + } + + // We remove uncontrolled stuff from map + gui.game.clearingUncontrolledTeams(); + + // We do some cosmetic fix + finalAdjustements(); + + // we create the net game + net=new NetGame(NULL, gui.game.gameHeader.getNumberOfPlayers(), gui.game.players); + + return EE_NO_ERROR; +} + + + +GameHeader prepareCampaign(MapHeader& mapHeader) +{ + GameHeader gameHeader; + + // We make a player for each team in the mapHeader + int playerNumber=0; + // Incase there are multiple "humans" selected, only the first will actually become human + bool wasHuman=false; + // Each team has a variable, type, that designates whether it is a human or an AI in + // a campaign match. + for (int i=0; itype==BaseTeam::T_HUMAN && !wasHuman) + { + std::string name = FormatableString("Player %0").arg(playerNumber); + gameHeader.getBasePlayer(i) = BasePlayer(playerNumber, name, i, BasePlayer::P_LOCAL); + wasHuman=true; + } + else if (mapHeader.getBaseTeam(i)->type==BaseTeam::T_AI || wasHuman) + { + std::string name = FormatableString("AI Player %0").arg(playerNumber); + gameHeader.getBasePlayer(i) = BasePlayer(playerNumber, name, i, BasePlayer::P_AI); + } + playerNumber+=1; + } + + gameHeader.setNumberOfPlayers(playerNumber); + + return gameHeader; +} + bool Engine::loadGame(const std::string &filename) { InputStream *stream = new BinaryInputStream(Toolkit::getFileManager()->openInputStreamBackend(filename)); @@ -609,6 +567,55 @@ bool Engine::loadGame(const std::string return true; } + + +MapHeader Engine::loadMapHeader(const std::string &filename) +{ + MapHeader mapHeader; + InputStream *stream = new BinaryInputStream(Toolkit::getFileManager()->openInputStreamBackend(filename)); + if (stream->isEndOfStream()) + { + std::cerr << "Engine::loadMapHeader : error, can't open file " << mapFileName << std::endl; + } + else + { + if (verbose) + std::cout << "Engine::loadMapHeader : loading map " << mapFileName << std::endl; + bool validMapSelected = mapHeader.load(stream); + if (!validMapSelected) + std::cerr << "Engine::loadMapHeader : invalid map header for map " << mapFileName << std::endl; + } + delete stream; + return mapHeader; +} + + + +GameHeader Engine::loadGameHeader(const std::string &filename) +{ + MapHeader mapHeader; + GameHeader gameHeader; + InputStream *stream = new BinaryInputStream(Toolkit::getFileManager()->openInputStreamBackend(filename)); + if (stream->isEndOfStream()) + { + std::cerr << "Engine::loadGameHeader : error, can't open file " << mapFileName << std::endl; + } + else + { + if (verbose) + std::cout << "Engine::loadGameHeader : loading map " << mapFileName << std::endl; + mapHeader.load(stream); + bool validMapSelected = gameHeader.load(stream); + if (!validMapSelected) + std::cerr << "Engine::loadGameHeader : invalid game header for map " << mapFileName << std::endl; + } + delete stream; + return gameHeader; + +} + + + void Engine::finalAdjustements(void) { gui.adjustLocalTeam(); diff -r b371d8df4dc9 -r ddbedd4025c4 src/Engine.h --- a/src/Engine.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Engine.h Thu Apr 26 18:29:44 2007 -0400 @@ -24,30 +24,40 @@ #include "GameGUI.h" #include #include "Campaign.h" +#include "MapHeader.h" +#include "GameHeader.h" class MultiplayersJoin; class NetGame; -//! Engine is responsible for loading games and setting up players +/// Engine is the backend of the game. It is responsible for loading and setting up games and players, +/// and its run function is meant to run the game that has been loaded. class Engine { - static const bool verbose = false; public: //! Constructor Engine(); //! Destructor ~Engine(); - - //! Load mapName for campaign, init teams and create netGame + + /// Initiates a campaign map. This first loads the MapHeader, and then generates a GameHeader for + /// the campaign map. It then informs GameGUI that this map is a campaign, and if the player wins + /// it, the given Campaign should be informed. + int initCampaign(const std::string &mapName, Campaign& campaign, const std::string& missionName); + + /// Initiates a campaign game that isn't part of a campaign. One example is the tutorial, which + /// is a lone map that runs with campaign semantics int initCampaign(const std::string &mapName); - //! Init the map from the campaign - int initCampaign(const std::string &mapName, Campaign& campaign, const std::string& missionName); - //! Display a custom map chooser screen, init teams and create netGame + + /// Displays the CustomMap dialogue, and initiates a game from the settings it recieves int initCustom(); - //! Init and load a custom game from gameName. init teams and create netGame + + /// Initiate a custom game from the provided game, without adjusting settings from the user int initCustom(const std::string &gameName); - //! Display a game chooser screen then call initCustom(gameName) with the selected file + + /// Show the load/save dialoge, and use initCustom(gameName) to load the game int initLoadGame(); + //! Start a multiplayer game. Init teams and create netGame void startMultiplayer(MultiplayersJoin *multiplayersJoin); //! Display a map/game chooser screen suitable for multiplayer use when hosting, than call startMultiplayer @@ -76,11 +86,26 @@ public: //! The netGame, take care of order queuing and dispatching NetGame *net; -protected: +private: + /// Initiates a game, provided the map and game header. This initiates the net + /// as well. + int initGame(MapHeader& mapHeader, GameHeader& gameHeader); + + /// Prepares a GameHeader for the given mapHeader as a campaign map + /// Campaign maps have one player per team, and the player can be + /// either a human or an AI. AI's are all AINull + GameHeader prepareCampaign(MapHeader& mapHeader); + //! Load a game. Return true on success bool loadGame(const std::string &filename); //! Do the final adjustements, like setting local teams and viewport, rendering minimap void finalAdjustements(void); + + ///This will load the map header of the game with the given filename + MapHeader loadMapHeader(const std::string &filename); + + ///This will load the game header of the game with the given filename + GameHeader loadGameHeader(const std::string &filename); protected: int cpuStats[41]; @@ -89,6 +114,8 @@ protected: unsigned cpuSumCountStats; Sint32 noxStartTick, noxEndTick; FILE *logFile; +private: + static const bool verbose = false; }; #endif diff -r b371d8df4dc9 -r ddbedd4025c4 src/Game.cpp --- a/src/Game.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Game.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -81,19 +81,7 @@ Game::~Game() } } - // delete existing teams and players - for (int i=0; idrawFilledRect(0, 0, 100, 100, 0, 0, 0); } - session.numberOfTeam=0; - session.numberOfPlayer=0; - + mapHeader.reset(); + gameHeader.reset(); + for (int i=0; i<32; i++) { teams[i]=NULL; @@ -145,45 +133,90 @@ void Game::init(GameGUI *gui) ticksGameSum[i]=0; } -void Game::setBase(const SessionInfo *initial) -{ - // This function reset some team info and overwrite the players - - assert(initial); - assert(initial->numberOfTeam==session.numberOfTeam); - // TODO, we should be able to play with less team than planed on the map - // for instance, play at 2 on a 4 player map, and we will have to check the following code !!! - - // the GUI asserts that we have not more team that planed on the map + + +void Game::clearGame() +{ + // Delete existing teams and players + for (int i=0; isetBaseTeam(&(initial->teams[i]), session.fileIsAMap); - + for (int i=0; isetBaseTeam(&newMapHeader->getBaseTeam(i)); +} + + + +void Game::setGameHeader(const GameHeader& newGameHeader) +{ // set the base players - for (int i=0; inumberOfPlayer; - - for (int i=0; inumberOfPlayer; i++) + gameHeader = newGameHeader; + + for (int i=0; iplayersMask=0; + gui.game.teams[i]->numberOfPlayer=0; + } + + for (int i=0; isetBasePlayer(&(initial->players[i]), teams); - } - - session.gameTPF=initial->gameTPF; - session.gameLatency=initial->gameLatency; + players[i]->setBasePlayer(gameHeader.getBasePlayer(i), teams); + gui.game.teams[players[i]->teamNumber]->numberOfPlayer+=1; + gui.game.teams[players[i]->teamNumber]->playersMask|=(1<sender>=0); assert(order->sender<32); - assert(order->sendersender < gameHeader.getNumberOfPlayers()); Team *team=players[order->sender]->team; assert(team); bool isPlayerAlive=team->isAlive; @@ -712,7 +745,7 @@ bool Game::isHumanAllAllied(void) Uint32 nonAIMask=0; // AIMask now have the mask of everything which isn't AI - for (int i=0; itype != BaseTeam::T_AI) ? 1 : 0) << i; //printf("team %d is AI is %d\n", i, teams[i]->type == BaseTeam::T_AI); @@ -720,7 +753,7 @@ bool Game::isHumanAllAllied(void) // if there is any non-AI player with which we aren't allied, return false // or if there is any player allied to AI - for (int i=0; itype != BaseTeam::T_AI) { if (teams[i]->allies != nonAIMask) @@ -741,7 +774,7 @@ void Game::setAIAlliance(void) Uint32 aiMask = 0; // find all AI - for (int i=0; itype == BaseTeam::T_AI) aiMask |= (1<type == BaseTeam::T_AI) { teams[i]->allies = aiMask; @@ -762,7 +795,7 @@ void Game::setAIAlliance(void) printf("Game : AIs are now in ffa mode\n"); // free for all on AI side - for (int i=0; itype == BaseTeam::T_AI) { @@ -778,242 +811,178 @@ bool Game::load(GAGCore::InputStream *st assert(stream); stream->readEnterSection("Game"); - // delete existing teams - for (int i=0; ireadLeaveSection(); return false; } - - session=(SessionGame)tempSessionInfo; - - if (stream->canSeek()) - stream->seekFromStart(tempSessionInfo.gameOffset); - + mapHeader=tempMapHeader; + Sint32 versionMinor=mapHeader.getVersionMinor(); + + + // We load the game header + GameHeader tempGameHeader; + if (verbose) + printf("Loading game header\n"); + if (!tempGameHeader.load(stream)) + { + fprintf(logFile, "Game::load::tempMapHeader.load\n"); + stream->readLeaveSection(); + return false; + } + gameHeader=tempGameHeader; + + // Test the beginning signature. Signatures are basic corruption tests. + // Since Game loads many other structures, it has many of them. char signature[4]; stream->read(signature, 4, "signatureStart"); - if (session.versionMinor >= 31) - { - if (memcmp(signature,"GaBe", 4)!=0) - { - fprintf(logFile, "Signature missmatch at begin\n"); - stream->readLeaveSection(); - return false; - } - } - else if (memcmp(signature, "GAMb",4)!=0) - { - fprintf(logFile, "Signature missmatch at begin\n"); + if (memcmp(signature,"GaBe", 4)!=0) + { + fprintf(logFile, "Signature missmatch at Game::load begin\n"); stream->readLeaveSection(); return false; } - - if (session.versionMinor>=31) - stepCounter = stream->readUint32("stepCounter"); + + ///Load the step counter and random seeds + stepCounter = stream->readUint32("stepCounter"); setSyncRandSeedA(stream->readUint32("SyncRandSeedA")); setSyncRandSeedB(stream->readUint32("SyncRandSeedB")); setSyncRandSeedC(stream->readUint32("SyncRandSeedC")); stream->read(signature, 4, "signatureAfterSyncRand"); - if (session.versionMinor>=31) - { - if (memcmp(signature,"GaSy", 4)!=0) - { - fprintf(logFile, "Signature missmatch after sync rand\n"); - stream->readLeaveSection(); - return false; - } - } - else if (memcmp(signature, "GAMm", 4)!=0) - { - fprintf(logFile, "Signature missmatch after sync rand\n"); + if (memcmp(signature,"GaSy", 4)!=0) + { + fprintf(logFile, "Signature missmatch after Game::load sync rand\n"); stream->readLeaveSection(); return false; } - // we load teams - if (stream->canSeek()) - stream->seekFromStart(tempSessionInfo.teamsOffset); + ///Load teams stream->readEnterSection("teams"); - for (int i=0; ireadEnterSection(i); - teams[i]=new Team(stream, this, session.versionMinor); + teams[i]=new Team(stream, this, versionMinor); stream->readLeaveSection(); } stream->readLeaveSection(); - if (session.versionMinor>=31) - { - stream->read(signature, 4, "signatureAfterTeams"); - if (memcmp(signature,"GaTe", 4)!=0) - { - fprintf(logFile, "Signature missmatch after teams\n"); - stream->readLeaveSection(); - return false; - } - } - - // we have to load team before map - if (stream->canSeek()) - stream->seekFromStart(tempSessionInfo.mapOffset); + + stream->read(signature, 4, "signatureAfterTeams"); + if (memcmp(signature,"GaTe", 4)!=0) + { + fprintf(logFile, "Signature missmatch after Game::load teams\n"); + stream->readLeaveSection(); + return false; + } + + // Load the map. Team has to be saved and loaded first. if(!map.load(stream, &session, this)) { fprintf(logFile, "Signature missmatch in map\n"); stream->readLeaveSection(); return false; } + stream->read(signature, 4, "signatureAfterMap"); - if (session.versionMinor>=31) - { - if (memcmp(signature,"GaMa", 4)!=0) - { - fprintf(logFile, "Signature missmatch after map\n"); - stream->readLeaveSection(); - return false; - } - } - else if (memcmp(signature,"GAMe", 4)!=0) + if (memcmp(signature,"GaMa", 4)!=0) { fprintf(logFile, "Signature missmatch after map\n"); stream->readLeaveSection(); return false; } - // we have to load map and team before players - if (stream->canSeek()) - stream->seekFromStart(tempSessionInfo.playersOffset); + // Load the players. Both Map and Team must be loaded first. stream->readEnterSection("players"); - for (int i=0; ireadEnterSection(i); - players[i]=new Player(stream, teams, session.versionMinor); + players[i]=new Player(stream, teams, versionMinor); stream->readLeaveSection(); } stream->readLeaveSection(); - if (session.versionMinor>=31) - { - stream->read(signature, 4, "signatureAfterPlayers"); - if (memcmp(signature,"GaPl", 4)!=0) - { - fprintf(logFile, "Signature missmatch after players\n"); - stream->readLeaveSection(); - return false; - } - } - else - stepCounter = stream->readUint32("stepCounter"); - - // we have to finish Team's loading: - for (int i=0; iread(signature, 4, "signatureAfterPlayers"); + if (memcmp(signature,"GaPl", 4)!=0) + { + fprintf(logFile, "Signature missmatch after players\n"); + stream->readLeaveSection(); + return false; + } + + // We have to finish Team's loading + for (int i=0; istats.setMapSize(map.getW(), map.getH()); teams[i]->update(); } - for (int i=0; iintegrity(); - // then script - if (stream->canSeek()) - stream->seekFromStart(tempSessionInfo.mapScriptOffset); + // Now load the map script if (!script.load(stream, this)) { stream->readLeaveSection(); return false; } - if (session.versionMinor < 37) - { - campaignText = ""; - } - else - { - if(session.versionMinor < 55) - stream->readText("nextMap"); - campaignText = stream->readText("campaignText"); - } -//game reverts to default prestige settings if higher then maximum (2000) -//this is done to maximize efficiency if maximum settings are ever changed this -//will need to be changed as well - if (session.varPrestige > 2000) - { - // default prestige calculation - prestigeToReach = std::max(MIN_MAX_PRESIGE, session.numberOfTeam*TEAM_MAX_PRESTIGE); - } - else - { - // custom prestige - prestigeToReach = session.varPrestige; - } + ///Load the campaign text for the game. + campaignText = stream->readText("campaignText"); + + // default prestige calculation + prestigeToReach = std::max(MIN_MAX_PRESIGE, mapHeader.getNumberOfTeams()*TEAM_MAX_PRESTIGE); + stream->readLeaveSection(); return true; } -void Game::save(GAGCore::OutputStream *stream, bool fileIsAMap, const char* name) +void Game::save(GAGCore::OutputStream *stream, bool fileIsAMap, const std::string& name) { assert(stream); stream->writeEnterSection("Game"); - // first we save a session info - SessionInfo tempSessionInfo(session); - - // A typical use case: You have loaded a map, and you want to save your game. - // In this case, the file is no more a map, but a game. - tempSessionInfo.fileIsAMap=(Sint32)fileIsAMap; - tempSessionInfo.setMapName(name); - - for (int i=0; igetPosition(); + mapHeader.setMapName(name); + + for (int i=0; iwrite("GaBe", 4, "signatureStart"); - stream->writeUint32(stepCounter, "stepCounter"); stream->writeUint32(getSyncRandSeedA(), "SyncRandSeedA"); stream->writeUint32(getSyncRandSeedB(), "SyncRandSeedB"); stream->writeUint32(getSyncRandSeedC(), "SyncRandSeedC"); stream->write("GaSy", 4, "signatureAfterSyncRand"); - SAVE_OFFSET(stream, 20, "teamsOffset"); + ///Save teams stream->writeEnterSection("teams"); - for (int i=0; iwriteEnterSection(i); teams[i]->save(stream); @@ -1022,13 +991,16 @@ void Game::save(GAGCore::OutputStream *s stream->writeLeaveSection(); stream->write("GaTe", 4, "signatureAfterTeams"); - SAVE_OFFSET(stream, 28, "mapOffset"); + + ///Save the map offset to the header, before we save the map + ///Then, save the map + mapHeader->setMapOffset(stream->getPosition()); map.save(stream); stream->write("GaMa", 4, "signatureAfterMap"); - - SAVE_OFFSET(stream, 24, "playersOffset"); + + ///Save the players stream->writeEnterSection("players"); - for (int i=0; iwriteEnterSection(i); players[i]->save(stream); @@ -1037,10 +1009,22 @@ void Game::save(GAGCore::OutputStream *s stream->writeLeaveSection(); stream->write("GaPl", 4, "signatureAfterPlayers"); - SAVE_OFFSET(stream, 32, "mapScriptOffset"); + ///Save the map script state script.save(stream, this); + ///Save the campaign text stream->writeText(campaignText, "campaignText"); + + ///Overwrite the MapHeader. This is done after the map + ///offset has been set. + if (stream->canSeek()) + { + Uint32 position = stream->getPosition(); + stream->seekFromStart(mapHeaderOffset); + mapHeader.save(stream); + stream->seekFromStart(position); + } + stream->writeLeaveSection(); } @@ -1107,17 +1091,17 @@ void Game::buildProjectSyncStep(Sint32 l void Game::wonSyncStep(void) { -// prestige of 0 results in infinite prestige - if (session.varPrestige > 0) + // prestige of 0 results in infinite prestige + if (prestigeToReach > 0) { totalPrestige=0; isGameEnded=false; int greatestPrestige=0; - for (int i=0; ime) & (teams[j]->allies)) /*&& ((teams[j]->me) & (teams[i]->allies))*/ )) && (teams[j]->isAlive)) isOtherAlive=true; @@ -1133,7 +1117,7 @@ void Game::wonSyncStep(void) totalPrestigeReached=true; isGameEnded=true; - for (int i=0; ihasWon = teams[i]->prestige == greatestPrestige; } } @@ -1145,7 +1129,7 @@ void Game::scriptSyncStep() script.syncStep(gui); // alter win/loose conditions - for (int i=0; iisAlive) { @@ -1160,7 +1144,7 @@ void Game::clearEventsStep(void) void Game::clearEventsStep(void) { // We clear all events - for (int i=0; iclearEvents(); } @@ -1170,7 +1154,7 @@ void Game::syncStep(Sint32 localTeam) { Sint32 startTick=SDL_GetTicks(); - for (int i=0; isyncStep(); map.syncStep(stepCounter); @@ -1180,7 +1164,7 @@ void Game::syncStep(Sint32 localTeam) if ((stepCounter&31)==16) { map.switchFogOfWar(); - for (int t=0; tmyBuildings[i]; @@ -1218,22 +1202,24 @@ void Game::syncStep(Sint32 localTeam) void Game::dirtyWarFlagGradient(void) { - for (int i=0; idirtyWarFlagGradient(); } void Game::addTeam(int pos) { if(pos==-1) - pos=session.numberOfTeam; - if (session.numberOfTeam<32) + pos=mapHeader.getNumberOfTeams(); + if (mapHeader.getNumberOfTeams()<32) { teams[pos]=new Team(this); - teams[pos]->teamNumber=session.numberOfTeam; + teams[pos]->teamNumber=mapHeader.getNumberOfTeams(); teams[pos]->race.load(); teams[pos]->setCorrectMasks(); - pos=++session.numberOfTeam; + pos=mapHeader.getNumberOfTeams(); + pos+=1; + mapHeader.setNumberOfTeams(pos) for (int i=0; isetCorrectColor( ((float)i*360.0f) /(float)pos ); @@ -1248,17 +1234,21 @@ void Game::removeTeam(int pos) void Game::removeTeam(int pos) { if(pos==-1) - pos=--session.numberOfTeam; - if (session.numberOfTeam>0) + { + pos=mapHeader.getNumberOfTeams(); + pos-=1; + mapHeader.setNumberOfTeams(pos) + } + if (mapHeader.getNumberOfTeams()>0) { Team *team=teams[pos]; team->clearMap(); delete team; - assert (session.numberOfTeam!=0); - for (int i=0; isetCorrectColor(((float)i*360.0f)/(float)session.numberOfTeam); + assert (mapHeader.getNumberOfTeams()!=0); + for (int i=0; isetCorrectColor(((float)i*360.0f)/(float)mapHeader.getNumberOfTeams()); map.removeTeam(); teams[pos]=NULL; @@ -1267,7 +1257,7 @@ void Game::removeTeam(int pos) void Game::clearingUncontrolledTeams(void) { - for (int ti=0; tiplayersMask==0) @@ -1283,7 +1273,7 @@ void Game::regenerateDiscoveryMap(void) void Game::regenerateDiscoveryMap(void) { map.unsetMapDiscovered(); - for (int t=0; trace.getUnitType(typeNum, level); @@ -1424,7 +1414,7 @@ bool Game::removeUnitAndBuildingAndFlags } if (flags & DEL_FLAG) { - for (int ti=0; ti::iterator bi=teams[ti]->virtualBuildings.begin(); bi!=teams[ti]->virtualBuildings.end(); ++bi) if ((*bi)->posX==x && (*bi)->posY==y) { @@ -2488,11 +2478,11 @@ void Game::drawMap(int sx, int sy, int s drawMapWater(sw, sh, viewportX, viewportY, time); drawMapTerrain(left, top, right, bot, viewportX, viewportY, localTeam, drawOptions); drawMapRessources(left, top, right, bot, viewportX, viewportY, localTeam, drawOptions); - drawMapAreas(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); drawMapGroundUnits(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); drawMapDebugAreas(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); drawMapGroundBuildings(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); drawMapAirUnits(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); + drawMapAreas(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); if((drawOptions & DRAW_SCRIPT_AREAS) != 0) drawMapScriptAreas(left, top, right, bot, viewportX, viewportY); drawMapBulletsExplosionsDeathAnimations(left, top, right, bot, sw, sh, viewportX, viewportY, localTeam, drawOptions); @@ -2579,7 +2569,7 @@ void Game::drawMap(int sx, int sy, int s if (false) for (int y=top-1; y<=bot; y++) for (int x=left-1; x<=right; x++) - for (int pi=0; piai && players[pi]->ai->implementitionID==AI::CASTOR) { AICastor *ai=(AICastor *)players[pi]->ai->aiImplementation; @@ -2863,15 +2853,15 @@ Uint32 Game::checkSum(std::vectorpush_back(sessionCs);// [0] + checkSumsVector->push_back(headerCs);// [0] cs=(cs<<31)|(cs>>1); Uint32 teamsCs=0; - for (int i=0; icheckSum(checkSumsVector, checkSumsVectorForBuildings, checkSumsVectorForUnits); teamsCs=(teamsCs<<31)|(teamsCs>>1); @@ -2884,7 +2874,7 @@ Uint32 Game::checkSum(std::vector>1); Uint32 playersCs=0; - for (int i=0; icheckSum(checkSumsVector); playersCs=(playersCs<<31)|(playersCs>>1); @@ -2897,7 +2887,7 @@ Uint32 Game::checkSum(std::vector>1); bool heavy=false; - for (int i=0; itype==BasePlayer::P_IP) { heavy=true; @@ -2933,7 +2923,7 @@ Team *Game::getTeamWithMostPrestige(void int maxPrestige=0; Team *maxPrestigeTeam=NULL; - for (int i=0; iprestige > maxPrestige) @@ -2945,20 +2935,20 @@ Team *Game::getTeamWithMostPrestige(void return maxPrestigeTeam; } -std::string glob2FilenameToName(const char *filename) -{ - GAGCore::InputStream *stream = new GAGCore::BinaryInputStream(GAGCore::Toolkit::getFileManager()->openInputStreamBackend(filename)); +std::string glob2FilenameToName(const std::string& filename) +{ + GAGCore::InputStream *stream = new GAGCore::BinaryInputStream(GAGCore::Toolkit::getFileManager()->openInputStreamBackend(filename.c_str())); if (stream->isEndOfStream()) { delete stream; } else { - SessionInfo tempSession; - bool res = tempSession.load(stream); + MapHeader tempHeader; + bool res = tempHeader.load(stream); delete stream; if (res) - return tempSession.getMapName(); + return tempHeader.getMapName(); } return ""; } @@ -2974,15 +2964,15 @@ private: const It to; }; -std::string glob2NameToFilename(const char *dir, const char *name, const char *extension) +std::string glob2NameToFilename(const std::string& dir, const std::string& name, const std::string& extension) { const char* pattern = " \t"; const char* endPattern = strchr(pattern, '\0'); - std::string fileName = name; + std::string& fileName = name; std::replace_if(fileName.begin(), fileName.end(), contains(pattern, endPattern), '_'); std::string fullFileName = dir; fullFileName += DIR_SEPARATOR + fileName; - if (extension && (*extension != '\0')) + if (extension != "" && extension != "\0") { fullFileName += '.'; fullFileName += extension; diff -r b371d8df4dc9 -r ddbedd4025c4 src/Game.h --- a/src/Game.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Game.h Thu Apr 26 18:29:44 2007 -0400 @@ -1,6 +1,8 @@ /* Copyright (C) 2001-2004 Stephane Magnenat & Luc-Olivier de Charrière for any question or comment contact us at or + + Copyright (C) 2007 Bradley Arsenault This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,9 +23,10 @@ #define __GAME_H #include "Map.h" -#include "Session.h" #include "SGSL.h" #include +#include "MapHeader.h" +#include "GameHeader.h" namespace GAGCore { @@ -38,6 +41,18 @@ class Game { static const bool verbose = false; public: + ///Constructor. GUI can be NULL + Game(GameGUI *gui); + + ///Clears all memory that Game uses + virtual ~Game(); + + ///Loads data from a stream + bool load(GAGCore::InputStream *stream); + + ///Saves data to a stream + void save(GAGCore::OutputStream *stream, bool fileIsAMap, const std::string& name); + enum FlagForRemoval { DEL_BUILDING=0x1, @@ -65,58 +80,31 @@ public: enum MinimapDrawOption { }; - - struct BuildProject - { - int posX; - int posY; - int teamNumber; - int typeNum; - int unitWorking; - int unitWorkingFuture; - }; - -public: - Game(GameGUI *gui); - virtual ~Game(); - -private: - enum BarOrientation - { - LEFT_TO_RIGHT, - RIGHT_TO_LEFT, - TOP_TO_BOTTOM, - BOTTOM_TO_TOP - }; - - void init(GameGUI *gui); - void drawPointBar(int x, int y, BarOrientation orientation, int maxLength, int actLength, Uint8 r, Uint8 g, Uint8 b, int barWidth=2); - - //! return true if all human are allied together, flase otherwise - bool isHumanAllAllied(void); - - -public: - bool anyPlayerWaited; - int anyPlayerWaitedTimeFor; - Uint32 maskAwayPlayer; - -public: - - //! This methode will overide currents values of *this by the values of *initial. - void setBase(const SessionInfo *initial); + + /// This method will prepare the game with this mapHeader + void setMapHeader(const MapHeader& mapHeader); + + /// This method will prepare the game with the provided gameHeader, + /// including initiating the Players + void setGameHeader(const GameHeader& gameHeader); + + ///Executes an Order with respect to the localPlayer of the GUI. All Orders get processed here. void executeOrder(Order *order, int localPlayer); - bool load(GAGCore::InputStream *stream); - void save(GAGCore::OutputStream *stream, bool fileIsAMap, const char *name); - + + ///Makes a step for building projects that are waiting for the areas to clear of units. void buildProjectSyncStep(Sint32 localTeam); - //! look for each team if it has won or not + + /// Check and update winning conditions void wonSyncStep(void); - //! call script.step(), then check conditions and updates internal variables if needed + + /// Advanced the map script and checks conditions void scriptSyncStep(); + //! before any game logic can be executed, we have to clear the event queu from the last tick void clearEventsStep(void); - //! called by gui, execute a step for this game. The gui parameter is for the script + + /// Advances the Game by one tick, in reference to localTeam being the localTeam. This does all + /// internal proccessing. void syncStep(Sint32 localTeam); void dirtyWarFlagGradient(); @@ -145,8 +133,44 @@ public: void drawUnit(int x, int y, Uint16 gid, int viewportX, int viewportY, int screenW, int screenH, int localTeam, Uint32 drawOptions); void drawMap(int sx, int sy, int sw, int sh, int viewportX, int viewportY, int teamSelected, Uint32 drawOptions = 0); + private: - + enum BarOrientation + { + LEFT_TO_RIGHT, + RIGHT_TO_LEFT, + TOP_TO_BOTTOM, + BOTTOM_TO_TOP + }; + + struct BuildProject + { + int posX; + int posY; + int teamNumber; + int typeNum; + int unitWorking; + int unitWorkingFuture; + }; + + ///Initiates Game + void init(GameGUI *gui); + + ///Clears existing game information, deleting the teams and players, in preperation of a new game. + void clearGame(); + + //! return true if all human are allied together, flase otherwise + bool isHumanAllAllied(void); + +public: + bool anyPlayerWaited; + int anyPlayerWaitedTimeFor; + Uint32 maskAwayPlayer; + +public: + +private: + void drawPointBar(int x, int y, BarOrientation orientation, int maxLength, int actLength, Uint8 r, Uint8 g, Uint8 b, int barWidth=2); inline void drawMapWater(int sw, int sh, int viewportX, int viewportY, int time); inline void drawMapTerrain(int left, int top, int right, int bot, int viewportX, int viewportY, int localTeam, Uint32 drawOptions); inline void drawMapRessources(int left, int top, int right, int bot, int viewportX, int viewportY, int localTeam, Uint32 drawOptions); @@ -169,7 +193,11 @@ public: void setAIAlliance(void); public: - SessionGame session; + ///This is a static header for a map. It remains the same in between games on the same map. + MapHeader mapHeader; + ///This is a game header. It contains all the settings for a particular game, from AI's to Alliances to victory conditions. + GameHeader gameHeader; + Team *teams[32]; Player *players[32]; Map map; @@ -197,16 +225,16 @@ public: bool oldMakeIslandsMap(MapGenerationDescriptor &descriptor); bool makeRandomMap(MapGenerationDescriptor &descriptor); bool generateMap(MapGenerationDescriptor &descriptor); - + protected: FILE *logFile; int ticksGameSum[32]; }; //! extract the user-visible name from a glob2 map filename, return empty string if filename is an invalid glob2 map -std::string glob2FilenameToName(const char *filename); +std::string glob2FilenameToName(const std::string& filename); //! create the filename from the directory, end user-visible name and extension. directory and extension must be given without the / and the . -std::string glob2NameToFilename(const char *dir, const char *name, const char *extension=NULL); +std::string glob2NameToFilename(const std::string& dir, const std::string& name, const std::string& extension=""); #endif diff -r b371d8df4dc9 -r ddbedd4025c4 src/GameGUI.cpp --- a/src/GameGUI.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/GameGUI.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -3737,13 +3737,13 @@ void GameGUI::executeOrder(Order *order) } } -bool GameGUI::loadBase(const SessionInfo *initial) +bool GameGUI::loadFromHeaders(MapHeader& mapHeader, GameHeader& gameHeader); { init(); - InputStream *stream = new BinaryInputStream(Toolkit::getFileManager()->openInputStreamBackend(initial->getFileName())); + InputStream *stream = new BinaryInputStream(Toolkit::getFileManager()->openInputStreamBackend(mapHeader.getFileName())); if (stream->isEndOfStream()) { - std::cerr << "GameGUI::loadBase() : error, can't open file " << initial->getFileName() << std::endl; + std::cerr << "GameGUI::loadFromHeaders() : error, can't open file " << initial->getFileName() << std::endl; delete stream; return false; } @@ -3754,7 +3754,8 @@ bool GameGUI::loadBase(const SessionInfo if (!res) return false; - game.setBase(initial); + game.setMapHeader(mapHeader); + game.setGameHeader(gameHeader); } return true; diff -r b371d8df4dc9 -r ddbedd4025c4 src/GameGUI.h --- a/src/GameGUI.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/GameGUI.h Thu Apr 26 18:29:44 2007 -0400 @@ -28,6 +28,7 @@ #include "Order.h" #include "Brush.h" #include "Campaign.h" +#include "MapHeader.h" namespace GAGCore { @@ -66,7 +67,7 @@ public: //! true if user close the glob2 window. bool exitGlobCompletely; //! if this is not empty, then Engine should load the map with this filename. - char toLoadGameFileName[SessionGame::MAP_NAME_MAX_SIZE+5]; + std::string toLoadGameFileName; //bool showExtendedInformation; bool drawHealthFoodBar, drawPathLines, drawAccessibilityAids; int localPlayer, localTeamNo; @@ -93,7 +94,7 @@ public: void executeOrder(Order *order); //! - bool loadBase(const SessionInfo *initial); + bool loadFromHeaders(MapHeader& mapHeader, GameHeader& gameHeader); //! bool load(GAGCore::InputStream *stream); void save(GAGCore::OutputStream *stream, const char *name); diff -r b371d8df4dc9 -r ddbedd4025c4 src/GameHeader.cpp --- a/src/GameHeader.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/GameHeader.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -20,6 +20,13 @@ GameHeader::GameHeader() { + reset(); +} + + + +void GameHeader::reset() +{ numberOfPlayers = 0; gameLatency = 5; } @@ -69,6 +76,13 @@ Sint32 GameHeader::getNumberOfPlayers() +void GameHeader::setNumberOfPlayers(Sint32 players) +{ + numberOfPlayers=players; +} + + + Sint32 GameHeader::getGameLatency() const { return gameLatency; @@ -80,3 +94,11 @@ void GameHeader::setGameLatency(Sint32 l { gameLatency = latency; } + + + +BasePlayer& getBasePlayer(const int n) +{ + assert(n<32 && n>=0); + return players[n]; +} diff -r b371d8df4dc9 -r ddbedd4025c4 src/GameHeader.h --- a/src/GameHeader.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/GameHeader.h Thu Apr 26 18:29:44 2007 -0400 @@ -30,6 +30,9 @@ public: public: ///Gives default values to all entries GameHeader(); + + ///Resets the GameHeader to a "blank" state with default values + void reset(); ///Loads game header information from the stream bool load(GAGCore::InputStream *stream, Sint32 versionMinor); @@ -40,11 +43,17 @@ public: ///Returns the number of players in the game Sint32 getNumberOfPlayers() const; + ///Sets the number of players in the game + void setNumberOfPlayers(Sint32 players); + ///Returns the games latency. This would be 0 for local games, but higher for networked games. Sint32 getGameLatency() const; ///Sets the latency of the game. void setGameLatency(Sint32 latency); + + ///Provides access to the base player. n must be between 0 and 31. + BasePlayer& getBasePlayer(const int n); private: ///The number of players in the game Sint32 numberOfPlayers; @@ -52,7 +61,7 @@ private: ///The number of ticks between an order issue, and the execution of the order. ///Used for net games to hide latency. Sint32 gameLatency; - + ///Represents the basic player information in the game BasePlayer players[32]; }; diff -r b371d8df4dc9 -r ddbedd4025c4 src/MapHeader.cpp --- a/src/MapHeader.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/MapHeader.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -21,10 +21,18 @@ MapHeader::MapHeader() { + reset(); +} + + + +void MapHeader::reset() +{ versionMajor = VERSION_MAJOR; versionMinor = VERSION_MINOR; numberOfTeams = 0; mapName = ""; + mapOffset = 0; } @@ -36,6 +44,15 @@ bool MapHeader::load(GAGCore::InputStrea versionMajor = stream->readSint32("versionMajor"); versionMinor = stream->readSint32("versionMinor"); numberOfTeams = stream->readSint32("numberOfTeams"); + mapOffset = stream->readUint32("mapOffset"); + stream->readEnterSection("teams"); + for(int i=0; i<32; ++i) + { + stream->readEnterSection(i); + teams[i].load(stream, versionMinor); + stream->readLeaveSection(i); + } + stream->readLeaveSection(); stream->readLeaveSection(); } @@ -51,6 +68,15 @@ void MapHeader::save(GAGCore::OutputStre stream->writeSint32(versionMajor, "versionMajor"); stream->writeSint32(versionMinor, "versionMinor"); stream->writeSint32(numberOfTeams, "numberOfTeams"); + stream->writeUint32(mapOffset, "mapOffset"); + stream->writeEnterSection("teams"); + for(int i=0; i<32; ++i) + { + stream->writeEnterSection(i); + teams[i].save(stream); + stream->writeLeaveSection(i); + } + stream->writeLeaveSection(); stream->writeLeaveSection(); } @@ -88,12 +114,44 @@ const std::string& MapHeader::getMapName { return mapName; } - + + + +const std::string& MapHeader::getFileName() const +{ +// if (fileIsAMap) + return glob2NameToFilename("maps", mapName, "map"); +// else +// return glob2NameToFilename("games", mapName, "game"); +} + void MapHeader::setMapName(const std::string& newMapName) { mapName = newMapName; +} + + + +Uint32 MapHeader::getMapOffset() const +{ + return mapOffset; +} + + + +void MapHeader::setMapOffset(Uint32 newMapOffset) +{ + mapOffset = newMapOffset; +} + + + +BaseTeam& MapHeader::getBaseTeam(const int n) +{ + assert(n>=0 && n<32); + return teams[n]; } @@ -110,13 +168,3 @@ Uint32 MapHeader::checkSum() const -void MapHeader::loadFromSessionGame(SessionGame* session) -{ - versionMinor = session->versionMinor; - versionMajor = session->versionMajor; - numberOfTeams = session->numberOfTeam; - mapName = session->getMapName(); -} - - - diff -r b371d8df4dc9 -r ddbedd4025c4 src/MapHeader.h --- a/src/MapHeader.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/MapHeader.h Thu Apr 26 18:29:44 2007 -0400 @@ -19,9 +19,9 @@ #ifndef __MAPHEADER_H #define __MAPHEADER_H -#include "Session.h" #include "Stream.h" #include "Version.h" +#include "Team.h" ///This is the map header. It is static with the map, and does not change from game to game if ///the user is playing on the same map. It holds small details about a map that aren't placed @@ -29,47 +29,72 @@ class MapHeader class MapHeader { public: - ///Gives default values to all entries + /// Gives default values to all entries MapHeader(); - ///Loads map header information from the stream + /// Resets the MapHeader to a "blank" state with default values + void reset(); + + /// Loads map header information from the stream bool load(GAGCore::InputStream *stream); - ///Saves map header information to the stream + /// Saves map header information to the stream void save(GAGCore::OutputStream *stream); - ///Returns the version major + /// Returns the version major Sint32 getVersionMajor() const; - ///Returns the version minor + /// Returns the version minor Sint32 getVersionMinor() const; - ///Returns the number of teams + /// Returns the number of teams Sint32 getNumberOfTeams() const; - ///Sets the number of teams in the map + /// Sets the number of teams in the map void setNumberOfTeams(Sint32 teamNum); - ///Returns the user-friendly name of the map + /// Returns the user-friendly name of the map const std::string& getMapName() const; - //! Set the user-friendly name of the map + /// Returns the file name of the map + const std::string& getFileName() const; + + /// Sets the user-friendly name of the map void setMapName(const std::string& newMapName); - ///Returns a checksum of the map header information + /// Returns the offset of the Map info in the game save. + /// This is used to quickly gain access to Map data, for + /// the generation of map previews + Uint32 getMapOffset() const; + + /// Sets the map offset. Should only be done during saving + /// the game or map. + /// Note that technically the MapHeader is the first thing + /// written to the file. This means that it has to be + /// *overwritten* after the offset has been found. + void setMapOffset(Uint32 mapOffset); + + /// Returns the base team for team n. n must be between 0 and 31 + BaseTeam& getBaseTeam(const int n); + + /// Returns a checksum of the map header information Uint32 checkSum() const; - ///This loads information from a provided SessionGame instance. - ///This is used purely for backwards compatibility - void loadFromSessionGame(SessionGame* session); private: - //! Major map version. Change only with structural modification + /// Major map version. Changes only with structural modification Sint32 versionMajor; - //! Minor map version. Change each time something has been changed in serialized version. + /// Minor map version. Changes each time something has been changed in serializations Sint32 versionMinor; - - ///The number of teams on the map + /// The number of teams on the map Sint32 numberOfTeams; + /// The offset of Map in the save. This is set during saving, + /// and is used to generate Map previews without loading + /// the complete file. + Uint32 mapOffset; + + ///The teams in the map. BaseTeam is used to allow access to information like team numbers and + ///team colors without loading the entire game. + BaseTeam teams[32]; std::string mapName; }; diff -r b371d8df4dc9 -r ddbedd4025c4 src/Player.cpp --- a/src/Player.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Player.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -55,7 +55,7 @@ BasePlayer::BasePlayer(Sint32 number, co void BasePlayer::init() { - type=P_IP; + type=P_NONE; number=0; numberMask=0; strncpy(name, "DEBUG PLAYER", MAX_NAME_LENGTH); @@ -260,6 +260,20 @@ Uint32 BasePlayer::checkSum() return cs; } + + +void Player::makeItAI(AI::ImplementitionID aiType) +{ + if (ai) + { + assert(type>=P_AI); + delete ai; + ai=NULL; + } + type=(PlayerType)(P_AI+aiType); +} + + void BasePlayer::setip(Uint32 host, Uint16 port) { @@ -504,19 +518,6 @@ void Player::setBasePlayer(const BasePla channel=initial->channel; }; -void Player::makeItAI(AI::ImplementitionID aiType) -{ - if (ai) - { - assert(type>=P_AI); - delete ai; - ai=NULL; - } - type=(PlayerType)(P_AI+aiType); - ai=new AI(aiType, this); - assert(ai); -} - bool Player::load(GAGCore::InputStream *stream, Team *teams[32], Sint32 versionMinor) { stream->readEnterSection("Player"); diff -r b371d8df4dc9 -r ddbedd4025c4 src/Player.h --- a/src/Player.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Player.h Thu Apr 26 18:29:44 2007 -0400 @@ -148,6 +148,8 @@ public: Uint32 checkSum(); + void makeItAI(AI::ImplementitionID aiType); + void setip(Uint32 host, Uint16 port); void setip(IPaddress ip); bool sameip(IPaddress ip); @@ -180,8 +182,6 @@ public: void setTeam(Team *team); void setBasePlayer(const BasePlayer *initial, Team *teams[32]); - void makeItAI(AI::ImplementitionID aiType); - bool load(GAGCore::InputStream *stream, Team *teams[32], Sint32 versionMinor); void save(GAGCore::OutputStream *stream); diff -r b371d8df4dc9 -r ddbedd4025c4 src/Session.h --- a/src/Session.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Session.h Thu Apr 26 18:29:44 2007 -0400 @@ -23,18 +23,6 @@ #include "MapGenerationDescriptor.h" #include "Player.h" #include "Team.h" - -//! Save in stream at offset the actual file pos -#define SAVE_OFFSET(stream, offset, name) \ - { \ - if (stream->canSeek()) \ - { \ - Uint32 pos = stream->getPosition(); \ - stream->seekFromStart(offset); \ - stream->writeUint32(pos, name); \ - stream->seekFromStart(pos); \ - } \ - } //! This is named SessionGame but in fact it is Glob2's map headers. //! Map Specific infos are not serialized and don't go through network diff -r b371d8df4dc9 -r ddbedd4025c4 src/Settings.cpp --- a/src/Settings.cpp Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Settings.cpp Thu Apr 26 18:29:44 2007 -0400 @@ -54,9 +54,7 @@ Settings::Settings() restoreDefaultShortcuts(); tempUnit = 1; tempUnitFuture = 1; - //while a little ugly it is necessary to store varPrestige within settings - //to prevent session.cpp from overriding variable once map is chosen - tempVarPrestige = 0; + for(int n=0; nteamNumber; numberOfPlayer=initial->numberOfPlayer; @@ -239,14 +239,8 @@ void Team::setBaseTeam(const BaseTeam *i race=initial->race; fprintf(logFile, "Team::setBaseTeam(), teamNumber=%d, playersMask=%d\n", teamNumber, playersMask); - // This case is a bit hard to understand. - // When you load a teamed saved game, you don't want to change your aliances. - // But players may join the network game in adifferent order than when the game was saved. - if (overwriteAfterbase) - { - setCorrectColor(initial->colorR, initial->colorG, initial->colorB); - setCorrectMasks(); - } + setCorrectColor(initial->colorR, initial->colorG, initial->colorB); + setCorrectMasks(); } diff -r b371d8df4dc9 -r ddbedd4025c4 src/Team.h --- a/src/Team.h Sun Apr 22 21:17:03 2007 +0200 +++ b/src/Team.h Thu Apr 26 18:29:44 2007 -0400 @@ -110,7 +110,7 @@ public: virtual ~Team(void); - void setBaseTeam(const BaseTeam *initial, bool overwriteAfterbase); + void setBaseTeam(const BaseTeam *initial); bool load(GAGCore::InputStream *stream, BuildingsTypes *buildingstypes, Sint32 versionMinor); void save(GAGCore::OutputStream *stream);