[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