1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // game saving functionality 17 // merely controls what to save when how - actual saving procedures reside in the subclasses 18 // 19 // Game saving is done on the following occasions: 20 // -scenario saving (C4GameSaveScenario) [SyncStateScenario; KeepFiles] 21 // -savegames (C4GameSaveSavegame) [SyncStateSavegame; KeepFiles] 22 // -records (C4GameSaveRecord) [SyncStateSynced; KeepFiles] - initially and while game is running 23 // -network synchronizations (C4GameSaveNetwork) [SyncStateSynced] - in lobby and runtime mode 24 // -network references (C4GameSaveNetReference) [SyncStateScenario] 25 26 #ifndef INC_C4GameSave 27 #define INC_C4GameSave 28 29 #include "landscape/C4Scenario.h" 30 #include "c4group/C4Components.h" 31 32 class C4GameSave 33 { 34 private: 35 C4Scenario rC4S; // local scenario core copy 36 37 protected: 38 C4Group *pSaveGroup; // group file written to 39 bool fOwnGroup; // whether group file is owned 40 41 // if set, the game is saved at initial (pre-frame0) state 42 // (lobby-dynamics, initial records and network references) 43 // no runtime data will be saved for initial-state-saves 44 // SafeGame/NoInitialize-core-settings will be kept in its current state for initial saves 45 bool fInitial; 46 47 // sync state describes what to save 48 enum SyncState 49 { 50 SyncNONE = 0, 51 SyncScenario = 1, // save (eventually static) landscape and objects only to play as a separate scenario later 52 SyncSavegame = 2, // save all runtime data, so the scenario can be continued at a future date 53 SyncSynchronized = 3 // save exact runtime data to be network- or replay-save 54 } Sync; // sync is set by ctor 55 56 // query functions GetSaveRuntimeData()57 virtual bool GetSaveRuntimeData() { return !fInitial; } // save exact landscape, players, etc. GetKeepTitle()58 virtual bool GetKeepTitle() { return !IsExact(); } // whether original, localized title with image and icon shall be deleted GetSaveDesc()59 virtual bool GetSaveDesc() { return true; } // should WriteDescData be executed in Save()-call? GetCopyScenario()60 virtual bool GetCopyScenario() { return true; } // return whether the savegame depends on the game scenario file GetSortOrder()61 virtual const char *GetSortOrder() { return C4FLS_Scenario; } // return nullptr to prevent sorting GetCreateSmallFile()62 virtual bool GetCreateSmallFile() { return false; } // return whether file size should be minimized GetForceExactLandscape()63 virtual bool GetForceExactLandscape() { return GetSaveRuntimeData() && IsExact(); } // whether exact landscape shall be saved GetSaveOrigin()64 virtual bool GetSaveOrigin() { return false; } // return whether C4S.Head.Origin shall be set GetClearOrigin()65 virtual bool GetClearOrigin() { return !GetSaveOrigin(); } // return whether C4S.Head.Origin shall be cleared if it's set GetSaveUserPlayers()66 virtual bool GetSaveUserPlayers() { return IsExact(); } // return whether joined user players shall be saved into SavePlayerInfos GetSaveScriptPlayers()67 virtual bool GetSaveScriptPlayers() { return IsExact(); } // return whether joined script players shall be saved into SavePlayerInfos GetSaveUserPlayerFiles()68 virtual bool GetSaveUserPlayerFiles() { return IsExact(); } // return whether .ocp files of joined user players shall be put into the scenario GetSaveScriptPlayerFiles()69 virtual bool GetSaveScriptPlayerFiles() { return IsExact(); } // return whether .ocp files of joined script players shall be put into the scenario 70 71 // savegame specializations AdjustCore(C4Scenario & rC4S)72 virtual void AdjustCore(C4Scenario &rC4S) {} // set specific C4S values WriteDesc(StdStrBuf & sBuf)73 virtual bool WriteDesc(StdStrBuf &sBuf) { return true; } // write desc (contents only) SaveComponents()74 virtual bool SaveComponents() { return true; } // save (or remove) custom components for specialization OnSaving()75 virtual bool OnSaving() { return true; } // callback for special actions to be performed when saving (like, add sync) 76 77 // query sync level IsExact()78 bool IsExact() { return Sync>=SyncSavegame; } // exact save (players, always exact landscape, etc.) IsSynced()79 bool IsSynced() { return Sync>=SyncSynchronized; } // synchronized 80 81 // protected constructor C4GameSave(bool fAInitial,SyncState ASync)82 C4GameSave(bool fAInitial, SyncState ASync) : pSaveGroup(nullptr), fOwnGroup(false), fInitial(fAInitial), Sync(ASync) { } 83 protected: 84 // some desc writing helpers 85 void WriteDescLineFeed(StdStrBuf &sBuf); // append a line break to desc 86 void WriteDescDate(StdStrBuf &sBuf, bool fRecord = false); // append current date to desc buffer 87 void WriteDescGameTime(StdStrBuf &sBuf); // append game time to desc buffer, if it's >0 88 void WriteDescDefinitions(StdStrBuf &sBuf); // append used definition filenames to desc buffer 89 void WriteDescNetworkClients(StdStrBuf &sBuf); // append current network client list to desc buffer 90 void WriteDescPlayers(StdStrBuf &sBuf, bool fByTeam, int32_t idTeam); // helper func used by WriteDescPlayers: Write all players matching team 91 void WriteDescPlayers(StdStrBuf &sBuf); // append currently participating players to desc buffer 92 void WriteDescLeague(StdStrBuf &sBuf, bool fLeague, const char *strLeagueName); // append league status 93 void WriteDescEngine(StdStrBuf &sBuf); // append engine build 94 private: 95 // saving subcalls 96 bool SaveCreateGroup(const char *szFilename, C4Group &hUseGroup); // create/copy group at target filename 97 bool SaveCore(); // save C4S core 98 bool SaveScenarioSections(); // save scenario sections 99 bool SaveLandscape(); // save current landscape 100 bool SaveRuntimeData(); // save any runtime data 101 public: ~C4GameSave()102 virtual ~C4GameSave() { Close(); } // dtor: close group 103 104 bool Save(const char *szFilename); // create group at filename and do actual saving; group is kept open until dtor or Close()-call! 105 bool Save(C4Group &hToGroup, bool fKeepGroup); // save game directly to target group 106 bool SaveDesc(C4Group &hToGroup); // save scenario desc to file 107 bool Close(); // close scenario group 108 GetGroup()109 C4Group *GetGroup() { return pSaveGroup; } // get scenario saving group; only open between calls to Save() and Close() 110 }; 111 112 class C4GameSaveScenario : public C4GameSave 113 { 114 public: C4GameSaveScenario(bool fForceExactLandscape,bool fSaveOrigin)115 C4GameSaveScenario(bool fForceExactLandscape, bool fSaveOrigin) : C4GameSave(false, SyncScenario), fForceExactLandscape(fForceExactLandscape), fSaveOrigin(fSaveOrigin) {} // ctor 116 117 protected: 118 bool fForceExactLandscape; 119 bool fSaveOrigin; GetSaveOrigin()120 bool GetSaveOrigin() override { return fSaveOrigin; } GetClearOrigin()121 bool GetClearOrigin() override { return false; } // always keep existing origin GetSaveDesc()122 bool GetSaveDesc() override { return false; } // should WriteDescData be executed in Save()-call? GetForceExactLandscape()123 bool GetForceExactLandscape() override { return C4GameSave::GetForceExactLandscape() || fForceExactLandscape; } GetSaveScriptPlayers()124 bool GetSaveScriptPlayers() override { return true; } // script players are also saved; but user players aren't! GetSaveScriptPlayerFiles()125 bool GetSaveScriptPlayerFiles() override { return true; } // script players are also saved; but user players aren't! 126 }; 127 128 class C4GameSaveSavegame : public C4GameSave 129 { 130 public: C4GameSaveSavegame()131 C4GameSaveSavegame() : C4GameSave(false, SyncSavegame) {} 132 133 protected: 134 // savegame specializations GetSaveOrigin()135 bool GetSaveOrigin() override { return true; } // origin must be saved in savegames GetSaveUserPlayerFiles()136 bool GetSaveUserPlayerFiles() override { return false; } // user player files are not needed in savegames, because they will be replaced by player files of resuming playerss 137 void AdjustCore(C4Scenario &rC4S) override; // set specific C4S values 138 bool WriteDesc(StdStrBuf &sBuf) override; // write savegame desc (contents only) 139 bool SaveComponents() override; // custom savegame components (title) 140 bool OnSaving() override; // add sync when saving 141 142 }; 143 144 class C4GameSaveRecord : public C4GameSave 145 { 146 private: 147 int iNum; // record number 148 bool fLeague; // recording of a league game? 149 bool fCopyScenario; // copy scenario? 150 151 public: 152 C4GameSaveRecord(bool fAInitial, int iANum, bool fLeague, bool fCopyScenario = true) C4GameSave(fAInitial,SyncSynchronized)153 : C4GameSave(fAInitial, SyncSynchronized), iNum(iANum), fLeague(fLeague), fCopyScenario(fCopyScenario) 154 {} 155 156 protected: 157 // query functions GetSaveDesc()158 bool GetSaveDesc() override { return false; } // desc is saved by external call when the record is finished GetCreateSmallFile()159 bool GetCreateSmallFile() override { return true; } // no need to save players complete with portraits GetSaveOrigin()160 bool GetSaveOrigin() override { return true; } // origin must be saved to trace language packs, folder local material, etc. for records 161 GetCopyScenario()162 bool GetCopyScenario() override { return fCopyScenario; } // records without copied scenario are a lot smaller can be reconstructed later (used for streaming) 163 164 // savegame specializations 165 void AdjustCore(C4Scenario &rC4S) override; // set specific C4S values 166 bool WriteDesc(StdStrBuf &sBuf) override; // write desc (contents only) - using old-style unchecked string buffers here... 167 bool SaveComponents() override; // custom components: PlayerInfos even if fInitial 168 169 }; 170 171 class C4GameSaveNetwork : public C4GameSave 172 { 173 public: C4GameSaveNetwork(bool fAInitial)174 C4GameSaveNetwork(bool fAInitial) : C4GameSave(fAInitial, SyncSynchronized) {} 175 176 protected: 177 // query functions GetSaveOrigin()178 bool GetSaveOrigin() override { return true; } // clients must know where to get music and localization GetKeepTitle()179 bool GetKeepTitle() override { return false; } // always delete title files (not used in dynamics) GetSaveDesc()180 bool GetSaveDesc() override { return false; } // no desc in dynamics GetCreateSmallFile()181 bool GetCreateSmallFile() override { return true; }// return whether file size should be minimized 182 GetCopyScenario()183 bool GetCopyScenario() override { return false; } // network dynamics do not base on normal scenario 184 // savegame specializations 185 void AdjustCore(C4Scenario &rC4S) override; // set specific C4S values 186 }; 187 188 #endif // INC_C4GameSave 189