This is an automated email from the git hooks/post-receive script. smcv pushed a commit to branch debian/master in repository openjk.
commit 501db346ac5d055749e56090a2b3e1fb380cdf03 Author: bibendovsky <[email protected]> Date: Sun Jul 24 22:41:50 2016 +0300 JA: Restore loading of retail saved game --- code/game/g_public.h | 6 +- code/game/g_savegame.cpp | 170 +++++++++++++++++++++++++++++++--- code/game/g_shared.h | 13 ++- code/qcommon/q_shared.h | 17 +++- code/qcommon/qcommon.h | 6 +- codeJK2/game/g_shared.h | 1 - shared/qcommon/ojk_i_saved_game_fwd.h | 3 + shared/qcommon/ojk_saved_game.cpp | 11 ++- shared/qcommon/ojk_saved_game.h | 3 + 9 files changed, 202 insertions(+), 28 deletions(-) diff --git a/code/game/g_public.h b/code/game/g_public.h index 0465c27..a69244a 100644 --- a/code/game/g_public.h +++ b/code/game/g_public.h @@ -90,7 +90,11 @@ typedef enum #ifndef GAME_INCLUDE // the server needs to know enough information to handle collision and snapshot generation -class playerState_t; +template<typename TSaberInfo> +class PlayerStateBase; + +using playerState_t = PlayerStateBase<saberInfo_t>; + struct gentity_s { entityState_t s; // communicated by server to clients diff --git a/code/game/g_savegame.cpp b/code/game/g_savegame.cpp index 174e514..4ca5aec 100644 --- a/code/game/g_savegame.cpp +++ b/code/game/g_savegame.cpp @@ -738,6 +738,126 @@ static void SG_ConvertRetailSaberinfoToNewSaberinfo( void *sabData, saberInfo_t } } + +void saberInfoRetail_t::sg_export( + saberInfo_t& dst) const +{ + ::WP_SaberSetDefaults( + &dst, + false); + + if (!activeBlocking) + { + dst.saberFlags |= SFL_NOT_ACTIVE_BLOCKING; + } + + ::memcpy( + dst.blade, + blade, + sizeof(blade)); + + dst.breakParryBonus = breakParryBonus; + dst.brokenSaber1 = brokenSaber1; + dst.brokenSaber2 = brokenSaber2; + + if (!disarmable) + { + dst.saberFlags |= SFL_NOT_DISARMABLE; + } + + dst.disarmBonus = disarmBonus; + dst.forceRestrictions = forceRestrictions; + dst.fullName = fullName; + + if (!lockable) + { + dst.saberFlags |= SFL_NOT_LOCKABLE; + } + + dst.lockBonus = lockBonus; + dst.maxChain = maxChain; + dst.model = model; + dst.name = name; + dst.numBlades = numBlades; + dst.parryBonus = parryBonus; + + if (returnDamage) + { + dst.saberFlags |= SFL_RETURN_DAMAGE; + } + + dst.singleBladeStyle = singleBladeStyle; + + if (singleBladeThrowable) + { + dst.saberFlags |= SFL_SINGLE_BLADE_THROWABLE; + } + + dst.skin = skin; + dst.soundLoop = soundLoop; + dst.soundOff = soundOff; + dst.soundOn = soundOn; + + if (style != SS_NONE && style < SS_NUM_SABER_STYLES) + { + //OLD WAY: only allowed ONE style + //learn only this style + dst.stylesLearned = 1 << style; + + //forbid all other styles + dst.stylesForbidden = 0; + for (auto styleNum = SS_NONE + 1; styleNum < SS_NUM_SABER_STYLES; ++styleNum) + { + if (styleNum != style) + { + dst.stylesForbidden |= 1 << styleNum; + } + } + } + + if (!throwable) + { + dst.saberFlags |= SFL_NOT_THROWABLE; + } + + if (twoHanded) + { + dst.saberFlags |= SFL_TWO_HANDED; + } + + dst.type = type; +} + +static void copy_retail_gclient_to_current( + const RetailGClient& src, + gclient_t& dst) +{ + const auto src_pre_size = offsetof(RetailGClient, ps.saber[0]); + + const auto src_post_offset = + offsetof(RetailGClient, ps.dualSabers); + + const auto src_post_size = sizeof(RetailGClient) - src_post_offset; + + const auto dst_post_offset = offsetof(gclient_t, ps.dualSabers); + + ::memcpy( + reinterpret_cast<char*>(&dst), + reinterpret_cast<const char*>(&src), + src_pre_size); + + for (int i = 0; i < MAX_SABERS; ++i) + { + src.ps.saber[i].sg_export( + dst.ps.saber[i]); + } + + ::memcpy( + reinterpret_cast<char*>(&dst) + src_post_offset, + reinterpret_cast<const char*>(&src) + dst_post_offset, + src_post_size); +} + #if 0 template<typename T> static void EvaluateFields(const save_field_t *pFields, T *pbData, byte *pbOriginalRefData, unsigned int ulChid, int iSize, qboolean bOkToSizeMisMatch) @@ -796,9 +916,6 @@ static void EvaluateFields(const save_field_t *pFields, T *pbData, byte *pbOrigi } } #else -// FIXME Retail saved game not supported. -// FIXME Is it really needed? -// FIXME Also remove iSize and bOkToSizeMisMatch in that case. template<typename T> static void EvaluateFields( const save_field_t* pFields, @@ -808,19 +925,44 @@ static void EvaluateFields( int iSize, qboolean bOkToSizeMisMatch) { - ::gi.saved_game->read_chunk( - ulChid); - - pbData->sg_import( - ::gi.saved_game); - - // FIXME Add support for retail version? + auto& instance = *pbData; - if (!::gi.saved_game->is_all_data_read()) + if (ulChid != INT_ID('G','C','L','I')) { - ::G_Error( - ::va("EvaluateFields(): variable-sized chunk '%s' without handler!", - ::SG_GetChidText(ulChid))); + ::gi.saved_game->read_chunk( + ulChid, + instance); + } + else + { + ::gi.saved_game->read_chunk( + ulChid); + + ::gi.saved_game->try_read( + instance); + + if (!::gi.saved_game->is_all_data_read()) + { + RetailGClient retail_client; + + ::gi.saved_game->reset_buffer_offset(); + + ::gi.saved_game->try_read( + retail_client); + + if (::gi.saved_game->is_all_data_read()) + { + copy_retail_gclient_to_current( + retail_client, + *reinterpret_cast<gclient_t*>(pbData)); + } + else + { + ::G_Error( + ::va("EvaluateFields(): variable-sized chunk '%s' without handler!", + ::SG_GetChidText(ulChid))); + } + } } if (pFields) diff --git a/code/game/g_shared.h b/code/game/g_shared.h index 7201c2e..b4523aa 100644 --- a/code/game/g_shared.h +++ b/code/game/g_shared.h @@ -608,7 +608,6 @@ public: // client data that stays across multiple respawns, but is cleared // on each level change or team change at ClientBegin() // !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!! -// FIXME Prefix added to avoid debugging problems in Visual Studio. class clientPersistant_t { public: @@ -686,11 +685,12 @@ typedef enum //# movetype_e // this structure is cleared on each ClientSpawn(), // except for 'client->pers' and 'client->sess' -class gclient_t +template<typename TSaberInfo> +class GClientBase { public: // ps MUST be the first element, because the server expects it - playerState_t ps; // communicated by server to clients + PlayerStateBase<TSaberInfo> ps; // communicated by server to clients // private to game clientPersistant_t pers; @@ -922,7 +922,12 @@ public: saved_game->read<int32_t>(inSpaceSuffocation); saved_game->read<int32_t>(inSpaceIndex); } -}; // gclient_t +}; // GClientBase + + +using gclient_t = GClientBase<saberInfo_t>; +using RetailGClient = GClientBase<saberInfoRetail_t>; + #define MAX_PARMS 16 #define MAX_PARM_STRING_LENGTH MAX_QPATH//was 16, had to lengthen it so they could take a valid file path diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 6ae3fab..84d622f 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -2083,8 +2083,9 @@ typedef struct } saberInfo_t; //NOTE: Below is the *retail* version of the saberInfo_t structure - it is ONLY used for loading retail-version savegames (we load the savegame into this smaller structure, then copy each field into the appropriate field in the new structure - see SG_ConvertRetailSaberinfoToNewSaberinfo() -typedef struct +class saberInfoRetail_t { +public: char *name; //entry in sabers.cfg, if any char *fullName; //the "Proper Name" of the saber, shown in the UI saberType_t type; //none, single or staff @@ -2263,7 +2264,10 @@ typedef struct saved_game->read<int32_t>(brokenSaber2); saved_game->read<int32_t>(returnDamage); } -} saberInfoRetail_t; + + void sg_export( + saberInfo_t& dst) const; +}; // saberInfoRetail_t #define MAX_SABERS 2 // if this ever changes then update the table "static const save_field_t savefields_gClient[]"!!!!!!!!!!!! @@ -2278,7 +2282,8 @@ typedef struct // so if a playerState_t is transmitted, the entityState_t can be fully derived // from it. // !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!! -class playerState_t +template<typename TSaberInfo> +class PlayerStateBase { public: int commandTime; // cmd->serverTime of last executed command @@ -2382,7 +2387,7 @@ public: //FIXME: maybe allocate all these structures (saber, force powers, vehicles) // or descend them as classes - so not every client has all this info - saberInfo_t saber[MAX_SABERS]; + TSaberInfo saber[MAX_SABERS]; qboolean dualSabers; qboolean SaberStaff( void ) { return ( saber[0].type == SABER_STAFF || (dualSabers && saber[1].type == SABER_STAFF) ); }; qboolean SaberActive() { return ( saber[0].Active() || (dualSabers&&saber[1].Active()) ); }; @@ -2866,8 +2871,10 @@ public: saved_game->read<int32_t>(brokenLimbs); saved_game->read<int32_t>(electrifyTime); } -}; // playerState_t +}; // PlayerStateBase + +using playerState_t = PlayerStateBase<saberInfo_t>; //==================================================================== diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 483b85b..70580da 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -68,7 +68,11 @@ void MSG_WriteData (msg_t *buf, const void *data, int length); struct usercmd_s; struct entityState_s; -class playerState_t; + +template<typename TSaberInfo> +class PlayerStateBase; + +using playerState_t = PlayerStateBase<saberInfo_t>; void MSG_WriteBits( msg_t *msg, int value, int bits ); diff --git a/codeJK2/game/g_shared.h b/codeJK2/game/g_shared.h index 0213be5..3aefa95 100644 --- a/codeJK2/game/g_shared.h +++ b/codeJK2/game/g_shared.h @@ -642,7 +642,6 @@ public: // client data that stays across multiple respawns, but is cleared // on each level change or team change at ClientBegin() // !!!!!!!!!! LOADSAVE-affecting structure !!!!!!!!!! -// FIXME Prefix added to avoid debugging problems in Visual Studio. class clientPersistant_t { public: diff --git a/shared/qcommon/ojk_i_saved_game_fwd.h b/shared/qcommon/ojk_i_saved_game_fwd.h index 1ed867c..b55fe77 100644 --- a/shared/qcommon/ojk_i_saved_game_fwd.h +++ b/shared/qcommon/ojk_i_saved_game_fwd.h @@ -141,6 +141,9 @@ public: // Clears buffer and resets it's offset to the beginning. virtual void reset_buffer() = 0; + // Resets buffer offset to the beginning. + virtual void reset_buffer_offset() = 0; + protected: // Tags for dispatching. diff --git a/shared/qcommon/ojk_saved_game.cpp b/shared/qcommon/ojk_saved_game.cpp index 56bb31c..5a18911 100644 --- a/shared/qcommon/ojk_saved_game.cpp +++ b/shared/qcommon/ojk_saved_game.cpp @@ -472,7 +472,9 @@ void SavedGame::raw_read( return; } - if ((io_buffer_offset_ + dst_size) > io_buffer_.size()) + auto is_overflowed = ((io_buffer_offset_ + dst_size) > io_buffer_.size()); + + if (is_overflowed) { if (!is_read_overflow_allowed_) { @@ -481,7 +483,7 @@ void SavedGame::raw_read( } } - if (!is_read_overflow_allowed_) + if (!is_overflowed) { std::uninitialized_copy_n( &io_buffer_[io_buffer_offset_], @@ -779,6 +781,11 @@ std::string SavedGame::get_chunk_id_string( void SavedGame::reset_buffer() { io_buffer_.clear(); + reset_buffer_offset(); +} + +void SavedGame::reset_buffer_offset() +{ io_buffer_offset_ = 0; } diff --git a/shared/qcommon/ojk_saved_game.h b/shared/qcommon/ojk_saved_game.h index 3b975fa..1b59232 100644 --- a/shared/qcommon/ojk_saved_game.h +++ b/shared/qcommon/ojk_saved_game.h @@ -105,6 +105,9 @@ public: // Clears buffer and resets it's offset to the beginning. void reset_buffer() override; + // Resets buffer offset to the beginning. + void reset_buffer_offset() override; + // Renames a saved game file. static void rename( -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/openjk.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

