serialize cvars

This commit is contained in:
Ricardo Luís Vaz Silva 2023-11-25 22:27:28 -03:00 committed by Rachael Alexanderson
parent 74ace89d6e
commit aed85a25a2
9 changed files with 115 additions and 5 deletions

View file

@ -218,6 +218,9 @@ public:
void* GetExtraDataPointer();
int pnum = -1;
FName userinfoName;
protected:
virtual void DoSet (UCVarValue value, ECVarType type) = 0;
virtual void InstantiateZSCVar()

View file

@ -1757,6 +1757,19 @@ void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointer
}
}
bool FSerializer::ReadOptionalInt(const char * key, int &into)
{
if(!isReading()) return false;
auto val = r->FindKey(key);
if(val && val->IsInt())
{
into = val->GetInt();
return true;
}
return false;
}
#include "renderstyle.h"
FSerializer& Serialize(FSerializer& arc, const char* key, FRenderStyle& style, FRenderStyle* def)
{

View file

@ -108,6 +108,10 @@ public:
FSerializer &AddString(const char *key, const char *charptr);
const char *GetString(const char *key);
FSerializer &ScriptNum(const char *key, int &num);
bool ReadOptionalInt(const char * key, int &into);
bool isReading() const
{
return r != nullptr;

View file

@ -393,7 +393,7 @@ void D_SetupUserInfo ()
// Reset everybody's userinfo to a default state.
for (i = 0; i < MAXPLAYERS; i++)
{
players[i].userinfo.Reset();
players[i].userinfo.Reset(i);
}
// Initialize the console player's user info
coninfo = &players[consoleplayer].userinfo;
@ -426,7 +426,7 @@ void D_SetupUserInfo ()
R_BuildPlayerTranslation(consoleplayer);
}
void userinfo_t::Reset()
void userinfo_t::Reset(int pnum)
{
// Clear this player's userinfo.
TMapIterator<FName, FBaseCVar *> it(*this);
@ -469,6 +469,9 @@ void userinfo_t::Reset()
newcvar->SetExtraDataPointer(cvar); // store backing cvar
}
newcvar->pnum = pnum;
newcvar->userinfoName = cvarname;
Insert(cvarname, newcvar);
}
}
@ -981,7 +984,6 @@ void ReadUserInfo(FSerializer &arc, userinfo_t &info, FString &skin)
const char *key;
const char *str;
info.Reset();
skin = "";
if (arc.BeginObject("userinfo"))
{

View file

@ -1981,8 +1981,12 @@ void C_SerializeCVars(FSerializer& arc, const char* label, uint32_t filter)
}
void SetupLoadingCVars();
void FinishLoadingCVars();
void G_DoLoadGame ()
{
SetupLoadingCVars();
bool hidecon;
if (gameaction != ga_autoloadgame)
@ -2125,6 +2129,7 @@ void G_DoLoadGame ()
// load a base level
bool demoplaybacksave = demoplayback;
G_InitNew(map.GetChars(), false);
FinishLoadingCVars();
demoplayback = demoplaybacksave;
savegamerestore = false;

View file

@ -202,7 +202,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam)
}
players[i].~player_t();
::new(&players[i]) player_t;
players[i].userinfo.Reset();
players[i].userinfo.Reset(i);
playeringame[i] = false;
}

View file

@ -269,7 +269,7 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
return *static_cast<FBoolCVar *>(*CheckKey(NAME_Wi_NoAutostartMap));
}
void Reset();
void Reset(int pnum);
int TeamChanged(int team);
int SkinChanged(const char *skinname, int playerclass);
int SkinNumChanged(int skinnum);

View file

@ -1620,6 +1620,7 @@ void player_t::Serialize(FSerializer &arc)
if (arc.isReading())
{
userinfo.Reset(mo->Level->PlayerNum(this));
ReadUserInfo(arc, userinfo, skinname);
}
else

View file

@ -646,6 +646,15 @@ static int propcmp(const void * a, const void * b)
//==========================================================================
void InitImports();
struct UserInfoCVarNamePlayer
{
FBaseCVar** addr;
FString name;
int pnum;
};
TArray<UserInfoCVarNamePlayer> LoadGameUserInfoCVars;
void InitThingdef()
{
// Some native types need size and serialization information added before the scripts get compiled.
@ -803,6 +812,79 @@ void InitThingdef()
auto fspp = NewStruct("FSpawnParticleParams", nullptr);
fspp->Size = sizeof(FSpawnParticleParams);
fspp->Align = alignof(FSpawnParticleParams);
auto cvst = NewStruct("CVar", nullptr, true);
NewPointer(cvst, false)->InstallHandlers(
[](FSerializer &arc, const char *key, const void *addr)
{
const FBaseCVar * self = *(const FBaseCVar**)addr;
if(self)
{
arc.BeginObject(key);
if(self->pnum != -1)
{
int32_t pnum = self->pnum;
FName name = self->userinfoName;
arc("name", name);
arc("player", pnum);
}
else
{
FString name = self->GetName();
arc("name", name);
}
arc.EndObject();
}
},
[](FSerializer &arc, const char *key, void *addr)
{
FBaseCVar ** self = (FBaseCVar**)addr;
FString name;
arc.BeginObject(key);
arc("name", name);
FBaseCVar * backing = FindCVar(name.GetChars(), nullptr);
if(!backing)
{
I_Error("Attempt to load pointer to inexisted CVar '%s'", name.GetChars());
}
else if((backing->GetFlags() & (CVAR_USERINFO|CVAR_IGNORE)) == CVAR_USERINFO)
{
if(int pnum; arc.ReadOptionalInt("player", pnum))
{
*self = nullptr;
LoadGameUserInfoCVars.Push({self, name, pnum}); // this needs to be done later, since userinfo isn't loaded yet
arc.EndObject();
return true;
}
}
*self = backing;
arc.EndObject();
return true;
}
);
}
void SetupLoadingCVars()
{
LoadGameUserInfoCVars.Clear();
}
void FinishLoadingCVars()
{
for(UserInfoCVarNamePlayer &cvar : LoadGameUserInfoCVars)
{
(*cvar.addr) = GetCVar(cvar.pnum, cvar.name.GetChars());
}
}
void SynthesizeFlagFields()