[openjk] 54/130: JA: Restore loading of retail saved game

Simon McVittie smcv at debian.org
Fri Oct 28 11:09:18 UTC 2016


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 <bibendovsky at hotmail.com>
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



More information about the Pkg-games-commits mailing list