From da83d9e2bd5f90f4f8c0f38facab61825e7b7be6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 21 Sep 2016 01:18:29 +0200 Subject: [PATCH] - converted player serializer and everything it needs. This means that everything belonging to the level snapshot will be generated in the JSON output. --- src/d_netinfo.cpp | 91 +++++++++++++------------ src/d_player.h | 8 +-- src/d_protocol.cpp | 40 ++++++----- src/d_protocol.h | 4 -- src/d_ticcmd.h | 3 - src/dthinker.h | 1 - src/p_saveg.cpp | 104 +++++++++++++++-------------- src/p_user.cpp | 161 ++++++++++++++++++++++----------------------- src/serializer.cpp | 53 +++++++++++++-- src/serializer.h | 11 +++- src/zzz_old.cpp | 2 +- 11 files changed, 265 insertions(+), 213 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 0b99fd73d..481421d31 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -56,7 +56,7 @@ #include "r_data/r_translate.h" #include "templates.h" #include "cmdlib.h" -#include "farchive.h" +#include "serializer.h" static FRandom pr_pickteam ("PickRandomTeam"); @@ -878,70 +878,75 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) *stream += strlen (*((char **)stream)) + 1; } -void WriteUserInfo(FArchive &arc, userinfo_t &info) +void WriteUserInfo(FSerializer &arc, userinfo_t &info) { - TMapIterator it(info); - TMap::Pair *pair; - FName name; - UCVarValue val; - int i; - - while (it.NextPair(pair)) + if (arc.BeginObject("userinfo")) { - name = pair->Key; - arc << name; - switch (name.GetIndex()) + TMapIterator it(info); + TMap::Pair *pair; + FString name; + const char *string; + UCVarValue val; + int i; + + while (it.NextPair(pair)) { - case NAME_Skin: - arc.WriteString(skins[info.GetSkin()].name); - break; + name = pair->Key; + name.ToLower(); + switch (pair->Key.GetIndex()) + { + case NAME_Skin: + string = skins[info.GetSkin()].name; + break; - case NAME_PlayerClass: - i = info.GetPlayerClassNum(); - arc.WriteString(i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars()); - break; + case NAME_PlayerClass: + i = info.GetPlayerClassNum(); + string = (i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars()); + break; - default: - val = pair->Value->GetGenericRep(CVAR_String); - arc.WriteString(val.String); - break; + default: + val = pair->Value->GetGenericRep(CVAR_String); + string = val.String; + break; + } + arc.StringPtr(name, string); } + arc.EndObject(); } - name = NAME_None; - arc << name; } -void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin) +void ReadUserInfo(FSerializer &arc, userinfo_t &info, FString &skin) { FName name; FBaseCVar **cvar; - char *str = NULL; UCVarValue val; + const char *key; + const char *str; info.Reset(); skin = NULL; - for (arc << name; name != NAME_None; arc << name) + if (arc.BeginObject("userinfo")) { - cvar = info.CheckKey(name); - arc << str; - if (cvar != NULL && *cvar != NULL) + while ((key = arc.GetKey())) { - switch (name) + arc.StringPtr(key, str); + name = key; + cvar = info.CheckKey(name); + if (cvar != NULL && *cvar != NULL) { - case NAME_Team: info.TeamChanged(atoi(str)); break; - case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known - case NAME_PlayerClass: info.PlayerClassChanged(str); break; - default: - val.String = str; - (*cvar)->SetGenericRep(val, CVAR_String); - break; + switch (name) + { + case NAME_Team: info.TeamChanged(atoi(str)); break; + case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known + case NAME_PlayerClass: info.PlayerClassChanged(str); break; + default: + val.String = str; + (*cvar)->SetGenericRep(val, CVAR_String); + break; + } } } } - if (str != NULL) - { - delete[] str; - } } CCMD (playerinfo) diff --git a/src/d_player.h b/src/d_player.h index f288f64f9..61a14691f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -371,8 +371,8 @@ struct userinfo_t : TMap int ColorSetChanged(int setnum); }; -void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin); -void WriteUserInfo(FArchive &arc, userinfo_t &info); +void ReadUserInfo(FSerializer &arc, userinfo_t &info, FString &skin); +void WriteUserInfo(FSerializer &arc, userinfo_t &info); // // Extended player object info: player_t @@ -384,7 +384,7 @@ public: ~player_t(); player_t &operator= (const player_t &p); - void Serialize(FArchive &arc); + void Serialize(FSerializer &arc); size_t FixPointers (const DObject *obj, DObject *replacement); size_t PropagateMark(); @@ -542,8 +542,6 @@ public: // Bookkeeping on players - state. extern player_t players[MAXPLAYERS]; -FArchive &operator<< (FArchive &arc, player_t *&p); - void P_CheckPlayerSprite(AActor *mo, int &spritenum, DVector2 &scale); inline void AActor::SetFriendPlayer(player_t *player) diff --git a/src/d_protocol.cpp b/src/d_protocol.cpp index df6f9f23a..6d7200f8c 100644 --- a/src/d_protocol.cpp +++ b/src/d_protocol.cpp @@ -38,7 +38,7 @@ #include "doomdef.h" #include "doomstat.h" #include "cmdlib.h" -#include "farchive.h" +#include "serializer.h" char *ReadString (BYTE **stream) @@ -287,27 +287,33 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream) return int(*stream - start); } -FArchive &operator<< (FArchive &arc, ticcmd_t &cmd) +FSerializer &Serialize(FSerializer &arc, const char *key, ticcmd_t &cmd, ticcmd_t *def) { - return arc << cmd.consistancy << cmd.ucmd; + if (arc.BeginObject(key)) + { + arc("consistency", cmd.consistancy) + ("ucmd", cmd.ucmd) + .EndObject(); + } + return arc; } -FArchive &operator<< (FArchive &arc, usercmd_t &cmd) +FSerializer &Serialize(FSerializer &arc, const char *key, usercmd_t &cmd, usercmd_t *def) { - BYTE bytes[256]; - BYTE *stream = bytes; - if (arc.IsStoring ()) + // This used packed data with the old serializer but that's totally counterproductive when + // having a text format that is human-readable. So this compression has been undone here. + // The few bytes of file size it saves are not worth the obfuscation. + + if (arc.BeginObject(key)) { - BYTE len = PackUserCmd (&cmd, NULL, &stream); - arc << len; - arc.Write (bytes, len); - } - else - { - BYTE len; - arc << len; - arc.Read (bytes, len); - UnpackUserCmd (&cmd, NULL, &stream); + arc("buttons", cmd.buttons) + ("pitch", cmd.pitch) + ("yaw", cmd.yaw) + ("roll", cmd.roll) + ("forwardmove", cmd.forwardmove) + ("sidemove", cmd.sidemove) + ("upmove", cmd.upmove) + .EndObject(); } return arc; } diff --git a/src/d_protocol.h b/src/d_protocol.h index 61f7377e3..2813b14dc 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -72,10 +72,6 @@ struct usercmd_t short upmove; }; -class FArchive; - -FArchive &operator<< (FArchive &arc, usercmd_t &cmd); - // When transmitted, the above message is preceded by a byte // indicating which fields are actually present in the message. enum diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 5142a3c4e..7e819629c 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -35,7 +35,4 @@ struct ticcmd_t SWORD consistancy; // checks for net game }; - -FArchive &operator<< (FArchive &arc, ticcmd_t &cmd); - #endif // __D_TICCMD_H__ diff --git a/src/dthinker.h b/src/dthinker.h index d423c3454..4785c0035 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -96,7 +96,6 @@ private: static void DestroyThinkersInList (FThinkerList &list); static void DestroyMostThinkersInList (FThinkerList &list, int stat); static int TickThinkers (FThinkerList *list, FThinkerList *dest); // Returns: # of thinkers ticked - static void SaveList(FArchive &arc, DThinker *node); static void SaveList(FSerializer &arc, DThinker *node); void Remove(); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index e2178f995..59d5f8f04 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -576,7 +576,7 @@ static void SpawnExtraPlayers(); void P_SerializePlayers(FSerializer &arc, bool skipload) { - BYTE numPlayers, numPlayersNow; + int numPlayers, numPlayersNow; int i; // Count the number of players present right now. @@ -588,35 +588,45 @@ void P_SerializePlayers(FSerializer &arc, bool skipload) } } -#if 0 if (arc.isWriting()) { // Record the number of players in this save. - arc << numPlayersNow; - - // Record each player's name, followed by their data. - for (i = 0; i < MAXPLAYERS; ++i) + arc("numplayers", numPlayersNow); + if (arc.BeginArray("players")) { - if (playeringame[i]) + // Record each player's name, followed by their data. + for (i = 0; i < MAXPLAYERS; ++i) { - arc.WriteString(players[i].userinfo.GetName()); - players[i].Serialize(arc); + if (playeringame[i]) + { + if (arc.BeginObject(nullptr)) + { + const char *n = players[i].userinfo.GetName(); + arc.StringPtr("playername", n); + players[i].Serialize(arc); + arc.EndObject(); + } + } } + arc.EndArray(); } } else { - arc << numPlayers; + arc("numplayers", numPlayers); - // If there is only one player in the game, they go to the - // first player present, no matter what their name. - if (numPlayers == 1) + if (arc.BeginArray("players")) { - ReadOnePlayer(arc, skipload); - } - else - { - ReadMultiplePlayers(arc, numPlayers, numPlayersNow, skipload); + // If there is only one player in the game, they go to the + // first player present, no matter what their name. + if (numPlayers == 1) + { + ReadOnePlayer(arc, skipload); + } + else + { + ReadMultiplePlayers(arc, numPlayers, numPlayersNow, skipload); + } } if (!skipload && numPlayersNow > numPlayers) { @@ -625,7 +635,6 @@ void P_SerializePlayers(FSerializer &arc, bool skipload) // Redo pitch limits, since the spawned player has them at 0. players[consoleplayer].SendPitchLimits(); } -#endif } //========================================================================== @@ -636,39 +645,39 @@ void P_SerializePlayers(FSerializer &arc, bool skipload) static void ReadOnePlayer(FSerializer &arc, bool skipload) { -#if 0 int i; - char *name = NULL; + const char *name = NULL; bool didIt = false; - arc << name; - - for (i = 0; i < MAXPLAYERS; ++i) + if (arc.BeginObject(nullptr)) { - if (playeringame[i]) + arc.StringPtr("playername", name); + + for (i = 0; i < MAXPLAYERS; ++i) { - if (!didIt) + if (playeringame[i]) { - didIt = true; - player_t playerTemp; - playerTemp.Serialize(arc); - if (!skipload) + if (!didIt) { - CopyPlayer(&players[i], &playerTemp, name); + didIt = true; + player_t playerTemp; + playerTemp.Serialize(arc); + if (!skipload) + { + CopyPlayer(&players[i], &playerTemp, name); + } } - } - else - { - if (players[i].mo != NULL) + else { - players[i].mo->Destroy(); - players[i].mo = NULL; + if (players[i].mo != NULL) + { + players[i].mo->Destroy(); + players[i].mo = NULL; + } } } } } - delete[] name; -#endif } //========================================================================== @@ -679,10 +688,9 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload) static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload) { -#if 0 // For two or more players, read each player into a temporary array. int i, j; - char **nametemp = new char *[numPlayers]; + const char **nametemp = new const char *[numPlayers]; player_t *playertemp = new player_t[numPlayers]; BYTE *tempPlayerUsed = new BYTE[numPlayers]; BYTE playerUsed[MAXPLAYERS]; @@ -690,8 +698,11 @@ static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayers for (i = 0; i < numPlayers; ++i) { nametemp[i] = NULL; - arc << nametemp[i]; - playertemp[i].Serialize(arc); + if (arc.BeginObject(nullptr)) + { + arc.StringPtr("playername", nametemp[i]); + playertemp[i].Serialize(arc); + } tempPlayerUsed[i] = 0; } for (i = 0; i < MAXPLAYERS; ++i) @@ -769,12 +780,7 @@ static void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayers delete[] tempPlayerUsed; delete[] playertemp; - for (i = 0; i < numPlayers; ++i) - { - delete[] nametemp[i]; - } delete[] nametemp; -#endif } //========================================================================== @@ -961,7 +967,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) AM_SerializeMarkers(arc); FRemapTable::StaticSerializeTranslations(arc); FCanvasTextureInfo::Serialize(arc); - //P_SerializePlayers(arc, hubLoad); + P_SerializePlayers(arc, hubload); P_SerializeSounds(arc); if (arc.isReading()) { diff --git a/src/p_user.cpp b/src/p_user.cpp index 57846dea4..3c3cdf135 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3000,18 +3000,17 @@ void P_UnPredictPlayer () } } -void player_t::Serialize(FArchive &arc) +void player_t::Serialize(FSerializer &arc) { -#if 0 - int i; FString skinname; - arc << cls - << mo - << camera - << playerstate - << cmd; - if (arc.IsLoading()) + arc("class", cls) + ("mo", mo) + ("camera", camera) + ("playerstate", playerstate) + ("cmd", cmd); + + if (arc.isReading()) { ReadUserInfo(arc, userinfo, skinname); } @@ -3019,78 +3018,80 @@ void player_t::Serialize(FArchive &arc) { WriteUserInfo(arc, userinfo); } - arc << DesiredFOV << FOV - << viewz - << viewheight - << deltaviewheight - << bob - << Vel - << centering - << health - << inventorytics; - arc << fragcount - << spreecount - << multicount - << lastkilltime - << ReadyWeapon << PendingWeapon - << cheats - << refire - << inconsistant - << killcount - << itemcount - << secretcount - << damagecount - << bonuscount - << hazardcount - << poisoncount - << poisoner - << attacker - << extralight - << fixedcolormap << fixedlightlevel - << morphTics - << MorphedPlayerClass - << MorphStyle - << MorphExitFlash - << PremorphWeapon - << chickenPeck - << jumpTics - << respawn_time - << air_finished - << turnticks - << oldbuttons; - arc << hazardtype - << hazardinterval; - arc << Bot; - arc << BlendR - << BlendG - << BlendB - << BlendA; - arc << WeaponState; - arc << LogText - << ConversationNPC - << ConversationPC - << ConversationNPCAngle.Degrees - << ConversationFaceTalker; - for (i = 0; i < MAXPLAYERS; i++) - arc << frags[i]; + arc("desiredfov", DesiredFOV) + ("fov", FOV) + ("viewz", viewz) + ("viewheight", viewheight) + ("deltaviewheight", deltaviewheight) + ("bob", bob) + ("vel", Vel) + ("centering", centering) + ("health", health) + ("inventorytics", inventorytics) + ("fragcount", fragcount) + ("spreecount", spreecount) + ("multicount", multicount) + ("lastkilltime", lastkilltime) + ("readyweapon", ReadyWeapon) + ("pendingweapon", PendingWeapon) + ("cheats", cheats) + ("refire", refire) + ("inconsistant", inconsistant) + ("killcount", killcount) + ("itemcount", itemcount) + ("secretcount", secretcount) + ("damagecount", damagecount) + ("bonuscount", bonuscount) + ("hazardcount", hazardcount) + ("poisoncount", poisoncount) + ("poisoner", poisoner) + ("attacker", attacker) + ("extralight", extralight) + ("fixedcolormap", fixedcolormap) + ("fixedlightlevel", fixedlightlevel) + ("morphTics", morphTics) + ("morphedplayerclass", MorphedPlayerClass) + ("morphstyle", MorphStyle) + ("morphexitflash", MorphExitFlash) + ("premorphweapon", PremorphWeapon) + ("chickenpeck", chickenPeck) + ("jumptics", jumpTics) + ("respawntime", respawn_time) + ("airfinished", air_finished) + ("turnticks", turnticks) + ("oldbuttons", oldbuttons) + ("hazardtype", hazardtype) + ("hazardinterval", hazardinterval) + ("bot", Bot) + ("blendr", BlendR) + ("blendg", BlendG) + ("blendb", BlendB) + ("blenda", BlendA) + ("weaponstate", WeaponState) + ("logtext", LogText) + ("conversionnpc", ConversationNPC) + ("conversionpc", ConversationPC) + ("conversionnpcangle", ConversationNPCAngle) + ("conversionfacetalker", ConversationFaceTalker) + .Array("frags", frags, MAXPLAYERS) + ("psprites", psprites) + ("currentplayerclass", CurrentPlayerClass) + ("crouchfactor", crouchfactor) + ("crouching", crouching) + ("crouchdir", crouchdir) + ("crouchviewdelta", crouchviewdelta) + ("original_cmd", original_cmd) + ("original_oldbuttons", original_oldbuttons) + ("poisontype", poisontype) + ("poisonpaintype", poisonpaintype) + ("timefreezer", timefreezer) + ("settings_controller", settings_controller) + ("onground", onground) + ("musinfoactor", MUSINFOactor) + ("musinfotics", MUSINFOtics); - arc << psprites; - - arc << CurrentPlayerClass; - - arc << crouchfactor - << crouching - << crouchdir - << crouchviewdelta - << original_cmd - << original_oldbuttons; - arc << poisontype << poisonpaintype; - arc << timefreezer; - arc << settings_controller; - arc << onground; - - if (arc.IsLoading ()) + if (arc.isWriting ()) { // If the player reloaded because they pressed +use after dying, we // don't want +use to still be down after the game is loaded. @@ -3101,8 +3102,6 @@ void player_t::Serialize(FArchive &arc) { userinfo.SkinChanged(skinname, CurrentPlayerClass); } - arc << MUSINFOactor << MUSINFOtics; -#endif } bool P_IsPlayerTotallyFrozen(const player_t *player) diff --git a/src/serializer.cpp b/src/serializer.cpp index 511bc6086..939c3fc7d 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -1136,12 +1136,22 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje if (value != nullptr) { int ndx; - int *pndx = arc.w->mObjectMap.CheckKey(value); - if (pndx != nullptr) ndx = *pndx; + if (value == WP_NOCHANGE) + { + ndx = -1; + } else { - ndx = arc.w->mDObjects.Push(value); - arc.w->mObjectMap[value] = ndx; + int *pndx = arc.w->mObjectMap.CheckKey(value); + if (pndx != nullptr) + { + ndx = *pndx; + } + else + { + ndx = arc.w->mDObjects.Push(value); + arc.w->mObjectMap[value] = ndx; + } } Serialize(arc, key, ndx, nullptr); } @@ -1149,8 +1159,15 @@ FSerializer &Serialize(FSerializer &arc, const char *key, DObject *&value, DObje else { auto val = arc.r->FindKey(key); - if (val != nullptr) + if (val != nullptr && val->IsInt()) { + if (val->GetInt() == -1) + { + value = WP_NOCHANGE; + } + else + { + } } else if (!retcode) { @@ -1302,7 +1319,14 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor if (!arc.w->inObject() || def == nullptr || clst != *def) { arc.WriteKey(key); - arc.w->mWriter.String(clst->TypeName.GetChars()); + if (clst == nullptr) + { + arc.w->mWriter.Null(); + } + else + { + arc.w->mWriter.String(clst->TypeName.GetChars()); + } } } else @@ -1314,6 +1338,10 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClassActor { clst = PClass::FindActor(val->GetString()); } + else if (val->IsNull()) + { + clst = nullptr; + } else { I_Error("string type expected for '%s'", key); @@ -1337,7 +1365,14 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl if (!arc.w->inObject() || def == nullptr || clst != *def) { arc.WriteKey(key); - arc.w->mWriter.String(clst->TypeName.GetChars()); + if (clst == nullptr) + { + arc.w->mWriter.Null(); + } + else + { + arc.w->mWriter.String(clst->TypeName.GetChars()); + } } } else @@ -1349,6 +1384,10 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, PClass *&cl { clst = PClass::FindClass(val->GetString()); } + else if (val->IsNull()) + { + clst = nullptr; + } else { I_Error("string type expected for '%s'", key); diff --git a/src/serializer.h b/src/serializer.h index 7b35d4d9a..12edc2e99 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -7,6 +7,9 @@ #include "r_defs.h" #include "resourcefiles/file_zip.h" +struct ticcmd_t; +struct usercmd_t; + struct FWriter; struct FReader; @@ -161,6 +164,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundID *def); FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def); FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def); +FSerializer &Serialize(FSerializer &arc, const char *key, ticcmd_t &sid, ticcmd_t *def); +FSerializer &Serialize(FSerializer &arc, const char *key, usercmd_t &cmd, usercmd_t *def); template FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **) @@ -220,8 +225,10 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDoorAnimat template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr, char **def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&font, FFont **def); - -template<> FSerializer &Serialize(FSerializer &arc, const char *key, sector_t *&value, sector_t **defval); +template<> inline FSerializer &Serialize(FSerializer &arc, const char *key, PClassPlayerPawn *&clst, PClassPlayerPawn **def) +{ + return Serialize(arc, key, (PClassActor *&)clst, (PClassActor **)def); +} FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def, bool *retcode); template<> inline FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def) diff --git a/src/zzz_old.cpp b/src/zzz_old.cpp index 92dd10877..e6193b3aa 100644 --- a/src/zzz_old.cpp +++ b/src/zzz_old.cpp @@ -59,7 +59,7 @@ void P_SerializeACSScriptNumber(FArchive &arc, int &scriptnum, bool was2byte) #if 0 // still needed as reference. -FArchive &FArchive::ReadObject(DObject* &obj, PClass *wanttype) +FCrap &FCrap::ReadObject(DObject* &obj, PClass *wanttype) { BYTE objHead; const PClass *type;