- converted player serializer and everything it needs.

This means that everything belonging to the level snapshot will be generated in the JSON output.
This commit is contained in:
Christoph Oelckers 2016-09-21 01:18:29 +02:00
parent 3a1191281f
commit da83d9e2bd
11 changed files with 265 additions and 213 deletions

View file

@ -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<FName, FBaseCVar *> it(info);
TMap<FName, FBaseCVar *>::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<FName, FBaseCVar *> it(info);
TMap<FName, FBaseCVar *>::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)

View file

@ -371,8 +371,8 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
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)

View file

@ -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;
}

View file

@ -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

View file

@ -35,7 +35,4 @@ struct ticcmd_t
SWORD consistancy; // checks for net game
};
FArchive &operator<< (FArchive &arc, ticcmd_t &cmd);
#endif // __D_TICCMD_H__

View file

@ -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();

View file

@ -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())
{

View file

@ -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)

View file

@ -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);

View file

@ -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<class T>
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)

View file

@ -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;