# Conflicts:
#	src/CMakeLists.txt
#	src/g_level.cpp
#	src/p_saveg.cpp
#	src/r_defs.h
#	src/version.h

(note that this commit will not compile!)
This commit is contained in:
Christoph Oelckers 2016-09-24 00:40:15 +02:00
commit 6bfbe30b99
201 changed files with 21931 additions and 6730 deletions

View file

@ -1178,7 +1178,6 @@ set (PCH_SOURCES
dthinker.cpp
edata.cpp
f_wipe.cpp
farchive.cpp
files.cpp
g_doomedmap.cpp
g_game.cpp
@ -1259,6 +1258,7 @@ set (PCH_SOURCES
po_man.cpp
portal.cpp
r_utility.cpp
serializer.cpp
sc_man.cpp
st_stuff.cpp
statistics.cpp
@ -1360,7 +1360,6 @@ set (PCH_SOURCES
thingdef/thingdef_properties.cpp
thingdef/thingdef_states.cpp
xlat/parse_xlat.cpp
fragglescript/t_fspic.cpp
fragglescript/t_func.cpp
fragglescript/t_load.cpp
fragglescript/t_oper.cpp
@ -1564,6 +1563,7 @@ source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DI
source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+")
source_group("Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+")
source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+")
source_group("RapidJSON" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rapidjson/.+")
source_group("OpenGL Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/.+")
source_group("OpenGL Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/data/.+")
source_group("OpenGL Renderer\\Dynamic Lights" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/dynlights/.+")

View file

@ -583,7 +583,8 @@ public:
void Destroy ();
~AActor ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void PostSerialize();
static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
@ -988,7 +989,7 @@ public:
double Speed;
double FloatSpeed;
WORD sprite; // used to find patch_t and flip value
int sprite; // used to find patch_t and flip value
BYTE frame; // sprite frame to draw
DVector2 Scale; // Scaling values; 1 is normal size
FRenderStyle RenderStyle; // Style to draw this actor with
@ -1183,8 +1184,9 @@ public:
private:
static AActor *TIDHash[128];
static inline int TIDHASH (int key) { return key & 127; }
public:
static FSharedStringArena mStringPropertyData;
private:
friend class FActorIterator;
friend bool P_IsTIDUsed(int tid);

View file

@ -38,7 +38,7 @@
#include "gi.h"
#include "p_setup.h"
#include "c_bind.h"
#include "farchive.h"
#include "serializer.h"
#include "r_renderer.h"
#include "r_sky.h"
#include "sbar.h"
@ -3106,13 +3106,14 @@ void AM_Drawer ()
//
//=============================================================================
void AM_SerializeMarkers(FArchive &arc)
void AM_SerializeMarkers(FSerializer &arc)
{
arc << markpointnum;
for (int i=0; i<AM_NUMMARKPOINTS; i++)
if (arc.BeginObject("automarkers"))
{
arc << markpoints[i].x << markpoints[i].y;
arc("markpointnum", markpointnum)
.Array("markpoints", &markpoints[0].x, AM_NUMMARKPOINTS*2) // write as a double array.
("scale_mtof", scale_mtof)
("scale_ftom", scale_ftom)
.EndObject();
}
arc << scale_mtof;
arc << scale_ftom;
}

View file

@ -23,7 +23,7 @@
#define __AMMAP_H__
struct event_t;
class FArchive;
class FSerializer;
void AM_StaticInit();
@ -45,7 +45,7 @@ void AM_Stop (void);
void AM_NewResolution ();
void AM_ToggleMap ();
void AM_LevelInit ();
void AM_SerializeMarkers(FArchive &arc);
void AM_SerializeMarkers(FSerializer &arc);
#endif

View file

@ -12,7 +12,7 @@
#include "cmdlib.h"
#include "teaminfo.h"
#include "d_net.h"
#include "farchive.h"
#include "serializer.h"
#include "d_player.h"
IMPLEMENT_POINTY_CLASS(DBot)
@ -55,31 +55,44 @@ void DBot::Clear ()
old = { 0, 0 };
}
void DBot::Serialize (FArchive &arc)
FSerializer &Serialize(FSerializer &arc, const char *key, botskill_t &skill, botskill_t *def)
{
if (arc.BeginObject(key))
{
arc("aiming", skill.aiming)
("perfection", skill.perfection)
("reaction", skill.reaction)
("isp", skill.isp)
.EndObject();
}
return arc;
}
void DBot::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << player
<< Angle
<< dest
<< prev
<< enemy
<< missile
<< mate
<< last_mate
<< skill
<< t_active
<< t_respawn
<< t_strafe
<< t_react
<< t_fight
<< t_roam
<< t_rocket
<< first_shot
<< sleft
<< allround
<< increase
<< old;
arc("player", player)
("angle", Angle)
("dest", dest)
("prev", prev)
("enemy", enemy)
("missile", missile)
("mate", mate)
("lastmate", last_mate)
("skill", skill)
("active", t_active)
("respawn", t_respawn)
("strafe", t_strafe)
("react", t_react)
("fight", t_fight)
("roam", t_roam)
("rocket", t_rocket)
("firstshot", first_shot)
("sleft", sleft)
("allround", allround)
("increase", increase)
("old", old);
}
void DBot::Tick ()
@ -193,11 +206,6 @@ CCMD (listbots)
Printf ("> %d bots\n", count);
}
FArchive &operator<< (FArchive &arc, botskill_t &skill)
{
return arc << skill.aiming << skill.perfection << skill.reaction << skill.isp;
}
// set the bot specific weapon information
// This is intentionally not in the weapon definition anymore.
void InitBotStuff()

View file

@ -58,8 +58,6 @@ struct botskill_t
int isp; //Instincts of Self Preservation. Personality
};
FArchive &operator<< (FArchive &arc, botskill_t &skill);
enum
{
BOTINUSE_No,
@ -142,7 +140,7 @@ public:
DBot ();
void Clear ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
//(b_think.cpp)

View file

@ -811,7 +811,7 @@ CCMD (load)
return;
}
FString fname = argv[1];
DefaultExtension (fname, ".zds");
DefaultExtension (fname, "." SAVEGAME_EXT);
G_LoadGame (fname);
}
@ -831,7 +831,7 @@ CCMD (save)
return;
}
FString fname = argv[1];
DefaultExtension (fname, ".zds");
DefaultExtension (fname, "." SAVEGAME_EXT);
G_SaveGame (fname, argv.argc() > 2 ? argv[2] : argv[1]);
}

View file

@ -53,7 +53,7 @@
#include "v_text.h"
#include "d_net.h"
#include "d_main.h"
#include "farchive.h"
#include "serializer.h"
// MACROS ------------------------------------------------------------------
@ -65,7 +65,7 @@ class DWaitingCommand : public DThinker
public:
DWaitingCommand (const char *cmd, int tics);
~DWaitingCommand ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
private:
@ -189,10 +189,11 @@ static const char *KeyConfCommands[] =
IMPLEMENT_CLASS (DWaitingCommand)
void DWaitingCommand::Serialize (FArchive &arc)
void DWaitingCommand::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Command << TicsLeft;
arc("command", Command)
("ticsleft", TicsLeft);
}
DWaitingCommand::DWaitingCommand ()

View file

@ -69,7 +69,7 @@
#include "i_system.h"
#include "doomerrors.h"
#include "p_effect.h"
#include "farchive.h"
#include "serializer.h"
#include "vmbuilder.h"
// [SO] Just the way Randy said to do it :)
@ -3198,8 +3198,8 @@ PClassActor *ADehackedPickup::DetermineType ()
return NULL;
}
void ADehackedPickup::Serialize(FArchive &arc)
void ADehackedPickup::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << droppedbymonster;
arc("droppedbymonster", droppedbymonster);
}

View file

@ -48,7 +48,8 @@ public:
bool TryPickup (AActor *&toucher);
void PlayPickupSound (AActor *toucher);
void DoPickupSpecial (AActor *toucher);
void Serialize(FArchive &arc);
void Serialize(FSerializer &arc);
private:
PClassActor *DetermineType ();
AInventory *RealPickup;

View file

@ -2580,7 +2580,7 @@ void D_DoomMain (void)
{
FString file(v);
FixPathSeperator (file);
DefaultExtension (file, ".zds");
DefaultExtension (file, "." SAVEGAME_EXT);
G_LoadGame (file);
}

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");
@ -880,52 +880,60 @@ 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)
{
if (arc.BeginObject("userinfo"))
{
TMapIterator<FName, FBaseCVar *> it(info);
TMap<FName, FBaseCVar *>::Pair *pair;
FName name;
FString name;
const char *string;
UCVarValue val;
int i;
while (it.NextPair(pair))
{
name = pair->Key;
arc << name;
switch (name.GetIndex())
name.ToLower();
switch (pair->Key.GetIndex())
{
case NAME_Skin:
arc.WriteString(skins[info.GetSkin()].name);
string = skins[info.GetSkin()].name;
break;
case NAME_PlayerClass:
i = info.GetPlayerClassNum();
arc.WriteString(i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars());
string = (i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars());
break;
default:
val = pair->Value->GetGenericRep(CVAR_String);
arc.WriteString(val.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"))
{
while ((key = arc.GetKey()))
{
arc.StringPtr(nullptr, str);
name = key;
cvar = info.CheckKey(name);
arc << str;
if (cvar != NULL && *cvar != NULL)
{
switch (name)
@ -940,9 +948,7 @@ void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin)
}
}
}
if (str != NULL)
{
delete[] str;
arc.EndObject();
}
}

View file

@ -102,7 +102,8 @@ class APlayerPawn : public AActor
DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
HAS_OBJECT_POINTERS
public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void PostBeginPlay();
virtual void Tick();
@ -374,8 +375,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
@ -387,7 +388,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();
@ -545,8 +546,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

@ -48,7 +48,7 @@
#include "g_level.h"
#include "colormatcher.h"
#include "b_bot.h"
#include "farchive.h"
#include "serializer.h"
FDecalLib DecalLibrary;
@ -113,7 +113,7 @@ struct DDecalThinker : public DThinker
HAS_OBJECT_POINTERS
public:
DDecalThinker (DBaseDecal *decal) : DThinker (STAT_DECALTHINKER), TheDecal (decal) {}
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
TObjPtr<DBaseDecal> TheDecal;
protected:
DDecalThinker () : DThinker (STAT_DECALTHINKER) {}
@ -123,10 +123,10 @@ IMPLEMENT_POINTY_CLASS (DDecalThinker)
DECLARE_POINTER (TheDecal)
END_POINTERS
void DDecalThinker::Serialize (FArchive &arc)
void DDecalThinker::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TheDecal;
arc("thedecal", TheDecal);
}
struct FDecalFaderAnim : public FDecalAnimator
@ -143,7 +143,7 @@ class DDecalFader : public DDecalThinker
DECLARE_CLASS (DDecalFader, DDecalThinker)
public:
DDecalFader (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
int TimeToStartDecay;
@ -168,7 +168,7 @@ class DDecalColorer : public DDecalThinker
DECLARE_CLASS (DDecalColorer, DDecalThinker)
public:
DDecalColorer (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
int TimeToStartDecay;
@ -194,7 +194,7 @@ class DDecalStretcher : public DDecalThinker
DECLARE_CLASS (DDecalStretcher, DDecalThinker)
public:
DDecalStretcher (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
int TimeToStart;
@ -225,7 +225,7 @@ class DDecalSlider : public DDecalThinker
DECLARE_CLASS (DDecalSlider, DDecalThinker)
public:
DDecalSlider (DBaseDecal *decal) : DDecalThinker (decal) {}
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
int TimeToStart;
@ -1153,10 +1153,12 @@ FDecalAnimator::~FDecalAnimator ()
IMPLEMENT_CLASS (DDecalFader)
void DDecalFader::Serialize (FArchive &arc)
void DDecalFader::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TimeToStartDecay << TimeToEndDecay << StartTrans;
arc("starttime", TimeToStartDecay)
("endtime", TimeToEndDecay)
("starttrans", StartTrans);
}
void DDecalFader::Tick ()
@ -1200,18 +1202,18 @@ DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const
IMPLEMENT_CLASS (DDecalStretcher)
void DDecalStretcher::Serialize (FArchive &arc)
void DDecalStretcher::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TimeToStart
<< TimeToStop
<< GoalX
<< StartX
<< bStretchX
<< GoalY
<< StartY
<< bStretchY
<< bStarted;
arc("starttime", TimeToStart)
("endtime", TimeToStop)
("goalx", GoalX)
("startx", StartX)
("stretchx", bStretchX)
("goaly", GoalY)
("starty", StartY)
("stretchy", bStretchY)
("started", bStarted);
}
DThinker *FDecalStretcherAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const
@ -1288,16 +1290,14 @@ void DDecalStretcher::Tick ()
IMPLEMENT_CLASS (DDecalSlider)
void DDecalSlider::Serialize (FArchive &arc)
void DDecalSlider::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TimeToStart
<< TimeToStop
/*<< DistX*/
<< DistY
/*<< StartX*/
<< StartY
<< bStarted;
arc("starttime", TimeToStart)
("endtime", TimeToStop)
("disty", DistY)
("starty", StartY)
("started", bStarted);
}
DThinker *FDecalSliderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const
@ -1371,10 +1371,13 @@ FDecalAnimator *FDecalLib::FindAnimator (const char *name)
IMPLEMENT_CLASS (DDecalColorer)
void DDecalColorer::Serialize (FArchive &arc)
void DDecalColorer::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TimeToStartDecay << TimeToEndDecay << StartColor << GoalColor;
arc("starttime", TimeToStartDecay)
("endtime", TimeToEndDecay)
("startcolor", StartColor)
("goalcolor", GoalColor);
}
void DDecalColorer::Tick ()

View file

@ -47,7 +47,13 @@
#include "stats.h"
#include "a_sharedglobal.h"
#include "dsectoreffect.h"
#include "farchive.h"
#include "serializer.h"
//==========================================================================
//
//
//
//==========================================================================
ClassReg DObject::RegistrationInfo =
{
@ -61,6 +67,12 @@ ClassReg DObject::RegistrationInfo =
};
_DECLARE_TI(DObject)
//==========================================================================
//
//
//
//==========================================================================
CCMD (dumpactors)
{
const char *const filters[32] =
@ -95,6 +107,12 @@ CCMD (dumpactors)
}
}
//==========================================================================
//
//
//
//==========================================================================
CCMD (dumpclasses)
{
// This is by no means speed-optimized. But it's an informational console
@ -234,6 +252,12 @@ CCMD (dumpclasses)
Printf ("%d classes shown, %d omitted\n", shown, omitted);
}
//==========================================================================
//
//
//
//==========================================================================
void DObject::InPlaceConstructor (void *mem)
{
new ((EInPlace *)mem) DObject;
@ -255,6 +279,12 @@ DObject::DObject (PClass *inClass)
GC::Root = this;
}
//==========================================================================
//
//
//
//==========================================================================
DObject::~DObject ()
{
if (!PClass::bShutdown)
@ -304,11 +334,23 @@ DObject::~DObject ()
}
}
//==========================================================================
//
//
//
//==========================================================================
void DObject::Destroy ()
{
ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe;
}
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::PropagateMark()
{
const PClass *info = GetClass();
@ -330,6 +372,12 @@ size_t DObject::PropagateMark()
return 0;
}
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
{
const PClass *info = GetClass();
@ -352,6 +400,12 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
return changed;
}
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
{
DObject *probe;
@ -417,70 +471,41 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
return changed;
}
void DObject::SerializeUserVars(FArchive &arc)
//==========================================================================
//
//
//
//==========================================================================
void DObject::SerializeUserVars(FSerializer &arc)
{
PSymbolTable *symt;
FName varname;
DWORD count, j;
int *varloc = NULL;
symt = &GetClass()->Symbols;
if (arc.IsStoring())
if (arc.isWriting())
{
// Write all fields that aren't serialized by native code.
GetClass()->WriteValue(arc, this);
}
else if (SaveVersion >= 4535)
{
GetClass()->ReadValue(arc, this);
}
else
{ // Old version that only deals with ints
// Read user variables until 'None' is encountered.
arc << varname;
while (varname != NAME_None)
{
PField *var = dyn_cast<PField>(symt->FindSymbol(varname, true));
DWORD wanted = 0;
if (var != NULL && !(var->Flags & VARF_Native))
{
PType *type = var->Type;
PArray *arraytype = dyn_cast<PArray>(type);
if (arraytype != NULL)
{
wanted = arraytype->ElementCount;
type = arraytype->ElementType;
GetClass()->WriteAllFields(arc, this);
}
else
{
wanted = 1;
}
assert(type == TypeSInt32);
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->Offset);
}
count = arc.ReadCount();
for (j = 0; j < MIN(wanted, count); ++j)
{
arc << varloc[j];
}
if (wanted < count)
{
// Ignore remaining values from archive.
for (; j < count; ++j)
{
int foo;
arc << foo;
}
}
arc << varname;
}
GetClass()->ReadAllFields(arc, this);
}
}
void DObject::Serialize (FArchive &arc)
//==========================================================================
//
//
//
//==========================================================================
void DObject::Serialize(FSerializer &arc)
{
int fresh = ObjectFlags & OF_JustSpawned;
int freshdef = 0;
arc("justspawned", fresh, freshdef);
if (arc.isReading())
{
ObjectFlags |= fresh;
}
ObjectFlags |= OF_SerialSuccess;
}

View file

@ -39,7 +39,7 @@
class PClass;
class FArchive;
class FSerializer;
class DObject;
/*
@ -413,16 +413,12 @@ public:
return GC::ReadBarrier(p) == u;
}
template<class U> friend inline FArchive &operator<<(FArchive &arc, TObjPtr<U> &o);
template<class U> friend inline void GC::Mark(TObjPtr<U> &obj);
template<class U> friend FSerializer &Serialize(FSerializer &arc, const char *key, TObjPtr<U> &value, TObjPtr<U> *);
friend class DObject;
};
template<class T> inline FArchive &operator<<(FArchive &arc, TObjPtr<T> &o)
{
return arc << o.p;
}
// Use barrier_cast instead of static_cast when you need to cast
// the contents of a TObjPtr to a related type.
template<class T,class U> inline T barrier_cast(TObjPtr<U> &o)
@ -463,8 +459,9 @@ public:
inline bool IsKindOf (const PClass *base) const;
inline bool IsA (const PClass *type) const;
void SerializeUserVars(FArchive &arc);
virtual void Serialize (FArchive &arc);
void SerializeUserVars(FSerializer &arc);
virtual void Serialize(FSerializer &arc);
void ClearClass()
{
Class = NULL;

View file

@ -39,7 +39,7 @@
#include "dobject.h"
#include "i_system.h"
#include "farchive.h"
#include "serializer.h"
#include "actor.h"
#include "templates.h"
#include "autosegs.h"
@ -47,6 +47,7 @@
#include "a_pickups.h"
#include "a_weaponpiece.h"
#include "d_player.h"
#include "doomerrors.h"
#include "fragglescript/t_fs.h"
// MACROS ------------------------------------------------------------------
@ -390,7 +391,7 @@ bool PType::VisitedNodeSet::Check(const PType *node)
//
//==========================================================================
void PType::WriteValue(FArchive &ar, const void *addr) const
void PType::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
assert(0 && "Cannot write value for this type");
}
@ -401,104 +402,12 @@ void PType::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PType::ReadValue(FArchive &ar, void *addr) const
bool PType::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
assert(0 && "Cannot read value for this type");
SkipValue(ar);
return false;
}
//==========================================================================
//
// PType :: SkipValue STATIC
//
//==========================================================================
void PType::SkipValue(FArchive &ar)
{
BYTE tag;
ar << tag;
SkipValue(ar, tag);
}
void PType::SkipValue(FArchive &ar, int tag)
{
assert(ar.IsLoading() && "SkipValue passed an archive that is writing");
BYTE buff[8];
switch (tag)
{
case VAL_Zero: case VAL_One:
break;
case VAL_Int8: case VAL_UInt8:
ar.Read(buff, 1);
break;
case VAL_Int16: case VAL_UInt16:
ar.Read(buff, 2);
break;
case VAL_Int32: case VAL_UInt32: case VAL_Float32:
ar.Read(buff, 4);
break;
case VAL_Int64: case VAL_UInt64: case VAL_Float64:
ar.Read(buff, 8);
break;
case VAL_Name:
ar.ReadName();
break;
case VAL_Object:
{
DObject *skipper;
ar << skipper;
break;
}
case VAL_State:
{
FState *skipper;
ar << skipper;
break;
}
case VAL_String:
{
FString skipper;
ar << skipper;
break;
}
case VAL_Array:
{
DWORD count = ar.ReadCount();
while (count-- > 0)
{
SkipValue(ar);
}
break;
}
case VAL_Struct:
{
const char *label;
for (label = ar.ReadName(); label != NULL; label = ar.ReadName())
{
SkipValue(ar);
}
break;
}
case VAL_Class:
{
PClass *type;
for (ar.UserReadClass(type); type != NULL; ar.UserReadClass(type))
{
SkipValue(ar, VAL_Struct);
}
break;
}
}
}
//==========================================================================
//
// PType :: SetDefaultValue
@ -805,116 +714,41 @@ PInt::PInt(unsigned int size, bool unsign)
//
// PInt :: WriteValue
//
// Write the value using the minimum byte size needed to represent it. This
// means that the value as written is not necessarily of the same type as
// stored, but the signedness information is preserved.
//
//==========================================================================
void PInt::WriteValue(FArchive &ar, const void *addr) const
void PInt::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
BYTE bval;
// The process for bytes is the same whether signed or unsigned, since
// they can't be compacted into a representation with fewer bytes.
if (Size == 1)
if (Size == 8 && Unsigned)
{
bval = *(BYTE *)addr;
}
else if (Unsigned)
{
unsigned val;
if (Size == 8)
{
QWORD qval = *(QWORD *)addr;
if (qval & 0xFFFFFFFF00000000llu)
{ // Value needs 64 bits
ar.WriteByte(VAL_UInt64);
ar.WriteInt64(qval);
return;
}
// Value can fit in 32 bits or less
val = (unsigned)qval;
goto check_u32;
}
else if (Size == 4)
{
val = *(DWORD *)addr;
check_u32: if (val & 0xFFFF0000u)
{ // Value needs 32 bits
ar.WriteByte(VAL_UInt32);
ar.WriteInt32(val);
return;
}
// Value can fit in 16 bits or less
goto check_u16;
}
else// if (Size == 2)
{
val = *(WORD *)addr;
check_u16: if (val & 0xFFFFFF00u)
{ // Value needs 16 bits
ar.WriteByte(VAL_UInt16);
ar.WriteInt16(val);
return;
}
// Value can fit in 8 bits
bval = (BYTE)val;
}
}
else // Signed
{
int val;
if (Size == 8)
{
SQWORD qval = *(SQWORD *)addr;
INT_MIN;
if (qval < (-0x7FFFFFFF - 1) || qval > 0x7FFFFFFF)
{ // Value needs 64 bits
ar.WriteByte(VAL_Int64);
ar.WriteInt64(qval);
return;
}
// Value can fit in 32 bits or less
val = (int)qval;
goto check_s32;
}
else if (Size == 4)
{
val = *(SDWORD *)addr;
check_s32: if (val < -0x8000 || val > 0x7FFF)
{ // Value needs 32 bits
ar.WriteByte(VAL_Int32);
ar.WriteInt32(val);
return;
}
// Value can fit in 16 bits or less
goto check_s16;
}
else// if (Size == 2)
{
val = *(SWORD *)addr;
check_s16: if (val < -0x80 || val > 0x7F)
{ // Value needs 16 bits
ar.WriteByte(VAL_Int16);
ar.WriteInt16(val);
return;
}
// Value can fit in 8 bits
bval = (BYTE)val;
}
}
// If we get here, the value fits in a byte. Values of 0 and 1 are
// optimized away into the tag so they don't require any extra space
// to store.
if (bval & 0xFE)
{
BYTE out[2] = { Unsigned ? VAL_UInt8 : VAL_Int8, bval };
ar.Write(out, 2);
// this is a special case that cannot be represented by an int64_t.
uint64_t val = *(uint64_t*)addr;
ar(key, val);
}
else
{
ar.WriteByte(VAL_Zero + bval);
int64_t val;
switch (Size)
{
case 1:
val = Unsigned ? *(uint8_t*)addr : *(int8_t*)addr;
break;
case 2:
val = Unsigned ? *(uint16_t*)addr : *(int16_t*)addr;
break;
case 4:
val = Unsigned ? *(uint32_t*)addr : *(int32_t*)addr;
break;
case 8:
val = *(int64_t*)addr;
break;
default:
return; // something invalid
}
ar(key, val);
}
}
@ -924,47 +758,37 @@ check_s16: if (val < -0x80 || val > 0x7F)
//
//==========================================================================
bool PInt::ReadValue(FArchive &ar, void *addr) const
bool PInt::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
union
{
QWORD uval;
SQWORD sval;
};
BYTE tag;
union
{
BYTE val8;
WORD val16;
DWORD val32;
float single;
double dbl;
};
NumericValue val;
ar << tag;
switch (tag)
{
case VAL_Zero: uval = 0; break;
case VAL_One: uval = 1; break;
case VAL_Int8: ar << val8; sval = (SBYTE)val8; break;
case VAL_UInt8: ar << val8; uval = val8; break;
case VAL_Int16: ar << val16; sval = (SWORD)val16; break;
case VAL_UInt16: ar << val16; uval = val16; break;
case VAL_Int32: ar << val32; sval = (SDWORD)val32; break;
case VAL_UInt32: ar << val32; uval = val32; break;
case VAL_Int64: ar << sval; break;
case VAL_UInt64: ar << uval; break;
case VAL_Float32: ar << single; sval = (SQWORD)single; break;
case VAL_Float64: ar << dbl; sval = (SQWORD)dbl; break;
default: SkipValue(ar, tag); return false; // Incompatible type
}
ar(key, val);
if (val.type == NumericValue::NM_invalid) return false; // not found or usable
if (val.type == NumericValue::NM_float) val.signedval = (int64_t)val.floatval;
// No need to check the unsigned state here. Downcasting to smaller types will yield the same result for both.
switch (Size)
{
case 1: *(BYTE *)addr = (BYTE)uval; break;
case 2: *(WORD *)addr = (WORD)uval; break;
case 4: *(DWORD *)addr = (DWORD)uval; break;
case 8: *(QWORD *)addr = uval; break;
case 1:
*(uint8_t*)addr = (uint8_t)val.signedval;
break;
case 2:
*(uint16_t*)addr = (uint16_t)val.signedval;
break;
case 4:
*(uint32_t*)addr = (uint32_t)val.signedval;
break;
case 8:
*(uint64_t*)addr = (uint64_t)val.signedval;
break;
default:
return false; // something invalid
}
return true;
}
@ -1259,28 +1083,16 @@ void PFloat::SetSymbols(const PFloat::SymbolInitI *sym, size_t count)
//
//==========================================================================
void PFloat::WriteValue(FArchive &ar, const void *addr) const
void PFloat::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
float singleprecision;
if (Size == 8)
{
// If it can be written as single precision without information
// loss, then prefer that over writing a full-sized double.
double doubleprecision = *(double *)addr;
singleprecision = (float)doubleprecision;
if (singleprecision != doubleprecision)
{
ar.WriteByte(VAL_Float64);
ar << doubleprecision;
return;
}
ar(key, *(double*)addr);
}
else
{
singleprecision = *(float *)addr;
ar(key, *(float*)addr);
}
ar.WriteByte(VAL_Float32);
ar << singleprecision;
}
//==========================================================================
@ -1289,59 +1101,25 @@ void PFloat::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
static bool ReadValueDbl(FArchive &ar, double *addr, unsigned tag)
bool PFloat::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
double val;
union
{
BYTE val8;
WORD val16;
DWORD val32;
QWORD val64;
fixed_t fix;
float single;
angle_t ang;
};
NumericValue val;
switch (tag)
{
case VAL_Zero: val = 0; break;
case VAL_One: val = 1; break;
case VAL_Int8: ar << val8; val = (SBYTE)val8; break;
case VAL_UInt8: ar << val8; val = val8; break;
case VAL_Int16: ar << val16; val = (SWORD)val16; break;
case VAL_UInt16: ar << val16; val = val16; break;
case VAL_Int32: ar << val32; val = (SDWORD)val32; break;
case VAL_UInt32: ar << val32; val = val32; break;
case VAL_Int64: ar << val64; val = (double)(SQWORD)val64; break;
case VAL_UInt64: ar << val64; val = (double)val64; break;
case VAL_Float32: ar << single; val = single; break;
case VAL_Float64: ar << val; break;
default: PType::SkipValue(ar, tag); return false; // Incompatible type
}
*(double *)addr = val;
return true;
}
ar(key, val);
if (val.type == NumericValue::NM_invalid) return false; // not found or usable
else if (val.type == NumericValue::NM_signed) val.floatval = (double)val.signedval;
else if (val.type == NumericValue::NM_unsigned) val.floatval = (double)val.unsignedval;
bool PFloat::ReadValue(FArchive &ar, void *addr) const
if (Size == 8)
{
BYTE tag;
ar << tag;
double val;
if (ReadValueDbl(ar, &val, tag))
{
if (Size == 4)
{
*(float *)addr = (float)val;
*(double*)addr = val.floatval;
}
else
{
*(double *)addr = val;
*(float*)addr = (float)val.floatval;
}
return true;
}
return false;
}
//==========================================================================
//
@ -1482,10 +1260,9 @@ int PString::GetRegType() const
//
//==========================================================================
void PString::WriteValue(FArchive &ar, const void *addr) const
void PString::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
ar.WriteByte(VAL_String);
ar.WriteString(*(const FString *)addr);
ar(key, *(FString*)addr);
}
//==========================================================================
@ -1494,26 +1271,20 @@ void PString::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PString::ReadValue(FArchive &ar, void *addr) const
bool PString::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_String)
const char *cptr;
ar.StringPtr(key, cptr);
if (cptr == nullptr)
{
ar << *(FString *)addr;
}
else if (tag == VAL_Name)
{
const char *str = ar.ReadName();
*(FString *)addr = str;
return false;
}
else
{
SkipValue(ar, tag);
return false;
}
*(FString*)addr = cptr;
return true;
}
}
//==========================================================================
//
@ -1574,10 +1345,10 @@ PName::PName()
//
//==========================================================================
void PName::WriteValue(FArchive &ar, const void *addr) const
void PName::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
ar.WriteByte(VAL_Name);
ar.WriteName(((const FName *)addr)->GetChars());
const char *cptr = ((const FName*)addr)->GetChars();
ar.StringPtr(key, cptr);
}
//==========================================================================
@ -1586,27 +1357,20 @@ void PName::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PName::ReadValue(FArchive &ar, void *addr) const
bool PName::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_Name)
const char *cptr;
ar.StringPtr(key, cptr);
if (cptr == nullptr)
{
*(FName *)addr = FName(ar.ReadName());
}
else if (tag == VAL_String)
{
FString str;
ar << str;
*(FName *)addr = FName(str);
return false;
}
else
{
SkipValue(ar, tag);
return false;
}
*(FName*)addr = FName(cptr);
return true;
}
}
/* PSound *****************************************************************/
@ -1630,10 +1394,10 @@ PSound::PSound()
//
//==========================================================================
void PSound::WriteValue(FArchive &ar, const void *addr) const
void PSound::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
ar.WriteByte(VAL_Name);
ar.WriteName(*(const FSoundID *)addr);
const char *cptr = *(const FSoundID *)addr;
ar.StringPtr(key, cptr);
}
//==========================================================================
@ -1642,29 +1406,20 @@ void PSound::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PSound::ReadValue(FArchive &ar, void *addr) const
bool PSound::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_Name)
const char *cptr;
ar.StringPtr(key, cptr);
if (cptr == nullptr)
{
const char *str = ar.ReadName();
*(FSoundID *)addr = FSoundID(str);
}
else if (tag == VAL_String)
{
FString str;
ar << str;
*(FSoundID *)addr = FSoundID(str);
return false;
}
else
{
SkipValue(ar, tag);
return false;
}
*(FSoundID *)addr = FSoundID(cptr);
return true;
}
}
/* PColor *****************************************************************/
@ -1736,10 +1491,9 @@ int PStatePointer::GetRegType() const
//
//==========================================================================
void PStatePointer::WriteValue(FArchive &ar, const void *addr) const
void PStatePointer::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
ar.WriteByte(VAL_State);
ar << *(FState **)addr;
ar(key, *(FState **)addr);
}
//==========================================================================
@ -1748,17 +1502,11 @@ void PStatePointer::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PStatePointer::ReadValue(FArchive &ar, void *addr) const
bool PStatePointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_State)
{
ar << *(FState **)addr;
return true;
}
SkipValue(ar, tag);
return false;
bool res = false;
::Serialize(ar, key, *(FState **)addr, nullptr, &res);
return res;
}
/* PPointer ***************************************************************/
@ -1854,12 +1602,11 @@ void PPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
//
//==========================================================================
void PPointer::WriteValue(FArchive &ar, const void *addr) const
void PPointer::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
ar.WriteByte(VAL_Object);
ar << *(DObject **)addr;
ar(key, *(DObject **)addr);
}
else
{
@ -1874,16 +1621,14 @@ void PPointer::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PPointer::ReadValue(FArchive &ar, void *addr) const
bool PPointer::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_Object && PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{
ar << *(DObject **)addr;
return true;
bool res = false;
::Serialize(ar, key, *(DObject **)addr, nullptr, &res);
return res;
}
SkipValue(ar, tag);
return false;
}
@ -2098,16 +1843,18 @@ void PArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
//
//==========================================================================
void PArray::WriteValue(FArchive &ar, const void *addr) const
void PArray::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (ar.BeginArray(key))
{
ar.WriteByte(VAL_Array);
ar.WriteCount(ElementCount);
const BYTE *addrb = (const BYTE *)addr;
for (unsigned i = 0; i < ElementCount; ++i)
{
ElementType->WriteValue(ar, addrb);
ElementType->WriteValue(ar, nullptr, addrb);
addrb += ElementSize;
}
ar.EndArray();
}
}
//==========================================================================
@ -2116,34 +1863,27 @@ void PArray::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PArray::ReadValue(FArchive &ar, void *addr) const
bool PArray::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
if (ar.BeginArray(key))
{
bool readsomething = false;
BYTE tag;
ar << tag;
if (tag == VAL_Array)
{
unsigned count = ar.ReadCount();
unsigned i;
unsigned count = ar.ArraySize();
unsigned loop = MIN(count, ElementCount);
BYTE *addrb = (BYTE *)addr;
for (i = 0; i < MIN(count, ElementCount); ++i)
for(unsigned i=0;i<loop;i++)
{
readsomething |= ElementType->ReadValue(ar, addrb);
readsomething |= ElementType->ReadValue(ar, nullptr, addrb);
addrb += ElementSize;
}
if (i < ElementCount)
if (loop < count)
{
DPrintf(DMSG_WARNING, "Array on disk (%u) is bigger than in memory (%u)\n",
count, ElementCount);
for (; i < ElementCount; ++i)
{
SkipValue(ar);
}
}
ar.EndArray();
return readsomething;
}
SkipValue(ar, tag);
return false;
}
@ -2437,10 +2177,13 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset
//
//==========================================================================
void PStruct::WriteValue(FArchive &ar, const void *addr) const
void PStruct::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (ar.BeginObject(key))
{
ar.WriteByte(VAL_Struct);
WriteFields(ar, addr, Fields);
ar.EndObject();
}
}
//==========================================================================
@ -2449,16 +2192,15 @@ void PStruct::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PStruct::ReadValue(FArchive &ar, void *addr) const
bool PStruct::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag == VAL_Struct)
if (ar.BeginObject(key))
{
return ReadFields(ar, addr);
bool ret = ReadFields(ar, addr);
ar.EndObject();
return ret;
}
SkipValue(ar, tag);
return true;
return false;
}
//==========================================================================
@ -2467,7 +2209,7 @@ bool PStruct::ReadValue(FArchive &ar, void *addr) const
//
//==========================================================================
void PStruct::WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields)
void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields)
{
for (unsigned i = 0; i < fields.Size(); ++i)
{
@ -2475,11 +2217,9 @@ void PStruct::WriteFields(FArchive &ar, const void *addr, const TArray<PField *>
// Skip fields with native serialization
if (!(field->Flags & VARF_Native))
{
ar.WriteName(field->SymbolName);
field->Type->WriteValue(ar, (const BYTE *)addr + field->Offset);
field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset);
}
}
ar.WriteName(NULL);
}
//==========================================================================
@ -2488,36 +2228,33 @@ void PStruct::WriteFields(FArchive &ar, const void *addr, const TArray<PField *>
//
//==========================================================================
bool PStruct::ReadFields(FArchive &ar, void *addr) const
bool PStruct::ReadFields(FSerializer &ar, void *addr) const
{
bool readsomething = false;
const char *label = ar.ReadName();
if (label == NULL)
{ // If there is nothing to restore, we count it as success.
return true;
}
for (; label != NULL; label = ar.ReadName())
bool foundsomething = false;
const char *label;
while ((label = ar.GetKey()))
{
foundsomething = true;
const PSymbol *sym = Symbols.FindSymbol(FName(label, true), true);
if (sym == NULL)
{
DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n",
label, TypeName.GetChars());
SkipValue(ar);
}
else if (!sym->IsKindOf(RUNTIME_CLASS(PField)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName.GetChars());
SkipValue(ar);
}
else
{
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar,
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr,
(BYTE *)addr + static_cast<const PField *>(sym)->Offset);
}
}
return readsomething;
return readsomething || !foundsomething;
}
//==========================================================================
@ -2741,7 +2478,7 @@ END_POINTERS
//
//==========================================================================
static void RecurseWriteFields(const PClass *type, FArchive &ar, const void *addr)
static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void *addr)
{
if (type != NULL)
{
@ -2755,19 +2492,33 @@ static void RecurseWriteFields(const PClass *type, FArchive &ar, const void *add
// a more-derived class has variables that shadow a less-
// derived class. Whether or not that is a language feature
// that will actually be allowed remains to be seen.
ar.UserWriteClass(const_cast<PClass *>(type));
FString key;
key.Format("class:%s", type->TypeName.GetChars());
if (ar.BeginObject(key.GetChars()))
{
PStruct::WriteFields(ar, addr, type->Fields);
ar.EndObject();
}
break;
}
}
}
}
void PClass::WriteValue(FArchive &ar, const void *addr) const
void PClass::WriteValue(FSerializer &ar, const char *key,const void *addr) const
{
if (ar.BeginObject(key))
{
RecurseWriteFields(this, ar, addr);
ar.EndObject();
}
}
// Same as WriteValue, but does not create a new object in the serializer
// This is so that user variables do not contain unnecessary subblocks.
void PClass::WriteAllFields(FSerializer &ar, const void *addr) const
{
ar.WriteByte(VAL_Class);
RecurseWriteFields(this, ar, addr);
ar.UserWriteClass(NULL);
}
//==========================================================================
@ -2776,20 +2527,40 @@ void PClass::WriteValue(FArchive &ar, const void *addr) const
//
//==========================================================================
bool PClass::ReadValue(FArchive &ar, void *addr) const
bool PClass::ReadValue(FSerializer &ar, const char *key, void *addr) const
{
BYTE tag;
ar << tag;
if (tag != VAL_Class)
if (ar.BeginObject(key))
{
SkipValue(ar, tag);
return false;
bool ret = ReadAllFields(ar, addr);
ar.EndObject();
return ret;
}
else
return true;
}
bool PClass::ReadAllFields(FSerializer &ar, void *addr) const
{
bool readsomething = false;
PClass *type;
for (ar.UserReadClass(type); type != NULL; ar.UserReadClass(type))
bool foundsomething = false;
const char *key;
key = ar.GetKey();
if (strcmp(key, "classtype"))
{
// this does not represent a DObject
Printf(TEXTCOLOR_RED "trying to read user variables but got a non-object (first key is '%s')", key);
ar.mErrors++;
return false;
}
while ((key = ar.GetKey()))
{
if (strncmp(key, "class:", 6))
{
// We have read all user variable blocks.
break;
}
foundsomething = true;
PClass *type = PClass::FindClass(key + 6);
if (type != nullptr)
{
// Only read it if the type is related to this one.
const PClass *parent;
@ -2800,20 +2571,28 @@ bool PClass::ReadValue(FArchive &ar, void *addr) const
break;
}
}
if (parent != NULL)
if (parent != nullptr)
{
if (ar.BeginObject(nullptr))
{
readsomething |= type->ReadFields(ar, addr);
ar.EndObject();
}
}
else
{
DPrintf(DMSG_ERROR, "Unknown superclass %s of class %s\n",
type->TypeName.GetChars(), TypeName.GetChars());
SkipValue(ar, VAL_Struct);
}
}
return readsomething;
else
{
DPrintf(DMSG_ERROR, "Unknown superclass %s of class %s\n",
key+6, TypeName.GetChars());
}
}
return readsomething || !foundsomething;
}
//==========================================================================
//

View file

@ -193,15 +193,11 @@ public:
// a tag indicating its type. The tag is there so that variable types can be changed
// without completely breaking savegames, provided that the change isn't between
// totally unrelated types.
virtual void WriteValue(FArchive &ar, const void *addr) const;
virtual void WriteValue(FSerializer &ar, const char *key,const void *addr) const;
// Returns true if the stored value was compatible. False otherwise.
// If the value was incompatible, then the memory at *addr is unchanged.
virtual bool ReadValue(FArchive &ar, void *addr) const;
// Skips over a value written with WriteValue
static void SkipValue(FArchive &ar);
static void SkipValue(FArchive &ar, int tag);
virtual bool ReadValue(FSerializer &ar, const char *key,void *addr) const;
// Sets the default value for this type at (base + offset)
// If the default value is binary 0, then this function doesn't need
@ -354,8 +350,8 @@ class PInt : public PBasicType
public:
PInt(unsigned int size, bool unsign);
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
@ -383,8 +379,8 @@ class PFloat : public PBasicType
public:
PFloat(unsigned int size);
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual void SetValue(void *addr, int val);
virtual void SetValue(void *addr, double val);
@ -421,8 +417,8 @@ public:
virtual int GetRegType() const;
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override;
@ -436,8 +432,8 @@ class PName : public PInt
public:
PName();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
};
class PSound : public PInt
@ -446,8 +442,8 @@ class PSound : public PInt
public:
PSound();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
};
class PColor : public PInt
@ -465,8 +461,8 @@ class PStatePointer : public PBasicType
public:
PStatePointer();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual int GetStoreOp() const;
virtual int GetLoadOp() const;
@ -489,8 +485,8 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
protected:
PPointer();
@ -559,8 +555,8 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
@ -622,12 +618,12 @@ public:
size_t PropagateMark();
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FArchive &ar, void *addr) const;
static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FSerializer &ar, void *addr) const;
protected:
PStruct();
};
@ -692,8 +688,10 @@ public:
typedef PClassClass MetaClass;
MetaClass *GetClass() const;
void WriteValue(FArchive &ar, const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override;
void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
void WriteAllFields(FSerializer &ar, const void *addr) const;
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
bool ReadAllFields(FSerializer &ar, void *addr) const;
virtual void DeriveData(PClass *newclass) {}
static void StaticInit();

View file

@ -339,7 +339,6 @@ struct mapthinghexen_t
BYTE args[5];
};
class FArchive;
struct FDoomEdEntry;
// Internal representation of a mapthing

View file

@ -206,13 +206,11 @@ struct PalEntry
#endif
};
class FArchive;
class PClassInventory;
class FTextureID
{
friend class FTextureManager;
friend FArchive &operator<< (FArchive &arc, FTextureID &tex);
friend FTextureID GetHUDIcon(PClassInventory *cls);
friend void R_InitSpriteDefs();

View file

@ -28,7 +28,7 @@
#include "p_3dmidtex.h"
#include "r_data/r_interpolate.h"
#include "statnums.h"
#include "farchive.h"
#include "serializer.h"
#include "doomstat.h"
IMPLEMENT_CLASS (DSectorEffect)
@ -64,10 +64,10 @@ DSectorEffect::DSectorEffect (sector_t *sector)
m_Sector = sector;
}
void DSectorEffect::Serialize (FArchive &arc)
void DSectorEffect::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << m_Sector;
arc("sector", m_Sector);
}
IMPLEMENT_POINTY_CLASS (DMover)
@ -90,10 +90,10 @@ void DMover::Destroy()
Super::Destroy();
}
void DMover::Serialize (FArchive &arc)
void DMover::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << interpolation;
arc("interpolation", interpolation);
}
void DMover::StopInterpolation(bool force)

View file

@ -10,7 +10,8 @@ class DSectorEffect : public DThinker
public:
DSectorEffect (sector_t *sector);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Destroy();
sector_t *GetSector() const { return m_Sector; }
@ -32,7 +33,8 @@ protected:
private:
protected:
DMover ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Destroy();
};

View file

@ -38,7 +38,7 @@
#include "statnums.h"
#include "i_system.h"
#include "doomerrors.h"
#include "farchive.h"
#include "serializer.h"
#include "d_player.h"
@ -103,69 +103,62 @@ bool FThinkerList::IsEmpty() const
return Sentinel == NULL || Sentinel->NextThinker == NULL;
}
void DThinker::SaveList(FArchive &arc, DThinker *node)
void DThinker::SaveList(FSerializer &arc, DThinker *node)
{
if (node != NULL)
{
while (!(node->ObjectFlags & OF_Sentinel))
{
assert(node->NextThinker != NULL && !(node->NextThinker->ObjectFlags & OF_EuthanizeMe));
arc << node;
::Serialize<DThinker>(arc, nullptr, node, nullptr);
node = node->NextThinker;
}
}
}
void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
//==========================================================================
//
//
//
//==========================================================================
void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad)
{
DThinker *thinker;
BYTE stat;
int statcount;
//DThinker *thinker;
//BYTE stat;
//int statcount;
int i;
// Save lists of thinkers, but not by storing the first one and letting
// the archiver catch the rest. (Which leads to buttloads of recursion
// and makes the file larger.) Instead, we explicitly save each thinker
// in sequence. When restoring an archive, we also have to maintain
// the thinker lists here instead of relying on the archiver to do it
// for us.
if (arc.IsStoring())
if (arc.isWriting())
{
for (statcount = i = 0; i <= MAX_STATNUM; i++)
{
statcount += (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty());
}
arc << statcount;
arc.BeginArray("thinkers");
for (i = 0; i <= MAX_STATNUM; i++)
{
if (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty())
{
stat = i;
arc << stat;
arc.BeginArray(nullptr);
SaveList(arc, Thinkers[i].GetHead());
SaveList(arc, FreshThinkers[i].GetHead());
thinker = NULL;
arc << thinker; // Save a final NULL for this list
}
arc.EndArray();
}
arc.EndArray();
}
else
{
// Prevent the constructor from inserting thinkers into a list.
bSerialOverride = true;
try
if (arc.BeginArray("thinkers"))
{
arc << statcount;
while (statcount > 0)
for (i = 0; i <= MAX_STATNUM; i++)
{
arc << stat << thinker;
while (thinker != NULL)
if (arc.BeginArray(nullptr))
{
int size = arc.ArraySize();
for (int j = 0; j < size; j++)
{
DThinker *thinker;
arc(nullptr, thinker);
if (thinker != nullptr)
{
// This may be a player stored in their ancillary list. Remove
// them first before inserting them into the new list.
if (thinker->NextThinker != NULL)
if (thinker->NextThinker != nullptr)
{
thinker->Remove();
}
@ -178,26 +171,29 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
}
else if (thinker->ObjectFlags & OF_JustSpawned)
{
FreshThinkers[stat].AddTail(thinker);
FreshThinkers[i].AddTail(thinker);
thinker->PostSerialize();
}
else
{
Thinkers[stat].AddTail(thinker);
}
arc << thinker;
}
statcount--;
Thinkers[i].AddTail(thinker);
thinker->PostSerialize();
}
}
catch (class CDoomError &)
{
bSerialOverride = false;
DestroyAllThinkers();
throw;
}
bSerialOverride = false;
arc.EndArray();
}
}
arc.EndArray();
}
}
}
//==========================================================================
//
//
//
//==========================================================================
DThinker::DThinker (int statnum) throw()
{
@ -261,6 +257,10 @@ void DThinker::PostBeginPlay ()
{
}
void DThinker::PostSerialize()
{
}
DThinker *DThinker::FirstThinker (int statnum)
{
DThinker *node;
@ -332,24 +332,6 @@ void DThinker::DestroyAllThinkers ()
GC::FullGC();
}
// Destroy all thinkers except for player-controlled actors
// Players are simply removed from the list of thinkers and
// will be added back after serialization is complete.
void DThinker::DestroyMostThinkers ()
{
int i;
for (i = 0; i <= MAX_STATNUM; i++)
{
if (i != STAT_TRAVELLING)
{
DestroyMostThinkersInList (Thinkers[i], i);
DestroyMostThinkersInList (FreshThinkers[i], i);
}
}
GC::FullGC();
}
void DThinker::DestroyThinkersInList (FThinkerList &list)
{
if (list.Sentinel != NULL)
@ -364,39 +346,6 @@ void DThinker::DestroyThinkersInList (FThinkerList &list)
}
}
void DThinker::DestroyMostThinkersInList (FThinkerList &list, int stat)
{
if (stat != STAT_PLAYER)
{
DestroyThinkersInList (list);
}
else if (list.Sentinel != NULL)
{ // If it's a voodoo doll, destroy it. Otherwise, simply remove
// it from the list. G_FinishTravel() will find it later from
// a players[].mo link and destroy it then, after copying various
// information to a new player.
for (DThinker *probe = list.Sentinel->NextThinker; probe != list.Sentinel; probe = list.Sentinel->NextThinker)
{
if (!probe->IsKindOf(RUNTIME_CLASS(APlayerPawn)) || // <- should not happen
static_cast<AActor *>(probe)->player == NULL ||
static_cast<AActor *>(probe)->player->mo != probe)
{
probe->Destroy();
}
else
{
probe->Remove();
// Technically, this doesn't need to be in any list now, since
// it's only going to be found later and destroyed before ever
// needing to tick again, but by moving it to a separate list,
// I can keep my debug assertions that all thinkers are either
// euthanizing or in a list.
Thinkers[MAX_STATNUM+1].AddTail(probe);
}
}
}
}
void DThinker::RunThinkers ()
{
int i, count;
@ -473,8 +422,12 @@ void DThinker::Tick ()
size_t DThinker::PropagateMark()
{
assert(NextThinker != NULL && !(NextThinker->ObjectFlags & OF_EuthanizeMe));
assert(PrevThinker != NULL && !(PrevThinker->ObjectFlags & OF_EuthanizeMe));
// Do not choke on partially initialized objects (as happens when loading a savegame fails)
if (NextThinker != nullptr || PrevThinker != nullptr)
{
assert(NextThinker != nullptr && !(NextThinker->ObjectFlags & OF_EuthanizeMe));
assert(PrevThinker != nullptr && !(PrevThinker->ObjectFlags & OF_EuthanizeMe));
}
GC::Mark(NextThinker);
GC::Mark(PrevThinker);
return Super::PropagateMark();

View file

@ -43,6 +43,7 @@ class player_t;
struct pspdef_s;
struct FState;
class DThinker;
class FSerializer;
class FThinkerIterator;
@ -69,6 +70,7 @@ public:
virtual ~DThinker ();
virtual void Tick ();
virtual void PostBeginPlay (); // Called just before the first tick
virtual void PostSerialize();
size_t PropagateMark();
void ChangeStatNum (int statnum);
@ -76,33 +78,32 @@ public:
static void RunThinkers ();
static void RunThinkers (int statnum);
static void DestroyAllThinkers ();
static void DestroyMostThinkers ();
static void DestroyThinkersInList(int statnum)
{
DestroyThinkersInList(Thinkers[statnum]);
DestroyThinkersInList(FreshThinkers[statnum]);
}
static void SerializeAll (FArchive &arc, bool keepPlayers);
static void SerializeThinkers(FSerializer &arc, bool keepPlayers);
static void MarkRoots();
static DThinker *FirstThinker (int statnum);
static bool bSerialOverride;
private:
enum no_link_type { NO_LINK };
DThinker(no_link_type) throw();
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();
static FThinkerList Thinkers[MAX_STATNUM+2]; // Current thinkers
static FThinkerList FreshThinkers[MAX_STATNUM+1]; // Newly created thinkers
static bool bSerialOverride;
friend struct FThinkerList;
friend class FThinkerIterator;
friend class DObject;
friend class FSerializer;
DThinker *NextThinker, *PrevThinker;
};

File diff suppressed because it is too large Load diff

View file

@ -1,358 +0,0 @@
/*
** farchive.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef __FARCHIVE_H__
#define __FARCHIVE_H__
#include <stdio.h>
#include "dobject.h"
#include "r_state.h"
#include "tflags.h"
class FFile
{
public:
enum EOpenMode
{
EReading,
EWriting,
ENotOpen
};
enum ESeekPos
{
ESeekSet,
ESeekRelative,
ESeekEnd
};
virtual ~FFile () {}
virtual bool Open (const char *name, EOpenMode mode) = 0;
virtual void Close () = 0;
virtual void Flush () = 0;
virtual EOpenMode Mode () const = 0;
virtual bool IsPersistent () const = 0;
virtual bool IsOpen () const = 0;
virtual FFile& Write (const void *, unsigned int) = 0;
virtual FFile& Read (void *, unsigned int) = 0;
virtual unsigned int Tell () const = 0;
virtual FFile& Seek (int, ESeekPos) = 0;
inline FFile& Seek (unsigned int i, ESeekPos p) { return Seek ((int)i, p); }
};
class FCompressedFile : public FFile
{
public:
FCompressedFile ();
FCompressedFile (const char *name, EOpenMode mode, bool dontcompress = false);
FCompressedFile (FILE *file, EOpenMode mode, bool dontcompress = false, bool postopen=true);
~FCompressedFile ();
bool Open (const char *name, EOpenMode mode);
void Close ();
void Flush ();
EOpenMode Mode () const;
bool IsPersistent () const { return true; }
bool IsOpen () const;
unsigned int GetSize () const { return m_BufferSize; }
FFile &Write (const void *, unsigned int);
FFile &Read (void *, unsigned int);
unsigned int Tell () const;
FFile &Seek (int, ESeekPos);
protected:
unsigned int m_Pos;
unsigned int m_BufferSize;
unsigned int m_MaxBufferSize;
unsigned char *m_Buffer;
bool m_NoCompress;
EOpenMode m_Mode;
FILE *m_File;
void Implode ();
void Explode ();
virtual bool FreeOnExplode () { return true; }
void PostOpen ();
private:
void BeEmpty ();
};
class FCompressedMemFile : public FCompressedFile
{
public:
FCompressedMemFile ();
FCompressedMemFile (FILE *file); // Create for reading
~FCompressedMemFile ();
bool Open (const char *name, EOpenMode mode); // Works for reading only
bool Open (void *memblock); // Open for reading only
bool Open (); // Open for writing only
bool Reopen (); // Re-opens imploded file for reading only
void Close ();
bool IsOpen () const;
void GetSizes(unsigned int &one, unsigned int &two) const;
void Serialize (FArchive &arc);
protected:
bool FreeOnExplode () { return !m_SourceFromMem; }
private:
bool m_SourceFromMem;
unsigned char *m_ImplodedBuffer;
};
class FPNGChunkFile : public FCompressedFile
{
public:
FPNGChunkFile (FILE *file, DWORD id); // Create for writing
FPNGChunkFile (FILE *file, DWORD id, size_t chunklen); // Create for reading
void Close ();
private:
DWORD m_ChunkID;
};
class FArchive
{
public:
FArchive (FFile &file);
virtual ~FArchive ();
inline bool IsLoading () const { return m_Loading; }
inline bool IsStoring () const { return m_Storing; }
inline bool IsPeristent () const { return m_Persistent; }
void SetHubTravel () { m_HubTravel = true; }
void Close ();
virtual void Write (const void *mem, unsigned int len);
virtual void Read (void *mem, unsigned int len);
void WriteString(const FString &str);
void WriteString (const char *str);
void WriteByte(BYTE val);
void WriteInt16(WORD val);
void WriteInt32(DWORD val);
void WriteInt64(QWORD val);
void WriteCount (DWORD count);
DWORD ReadCount ();
void UserWriteClass (PClass *info);
void UserReadClass (PClass *&info);
template<typename T> void UserReadClass(T *&info)
{
PClass *myclass;
UserReadClass(myclass);
info = dyn_cast<T>(myclass);
}
FArchive& operator<< (BYTE &c);
FArchive& operator<< (WORD &s);
FArchive& operator<< (DWORD &i);
FArchive& operator<< (QWORD &i);
FArchive& operator<< (QWORD_UNION &i) { return operator<< (i.AsOne); }
FArchive& operator<< (float &f);
FArchive& operator<< (double &d);
FArchive& operator<< (char *&str);
FArchive& operator<< (FName &n);
FArchive& operator<< (FString &str);
FArchive& SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize);
FArchive& SerializeObject (DObject *&object, PClass *type);
FArchive& WriteObject (DObject *obj);
FArchive& ReadObject (DObject *&obj, PClass *wanttype);
void WriteName (const char *name);
const char *ReadName (); // The returned name disappears with the archive, unlike strings
void WriteSprite (int spritenum);
int ReadSprite ();
inline FArchive& operator<< (SBYTE &c) { return operator<< ((BYTE &)c); }
inline FArchive& operator<< (SWORD &s) { return operator<< ((WORD &)s); }
inline FArchive& operator<< (SDWORD &i) { return operator<< ((DWORD &)i); }
inline FArchive& operator<< (SQWORD &i) { return operator<< ((QWORD &)i); }
inline FArchive& operator<< (unsigned char *&str) { return operator<< ((char *&)str); }
inline FArchive& operator<< (signed char *&str) { return operator<< ((char *&)str); }
inline FArchive& operator<< (bool &b) { return operator<< ((BYTE &)b); }
inline FArchive& operator<< (DObject* &object) { return ReadObject (object, RUNTIME_CLASS(DObject)); }
void EnableThinkers()
{
m_ThinkersAllowed = true;
}
bool ThinkersAllowed()
{
return m_ThinkersAllowed;
}
protected:
enum { EObjectHashSize = 137 };
DWORD MapObject (DObject *obj);
DWORD WriteClass (PClass *info);
PClass *ReadClass ();
PClass *ReadClass (const PClass *wanttype);
PClass *ReadStoredClass (const PClass *wanttype);
DWORD AddName (const char *name);
DWORD AddName (unsigned int start); // Name has already been added to storage
DWORD FindName (const char *name) const;
DWORD FindName (const char *name, unsigned int bucket) const;
bool m_Persistent; // meant for persistent storage (disk)?
bool m_Loading; // extracting objects?
bool m_Storing; // inserting objects?
bool m_HubTravel; // travelling inside a hub?
FFile *m_File; // unerlying file object
TMap<PClass *, DWORD> ClassToArchive; // Maps PClass to archive type index
TArray<PClass *> ArchiveToClass; // Maps archive type index to PClass
TMap<DObject *, DWORD> ObjectToArchive; // Maps objects to archive index
TArray<DObject *> ArchiveToObject; // Maps archive index to objects
struct NameMap
{
DWORD StringStart; // index into m_NameStorage
DWORD HashNext; // next in hash bucket
enum { NO_INDEX = 0xffffffff };
};
TArray<NameMap> m_Names;
TArray<char> m_NameStorage;
unsigned int m_NameHash[EObjectHashSize];
int *m_SpriteMap;
size_t m_NumSprites;
bool m_ThinkersAllowed = false;
FArchive ();
void AttachToFile (FFile &file);
private:
FArchive (const FArchive &) {}
void operator= (const FArchive &) {}
};
// Create an FPNGChunkFile and FArchive in one step
class FPNGChunkArchive : public FArchive
{
public:
FPNGChunkArchive (FILE *file, DWORD chunkid);
FPNGChunkArchive (FILE *file, DWORD chunkid, size_t chunklen);
~FPNGChunkArchive ();
FPNGChunkFile Chunk;
};
inline FArchive &operator<< (FArchive &arc, PalEntry &p)
{
return arc << p.a << p.r << p.g << p.b;
}
template<class T>
inline FArchive &operator<< (FArchive &arc, T* &object)
{
return arc.SerializeObject ((DObject*&)object, RUNTIME_TEMPLATE_CLASS(T));
}
class FFont;
FArchive &SerializeFFontPtr (FArchive &arc, FFont* &font);
template<> inline FArchive &operator<< <FFont> (FArchive &arc, FFont* &font)
{
return SerializeFFontPtr (arc, font);
}
struct FStrifeDialogueNode;
struct FSwitchDef;
struct FDoorAnimation;
struct FLinePortal;
template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw);
template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da);
FArchive &operator<< (FArchive &arc, FLinePortal &da);
FArchive &operator<< (FArchive &arc, FSectorPortal &da);
template<class T,class TT>
inline FArchive &operator<< (FArchive &arc, TArray<T,TT> &self)
{
if (arc.IsStoring())
{
arc.WriteCount(self.Count);
}
else
{
DWORD numStored = arc.ReadCount();
self.Resize(numStored);
}
for (unsigned int i = 0; i < self.Count; ++i)
{
arc << self.Array[i];
}
return arc;
}
struct sector_t;
struct line_t;
struct vertex_t;
struct side_t;
FArchive &operator<< (FArchive &arc, sector_t *&sec);
FArchive &operator<< (FArchive &arc, const sector_t *&sec);
FArchive &operator<< (FArchive &arc, line_t *&line);
FArchive &operator<< (FArchive &arc, vertex_t *&vert);
FArchive &operator<< (FArchive &arc, side_t *&side);
FArchive &operator<<(FArchive &arc, DAngle &ang);
FArchive &operator<<(FArchive &arc, DVector3 &vec);
FArchive &operator<<(FArchive &arc, DVector2 &vec);
template<typename T, typename TT>
FArchive& operator<< (FArchive& arc, TFlags<T, TT>& flag)
{
return flag.Serialize (arc);
}
#endif //__FARCHIVE_H__

View file

@ -600,3 +600,58 @@ char *MemoryArrayReader::Gets(char *strbuf, int len)
{
return GetsFromBuffer((char*)&buf[0], strbuf, len);
}
//==========================================================================
//
// FileWriter (the motivation here is to have a buffer writing subclass)
//
//==========================================================================
bool FileWriter::OpenDirect(const char *filename)
{
File = fopen(filename, "wb");
return (File != NULL);
}
FileWriter *FileWriter::Open(const char *filename)
{
FileWriter *fwrit = new FileWriter();
if (fwrit->OpenDirect(filename))
{
return fwrit;
}
delete fwrit;
return NULL;
}
size_t FileWriter::Write(const void *buffer, size_t len)
{
if (File != NULL)
{
return fwrite(buffer, 1, len, File);
}
else
{
return 0;
}
}
size_t FileWriter::Printf(const char *fmt, ...)
{
va_list ap;
FString out;
va_start(ap, fmt);
out.VFormat(fmt, ap);
va_end(ap);
return Write(out.GetChars(), out.Len());
}
size_t BufferWriter::Write(const void *buffer, size_t len)
{
unsigned int ofs = mBuffer.Reserve((unsigned)len);
memcpy(&mBuffer[ofs], buffer, len);
return len;
}

View file

@ -356,4 +356,46 @@ protected:
};
class FileWriter
{
protected:
bool OpenDirect(const char *filename);
FileWriter()
{
File = NULL;
}
public:
virtual ~FileWriter()
{
if (File != NULL) fclose(File);
}
static FileWriter *Open(const char *filename);
virtual size_t Write(const void *buffer, size_t len);
size_t Printf(const char *fmt, ...);
protected:
FILE *File;
protected:
bool CloseOnDestruct;
};
class BufferWriter : public FileWriter
{
protected:
TArray<unsigned char> mBuffer;
public:
BufferWriter() {}
virtual size_t Write(const void *buffer, size_t len) override;
TArray<unsigned char> *GetBuffer() { return &mBuffer; }
};
#endif

View file

@ -1,204 +0,0 @@
/*
** t_fspic.cpp
** Fragglescript HUD pics (incomplete and untested!)
**
**---------------------------------------------------------------------------
** Copyright 2005 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "t_script.h"
#include "doomtype.h"
#include "p_local.h"
#include "farchive.h"
#include "sbar.h"
#include "v_video.h"
struct FHudPic
{
FTextureID texturenum;
int xpos;
int ypos;
bool draw;
void Serialize(FArchive & arc)
{
arc << xpos << ypos << draw << texturenum;
}
};
//======================================================================
//
//======================================================================
class DHUDPicManager : public DHUDMessage
{
// This is no real hudmessage but this way I don't need any external code to handle this
// because the hudmessage and thinker code handles everything automatically
DECLARE_CLASS(DHUDPicManager, DHUDMessage)
float basetrans;
public:
TArray<FHudPic> piclist;
DHUDPicManager();
~DHUDPicManager() {}
void Serialize(FArchive & ar);
virtual void DoDraw (int linenum, int x, int y, int hudheight, float translucent);
void DoDraw (int, int, int, bool, int) { assert(false); }
} ;
IMPLEMENT_CLASS(DHUDPicManager)
//======================================================================
//
//======================================================================
DHUDPicManager::DHUDPicManager()
{
HUDWidth=HUDHeight=0;
basetrans=0.8f;
//SetID(0xffffffff);
NumLines=1;
HoldTics=0; // stay forever!
//logtoconsole=false;
}
//======================================================================
//
//======================================================================
void DHUDPicManager::Serialize(FArchive & ar)
{
Super::Serialize(ar);
short count=piclist.Size();
ar << count << basetrans;
if (ar.IsLoading()) piclist.Resize(count);
for(int i=0;i<count;i++) piclist[i].Serialize(ar);
}
//======================================================================
//
//======================================================================
void DHUDPicManager::DoDraw (int linenum, int x, int y, int hudheight, float translucent)
{
for(unsigned int i=0; i<piclist.Size();i++) if (piclist[i].texturenum.isValid() && piclist[i].draw)
{
FTexture * tex = TexMan[piclist[i].texturenum];
if (tex) screen->DrawTexture(tex, piclist[i].xpos, piclist[i].ypos, DTA_320x200, true,
DTA_AlphaF, translucent*basetrans, TAG_DONE);
}
}
//======================================================================
//
//======================================================================
static TArray<FHudPic> & GetPicList()
{
//TThinkerIterator<DHUDPicManager> it;
DHUDPicManager * pm=NULL;//it.Next();
if (!pm) pm=new DHUDPicManager;
return pm->piclist;
}
//======================================================================
//
// External interface
//
//======================================================================
//======================================================================
//
//======================================================================
int HU_GetFSPic(FTextureID texturenum, int xpos, int ypos)
{
TArray<FHudPic> &piclist=GetPicList();
unsigned int i;
for(i=0;i<piclist.Size();i++) if (piclist[i].texturenum.isValid()) continue;
if (i==piclist.Size()) i=piclist.Reserve(1);
FHudPic * pic=&piclist[i];
piclist[i].texturenum = texturenum;
piclist[i].xpos = xpos;
piclist[i].ypos = ypos;
piclist[i].draw = false;
return i;
}
//======================================================================
//
//======================================================================
int HU_DeleteFSPic(unsigned handle)
{
TArray<FHudPic> &piclist=GetPicList();
if(handle >= piclist.Size()) return -1;
piclist[handle].texturenum.SetInvalid();
return 0;
}
//======================================================================
//
//======================================================================
int HU_ModifyFSPic(unsigned handle, FTextureID texturenum, int xpos, int ypos)
{
TArray<FHudPic> &piclist=GetPicList();
if(handle >= piclist.Size()) return -1;
if(!piclist[handle].texturenum.isValid()) return -1;
piclist[handle].texturenum = texturenum;
piclist[handle].xpos = xpos;
piclist[handle].ypos = ypos;
return 0;
}
//======================================================================
//
//======================================================================
int HU_FSDisplay(unsigned handle, bool newval)
{
TArray<FHudPic> &piclist=GetPicList();
if(handle >= piclist.Size()) return -1;
if(!piclist[handle].texturenum.isValid()) return -1;
piclist[handle].draw = newval;
return 0;
}

View file

@ -65,7 +65,7 @@
#include "v_palette.h"
#include "v_font.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "serializer.h"
#include "p_setup.h"
#include "p_spec.h"
#include "r_utility.h"
@ -1780,7 +1780,7 @@ class DLightLevel : public DLighting
public:
DLightLevel(sector_t * s,int destlevel,int speed);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; }
};
@ -1789,11 +1789,11 @@ public:
IMPLEMENT_CLASS (DLightLevel)
void DLightLevel::Serialize (FArchive &arc)
void DLightLevel::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << destlevel << speed;
if (arc.IsLoading()) m_Sector->lightingdata=this;
arc("destlevel", destlevel)
("speed", speed);
}
@ -3647,58 +3647,24 @@ void FParser::SF_Pow()
//==========================================================================
int HU_GetFSPic(FTextureID lumpnum, int xpos, int ypos);
int HU_DeleteFSPic(unsigned int handle);
int HU_ModifyFSPic(unsigned int handle, FTextureID lumpnum, int xpos, int ypos);
int HU_FSDisplay(unsigned int handle, bool newval);
void FParser::SF_NewHUPic()
{
if (CheckArgs(3))
{
t_return.type = svt_int;
t_return.value.i = HU_GetFSPic(
TexMan.GetTexture(stringvalue(t_argv[0]), FTexture::TEX_MiscPatch, FTextureManager::TEXMAN_TryAny),
intvalue(t_argv[1]), intvalue(t_argv[2]));
}
// disabled because it was never used and never tested
}
void FParser::SF_DeleteHUPic()
{
if (CheckArgs(1))
{
if (HU_DeleteFSPic(intvalue(t_argv[0])) == -1)
script_error("deletehupic: Invalid sfpic handle: %i\n", intvalue(t_argv[0]));
}
// disabled because it was never used and never tested
}
void FParser::SF_ModifyHUPic()
{
if (t_argc != 4)
{
script_error("modifyhupic: invalid number of arguments\n");
return;
}
if (HU_ModifyFSPic(intvalue(t_argv[0]),
TexMan.GetTexture(stringvalue(t_argv[0]), FTexture::TEX_MiscPatch, FTextureManager::TEXMAN_TryAny),
intvalue(t_argv[2]), intvalue(t_argv[3])) == -1)
{
script_error("modifyhypic: invalid sfpic handle %i\n", intvalue(t_argv[0]));
}
return;
// disabled because it was never used and never tested
}
void FParser::SF_SetHUPicDisplay()
{
if (t_argc != 2)
{
script_error("sethupicdisplay: invalud number of arguments\n");
return;
}
if (HU_FSDisplay(intvalue(t_argv[0]), intvalue(t_argv[1]) > 0 ? 1 : 0) == -1)
script_error("sethupicdisplay: invalid pic handle %i\n", intvalue(t_argv[0]));
// disabled because it was never used and never tested
}

View file

@ -56,7 +56,7 @@
#include "t_script.h"
#include "i_system.h"
#include "w_wad.h"
#include "farchive.h"
#include "serializer.h"
//==========================================================================
@ -81,10 +81,14 @@ END_POINTERS
//
//==========================================================================
void DFsSection::Serialize(FArchive &ar)
void DFsSection::Serialize(FSerializer &arc)
{
Super::Serialize(ar);
ar << type << start_index << end_index << loop_index << next;
Super::Serialize(arc);
arc("type", type)
("start_index", start_index)
("end_index", end_index)
("loop_index", loop_index)
("next", next);
}
//==========================================================================

View file

@ -54,7 +54,7 @@
#include "i_system.h"
#include "doomerrors.h"
#include "doomstat.h"
#include "farchive.h"
#include "serializer.h"
//==========================================================================
//
@ -162,6 +162,19 @@ DFsScript::DFsScript()
lastiftrue = false;
}
//==========================================================================
//
// This is here to delete the locally allocated buffer in case this
// gets forcibly destroyed
//
//==========================================================================
DFsScript::~DFsScript()
{
if (data != NULL) delete[] data;
data = NULL;
}
//==========================================================================
//
//
@ -187,18 +200,23 @@ void DFsScript::Destroy()
//
//==========================================================================
void DFsScript::Serialize(FArchive &arc)
void DFsScript::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
// don't save a reference to the global script
if (parent == global_script) parent = NULL;
if (parent == global_script) parent = nullptr;
arc << data << scriptnum << len << parent << trigger << lastiftrue;
for(int i=0; i< SECTIONSLOTS; i++) arc << sections[i];
for(int i=0; i< VARIABLESLOTS; i++) arc << variables[i];
for(int i=0; i< MAXSCRIPTS; i++) arc << children[i];
arc("data", data)
("scriptnum", scriptnum)
("len", len)
("parent", parent)
("trigger", trigger)
("lastiftrue", lastiftrue)
.Array("sections", sections, SECTIONSLOTS)
.Array("variables", variables, VARIABLESLOTS)
.Array("children", children, MAXSCRIPTS);
if (parent == NULL) parent = global_script;
if (parent == nullptr) parent = global_script;
}
//==========================================================================
@ -338,12 +356,17 @@ void DRunningScript::Destroy()
//
//==========================================================================
void DRunningScript::Serialize(FArchive &arc)
void DRunningScript::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << script << save_point << wait_type << wait_data << prev << next << trigger;
for(int i=0; i< VARIABLESLOTS; i++) arc << variables[i];
arc("script", script)
("save_point", save_point)
("wait_type", wait_type)
("wait_data", wait_data)
("prev", prev)
("next", next)
("trigger", trigger)
.Array("variables", variables, VARIABLESLOTS);
}
@ -416,10 +439,13 @@ void DFraggleThinker::Destroy()
//
//==========================================================================
void DFraggleThinker::Serialize(FArchive &arc)
void DFraggleThinker::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << LevelScript << RunningScripts << SpawnedThings << nocheckposition;
arc("levelscript", LevelScript)
("runningscripts", RunningScripts)
("spawnedthings", SpawnedThings)
("nocheckposition", nocheckposition);
}
//==========================================================================

View file

@ -189,7 +189,7 @@ public:
void GetValue(svalue_t &result);
void SetValue(const svalue_t &newvalue);
void Serialize(FArchive &ar);
void Serialize(FSerializer &ar);
};
//==========================================================================
@ -238,7 +238,7 @@ public:
next = NULL;
}
void Serialize(FArchive &ar);
void Serialize(FSerializer &ar);
};
@ -336,8 +336,9 @@ public:
// true or false
DFsScript();
~DFsScript();
void Destroy();
void Serialize(FArchive &ar);
void Serialize(FSerializer &ar);
DFsVariable *NewVariable(const char *name, int vtype);
void NewFunction(const char *name, void (FParser::*handler)());
@ -652,7 +653,7 @@ class DRunningScript : public DObject
public:
DRunningScript(AActor *trigger=NULL, DFsScript *owner = NULL, int index = 0) ;
void Destroy();
void Serialize(FArchive &arc);
void Serialize(FSerializer &arc);
TObjPtr<DFsScript> script;
@ -689,7 +690,7 @@ public:
void Destroy();
void Serialize(FArchive & arc);
void Serialize(FSerializer & arc);
void Tick();
size_t PropagateMark();
size_t PointerSubstitution (DObject *old, DObject *notOld);

View file

@ -54,7 +54,7 @@
#include "t_script.h"
#include "a_pickups.h"
#include "farchive.h"
#include "serializer.h"
//==========================================================================
@ -306,10 +306,15 @@ void DFsVariable::SetValue(const svalue_t &newvalue)
//
//==========================================================================
void DFsVariable::Serialize(FArchive & ar)
void DFsVariable::Serialize(FSerializer & ar)
{
Super::Serialize(ar);
ar << Name << type << string << actor << value.i << next;
ar("name", Name)
("type", type)
("string", string)
("actor", actor)
("value", value.i)
("next", next);
}

View file

@ -120,7 +120,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
bool isdefault = false;
// shoot a cube at current target
targ = state->GetNextInList(PClass::FindClass("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain));
targ = state->GetNextInList(PClass::FindActor("BossTarget"), G_SkillProperty(SKILLP_EasyBossBrain));
if (targ != NULL)
{

View file

@ -29,7 +29,8 @@ public:
void Tick ();
void SetWeapon (EMarineWeapon);
void SetSprite (PClassActor *source);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
int CurrentWeapon;

View file

@ -14,10 +14,10 @@
#include "a_specialspot.h"
#include "templates.h"
#include "m_bbox.h"
#include "farchive.h"
#include "portal.h"
#include "d_player.h"
#include "p_maputl.h"
#include "serializer.h"
#include "g_shared/a_pickups.h"
// Include all the other Doom stuff here to reduce compile time

View file

@ -21,19 +21,14 @@ static FRandom pr_m_fireshotgun2 ("SMarineFireSSG");
IMPLEMENT_CLASS (AScriptedMarine)
void AScriptedMarine::Serialize (FArchive &arc)
void AScriptedMarine::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
if (arc.IsStoring ())
{
arc.WriteSprite (SpriteOverride);
}
else
{
SpriteOverride = arc.ReadSprite ();
}
arc << CurrentWeapon;
auto def = (AScriptedMarine*)GetDefault();
arc.Sprite("spriteoverride", SpriteOverride, &def->SpriteOverride)
("currentweapon", CurrentWeapon, def->CurrentWeapon);
}
void AScriptedMarine::Activate (AActor *activator)

View file

@ -27,6 +27,7 @@
#include <stdio.h>
#include <stddef.h>
#include <time.h>
#include <memory>
#ifdef __APPLE__
#include <CoreServices/CoreServices.h>
#endif
@ -78,12 +79,14 @@
#include "p_acs.h"
#include "p_effect.h"
#include "m_joy.h"
#include "farchive.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "a_morph.h"
#include "p_spec.h"
#include "r_data/colormaps.h"
#include "serializer.h"
#include "w_zip.h"
#include "resourcefiles/resourcefile.h"
#include <zlib.h>
@ -110,10 +113,11 @@ void G_DoWorldDone (void);
void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description);
void G_DoAutoSave ();
void STAT_Write(FILE *file);
void STAT_Read(PNGHandle *png);
void STAT_Serialize(FSerializer &file);
bool WriteZip(const char *filename, TArray<FString> &filenames, TArray<FCompressedBuffer> &content);
FIntCVar gameskill ("skill", 2, CVAR_SERVERINFO|CVAR_LATCH);
CVAR(Bool, save_formatted, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // use formatted JSON for saves (more readable but a larger files and a bit slower.
CVAR (Int, deathmatch, 0, CVAR_SERVERINFO|CVAR_LATCH);
CVAR (Bool, chasedemo, false, 0);
CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
@ -1775,7 +1779,7 @@ void G_LoadGame (const char* name, bool hidecon)
}
}
static bool CheckSingleWad (char *name, bool &printRequires, bool printwarn)
static bool CheckSingleWad (const char *name, bool &printRequires, bool printwarn)
{
if (name == NULL)
{
@ -1795,22 +1799,20 @@ static bool CheckSingleWad (char *name, bool &printRequires, bool printwarn)
}
}
printRequires = true;
delete[] name;
return false;
}
delete[] name;
return true;
}
// Return false if not all the needed wads have been loaded.
bool G_CheckSaveGameWads (PNGHandle *png, bool printwarn)
bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn)
{
char *text;
bool printRequires = false;
FString text;
text = M_GetPNGText (png, "Game WAD");
arc("Game WAD", text);
CheckSingleWad (text, printRequires, printwarn);
text = M_GetPNGText (png, "Map WAD");
arc("Map WAD", text);
CheckSingleWad (text, printRequires, printwarn);
if (printRequires)
@ -1828,9 +1830,6 @@ bool G_CheckSaveGameWads (PNGHandle *png, bool printwarn)
void G_DoLoadGame ()
{
char sigcheck[20];
char *text = NULL;
char *map;
bool hidecon;
if (gameaction != ga_autoloadgame)
@ -1840,76 +1839,83 @@ void G_DoLoadGame ()
hidecon = gameaction == ga_loadgamehidecon;
gameaction = ga_nothing;
FILE *stdfile = fopen (savename.GetChars(), "rb");
if (stdfile == NULL)
FResourceFile *resfile = FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true);
if (resfile == nullptr)
{
Printf ("Could not read savegame '%s'\n", savename.GetChars());
return;
}
PNGHandle *png = M_VerifyPNG (stdfile);
if (png == NULL)
try
{
fclose (stdfile);
Printf ("'%s' is not a valid (PNG) savegame\n", savename.GetChars());
FResourceLump *info = resfile->FindLump("info.json");
if (info == nullptr)
{
delete resfile;
Printf("'%s' is not a valid savegame: Missing 'info.json'.\n", savename.GetChars());
return;
}
SaveVersion = 0;
void *data = info->CacheLump();
FSerializer arc;
if (!arc.OpenReader((const char *)data, info->LumpSize))
{
Printf("Failed to access savegame info\n");
delete resfile;
return;
}
// Check whether this savegame actually has been created by a compatible engine.
// Since there are ZDoom derivates using the exact same savegame format but
// with mutual incompatibilities this check simplifies things significantly.
char *engine = M_GetPNGText (png, "Engine");
if (engine == NULL || 0 != strcmp (engine, GAMESIG))
FString savever, engine, map;
arc("Save Version", SaveVersion);
arc("Engine", engine);
arc("Current Map", map);
if (engine.CompareNoCase(GAMESIG) != 0)
{
// Make a special case for the message printed for old savegames that don't
// have this information.
if (engine == NULL)
if (engine.IsEmpty())
{
Printf("Savegame is from an incompatible version\n");
}
else
{
Printf("Savegame is from another ZDoom-based engine: %s\n", engine);
delete[] engine;
}
delete png;
fclose (stdfile);
delete resfile;
return;
}
if (engine != NULL)
{
delete[] engine;
}
SaveVersion = 0;
if (!M_GetPNGText (png, "ZDoom Save Version", sigcheck, 20) ||
0 != strncmp (sigcheck, SAVESIG, 9) || // ZDOOMSAVE is the first 9 chars
(SaveVersion = atoi (sigcheck+9)) < MINSAVEVER)
if (SaveVersion < MINSAVEVER || SaveVersion > SAVEVER)
{
delete png;
fclose (stdfile);
delete resfile;
Printf("Savegame is from an incompatible version");
if (SaveVersion != 0)
if (SaveVersion < MINSAVEVER)
{
Printf(": %d (%d is the oldest supported)", SaveVersion, MINSAVEVER);
}
else
{
Printf(": %d (%d is the highest supported)", SaveVersion, SAVEVER);
}
Printf("\n");
return;
}
if (!G_CheckSaveGameWads (png, true))
if (!G_CheckSaveGameWads(arc, true))
{
fclose (stdfile);
delete resfile;
return;
}
map = M_GetPNGText (png, "Current Map");
if (map == NULL)
if (map.IsEmpty())
{
Printf("Savegame is missing the current map\n");
fclose (stdfile);
delete resfile;
return;
}
@ -1919,73 +1925,83 @@ void G_DoLoadGame ()
{
gamestate = GS_HIDECONSOLE;
}
// we are done with info.json.
arc.Close();
info = resfile->FindLump("globals.json");
if (info == nullptr)
{
delete resfile;
Printf("'%s' is not a valid savegame: Missing 'globals.json'.\n", savename.GetChars());
return;
}
data = info->CacheLump();
if (!arc.OpenReader((const char *)data, info->LumpSize))
{
Printf("Failed to access savegame info\n");
delete resfile;
return;
}
// Read intermission data for hubs
G_ReadHubInfo(png);
G_SerializeHub(arc);
bglobal.RemoveAllBots(true);
text = M_GetPNGText (png, "Important CVARs");
if (text != NULL)
FString cvar;
arc("importantcvars", cvar);
if (!cvar.IsEmpty())
{
BYTE *vars_p = (BYTE *)text;
BYTE *vars_p = (BYTE *)cvar.GetChars();
C_ReadCVars(&vars_p);
delete[] text;
}
DWORD time[2] = { 1,0 };
arc("ticrate", time[0])
("leveltime", time[1]);
// dearchive all the modifications
if (M_FindPNGChunk (png, MAKE_ID('p','t','I','c')) == 8)
{
DWORD time[2];
fread (&time, 8, 1, stdfile);
time[0] = BigLong((unsigned int)time[0]);
time[1] = BigLong((unsigned int)time[1]);
level.time = Scale(time[1], TICRATE, time[0]);
}
else
{ // No ptIc chunk so we don't know how long the user was playing
level.time = 0;
}
G_ReadSnapshots (png);
G_ReadSnapshots(resfile);
delete resfile; // we no longer need the resource file below this point
resfile = nullptr;
G_ReadVisited(arc);
// load a base level
savegamerestore = true; // Use the player actors in the savegame
bool demoplaybacksave = demoplayback;
G_InitNew(map, false);
demoplayback = demoplaybacksave;
delete[] map;
savegamerestore = false;
STAT_Read(png);
FRandom::StaticReadRNGState(png);
P_ReadACSDefereds(png);
P_ReadACSVars(png);
STAT_Serialize(arc);
FRandom::StaticReadRNGState(arc);
P_ReadACSDefereds(arc);
P_ReadACSVars(arc);
NextSkill = -1;
if (M_FindPNGChunk (png, MAKE_ID('s','n','X','t')) == 1)
{
BYTE next;
fread (&next, 1, 1, stdfile);
NextSkill = next;
}
arc("nextskill", NextSkill);
if (level.info->snapshot != NULL)
{
delete level.info->snapshot;
level.info->snapshot = NULL;
}
if (level.info != nullptr)
level.info->Snapshot.Clean();
BackupSaveName = savename;
delete png;
fclose (stdfile);
// At this point, the GC threshold is likely a lot higher than the
// amount of memory in use, so bring it down now by starting a
// collection.
GC::StartCollection();
}
catch (...)
{
// delete the resource file if anything goes wrong in here.
if (resfile != nullptr) delete resfile;
return;
}
}
//
@ -2047,7 +2063,7 @@ FString G_BuildSaveName (const char *prefix, int slot)
name << prefix;
if (slot >= 0)
{
name.AppendFormat("%d.zds", slot);
name.AppendFormat("%d." SAVEGAME_EXT, slot);
}
return name;
}
@ -2104,23 +2120,23 @@ void G_DoAutoSave ()
}
static void PutSaveWads (FILE *file)
static void PutSaveWads (FSerializer &arc)
{
const char *name;
// Name of IWAD
name = Wads.GetWadName (FWadCollection::IWAD_FILENUM);
M_AppendPNGText (file, "Game WAD", name);
arc.AddString("Game WAD", name);
// Name of wad the map resides in
if (Wads.GetLumpFile (level.lumpnum) > 1)
{
name = Wads.GetWadName (Wads.GetLumpFile (level.lumpnum));
M_AppendPNGText (file, "Map WAD", name);
arc.AddString("Map WAD", name);
}
}
static void PutSaveComment (FILE *file)
static void PutSaveComment (FSerializer &arc)
{
char comment[256];
const char *readableTime;
@ -2135,7 +2151,7 @@ static void PutSaveComment (FILE *file)
strncpy (comment+15, readableTime+10, 9);
comment[24] = 0;
M_AppendPNGText (file, "Creation Time", comment);
arc.AddString("Creation Time", comment);
// Get level name
//strcpy (comment, level.level_name);
@ -2150,10 +2166,10 @@ static void PutSaveComment (FILE *file)
comment[len+16] = 0;
// Write out the comment
M_AppendPNGText (file, "Comment", comment);
arc.AddString("Comment", comment);
}
static void PutSavePic (FILE *file, int width, int height)
static void PutSavePic (FileWriter *file, int width, int height)
{
if (width <= 0 || height <= 0 || !storesavepic)
{
@ -2167,6 +2183,9 @@ static void PutSavePic (FILE *file, int width, int height)
void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description)
{
TArray<FCompressedBuffer> savegame_content;
TArray<FString> savegame_filenames;
char buf[100];
// Do not even try, if we're not in a level. (Can happen after
@ -2178,7 +2197,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
if (demoplayback)
{
filename = G_BuildSaveName ("demosave.zds", -1);
filename = G_BuildSaveName ("demosave." SAVEGAME_EXT, -1);
}
if (cl_waitforsave)
@ -2187,87 +2206,97 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio
insave = true;
G_SnapshotLevel ();
FILE *stdfile = fopen (filename, "wb");
BufferWriter savepic;
FSerializer savegameinfo; // this is for displayable info about the savegame
FSerializer savegameglobals; // and this for non-level related info that must be saved.
if (stdfile == NULL)
{
Printf ("Could not create savegame '%s'\n", filename.GetChars());
insave = false;
I_FreezeTime(false);
return;
}
savegameinfo.OpenWriter(true);
savegameglobals.OpenWriter(save_formatted);
SaveVersion = SAVEVER;
PutSavePic (stdfile, SAVEPICWIDTH, SAVEPICHEIGHT);
PutSavePic(&savepic, SAVEPICWIDTH, SAVEPICHEIGHT);
mysnprintf(buf, countof(buf), GAMENAME " %s", GetVersionString());
M_AppendPNGText (stdfile, "Software", buf);
M_AppendPNGText (stdfile, "Engine", GAMESIG);
M_AppendPNGText (stdfile, "ZDoom Save Version", SAVESIG);
M_AppendPNGText (stdfile, "Title", description);
M_AppendPNGText (stdfile, "Current Map", level.MapName);
PutSaveWads (stdfile);
PutSaveComment (stdfile);
// put some basic info into the PNG so that this isn't lost when the image gets extracted.
M_AppendPNGText(&savepic, "Software", buf);
M_AppendPNGText(&savepic, "Title", description);
M_AppendPNGText(&savepic, "Current Map", level.MapName);
M_FinishPNG(&savepic);
int ver = SAVEVER;
savegameinfo.AddString("Software", buf)
.AddString("Engine", GAMESIG)
("Save Version", ver)
.AddString("Title", description)
.AddString("Current Map", level.MapName);
PutSaveWads (savegameinfo);
PutSaveComment (savegameinfo);
// Intermission stats for hubs
G_WriteHubInfo(stdfile);
G_SerializeHub(savegameglobals);
{
FString vars = C_GetMassCVarString(CVAR_SERVERINFO);
M_AppendPNGText (stdfile, "Important CVARs", vars.GetChars());
savegameglobals.AddString("importantcvars", vars.GetChars());
}
if (level.time != 0 || level.maptime != 0)
{
DWORD time[2] = { DWORD(BigLong(TICRATE)), DWORD(BigLong(level.time)) };
M_AppendPNGChunk (stdfile, MAKE_ID('p','t','I','c'), (BYTE *)&time, 8);
int tic = TICRATE;
savegameglobals("ticrate", tic);
savegameglobals("leveltime", level.time);
}
G_WriteSnapshots (stdfile);
STAT_Write(stdfile);
FRandom::StaticWriteRNGState (stdfile);
P_WriteACSDefereds (stdfile);
STAT_Serialize(savegameglobals);
FRandom::StaticWriteRNGState(savegameglobals);
P_WriteACSDefereds(savegameglobals);
P_WriteACSVars(savegameglobals);
G_WriteVisited(savegameglobals);
P_WriteACSVars(stdfile);
if (NextSkill != -1)
{
BYTE next = NextSkill;
M_AppendPNGChunk (stdfile, MAKE_ID('s','n','X','t'), &next, 1);
savegameglobals("nextskill", NextSkill);
}
M_FinishPNG (stdfile);
fclose (stdfile);
auto picdata = savepic.GetBuffer();
FCompressedBuffer bufpng = { picdata->Size(), picdata->Size(), METHOD_STORED, 0, crc32(0, &(*picdata)[0], picdata->Size()), (char*)&(*picdata)[0] };
savegame_content.Push(bufpng);
savegame_filenames.Push("savepic.png");
savegame_content.Push(savegameinfo.GetCompressedOutput());
savegame_filenames.Push("info.json");
savegame_content.Push(savegameglobals.GetCompressedOutput());
savegame_filenames.Push("globals.json");
G_WriteSnapshots (savegame_filenames, savegame_content);
WriteZip(filename, savegame_filenames, savegame_content);
M_NotifyNewSave (filename.GetChars(), description, okForQuicksave);
// Check whether the file is ok.
bool success = false;
stdfile = fopen (filename.GetChars(), "rb");
if (stdfile != NULL)
{
PNGHandle *pngh = M_VerifyPNG(stdfile);
if (pngh != NULL)
{
success = true;
delete pngh;
}
fclose(stdfile);
}
if (success)
// delete the JSON buffers we created just above. Everything else will
// either still be needed or taken care of automatically.
savegame_content[1].Clean();
savegame_content[2].Clean();
// Check whether the file is ok by trying to open it.
FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr, true);
if (test != nullptr)
{
delete test;
if (longsavemessages) Printf ("%s (%s)\n", GStrings("GGSAVED"), filename.GetChars());
else Printf ("%s\n", GStrings("GGSAVED"));
}
else Printf(PRINT_HIGH, "Save failed\n");
BackupSaveName = filename;
// We don't need the snapshot any longer.
if (level.info->snapshot != NULL)
{
delete level.info->snapshot;
level.info->snapshot = NULL;
}
level.info->Snapshot.Clean();
insave = false;
I_FreezeTime(false);

View file

@ -24,7 +24,6 @@
#define __G_GAME__
struct event_t;
struct PNGHandle;
//
@ -68,8 +67,8 @@ void G_ScreenShot (char *filename);
FString G_BuildSaveName (const char *prefix, int slot);
struct PNGHandle;
bool G_CheckSaveGameWads (PNGHandle *png, bool printwarn);
class FSerializer;
bool G_CheckSaveGameWads (FSerializer &arc, bool printwarn);
enum EFinishLevelType
{

View file

@ -148,7 +148,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return;
spot = state->GetSpotWithMinMaxDistance(PClass::FindClass("BossSpot"), actor->X(), actor->Y(), 128, 0);
spot = state->GetSpotWithMinMaxDistance(PClass::FindActor("BossSpot"), actor->X(), actor->Y(), 128, 0);
if (spot == NULL) return;
prev = actor->Pos();

View file

@ -14,10 +14,10 @@
#include "templates.h"
#include "r_data/r_translate.h"
#include "doomstat.h"
#include "farchive.h"
#include "d_player.h"
#include "a_morph.h"
#include "p_spec.h"
#include "serializer.h"
// Include all the other Heretic stuff here to reduce compile time
#include "a_chicken.cpp"

View file

@ -866,16 +866,18 @@ class ARainTracker : public AInventory
{
DECLARE_CLASS (ARainTracker, AInventory)
public:
void Serialize (FArchive &arc);
AActor *Rain1, *Rain2;
void Serialize(FSerializer &arc);
TObjPtr<AActor> Rain1, Rain2;
};
IMPLEMENT_CLASS (ARainTracker)
void ARainTracker::Serialize (FArchive &arc)
void ARainTracker::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Rain1 << Rain2;
arc("rain1", Rain1)
("rain2", Rain2);
}
//----------------------------------------------------------------------------
@ -1140,10 +1142,11 @@ class APhoenixRod : public AWeapon
{
DECLARE_CLASS (APhoenixRod, AWeapon)
public:
void Serialize (FArchive &arc)
void Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << FlameCount;
arc("flamecount", FlameCount);
}
int FlameCount; // for flamethrower duration
};

View file

@ -31,10 +31,11 @@ class ACWeapWraithverge : public AClericWeapon
{
DECLARE_CLASS (ACWeapWraithverge, AClericWeapon)
public:
void Serialize (FArchive &arc)
void Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << CHolyCount;
arc("cholycount", CHolyCount);
}
PalEntry GetBlend ()
{

View file

@ -64,19 +64,21 @@ class AHeresiarch : public AActor
{
DECLARE_CLASS (AHeresiarch, AActor)
public:
const PClass *StopBall;
PClassActor *StopBall;
DAngle BallAngle;
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Die (AActor *source, AActor *inflictor, int dmgflags);
};
IMPLEMENT_CLASS (AHeresiarch)
void AHeresiarch::Serialize (FArchive &arc)
void AHeresiarch::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << StopBall << BallAngle;
arc("stopball", StopBall)
("ballangle", BallAngle);
}
void AHeresiarch::Die (AActor *source, AActor *inflictor, int dmgflags)
@ -105,10 +107,13 @@ public:
DAngle AngleOffset;
DAngle OldAngle;
void Serialize (FArchive &arc)
void Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << AngleOffset << OldAngle;
arc("angleoffset", AngleOffset)
("oldangle", OldAngle);
}
bool SpecialBlastHandling (AActor *source, double strength)

View file

@ -17,13 +17,13 @@
#include "p_terrain.h"
#include "m_bbox.h"
#include "ravenshared.h"
#include "farchive.h"
#include "v_palette.h"
#include "g_game.h"
#include "p_blockmap.h"
#include "r_utility.h"
#include "p_maputl.h"
#include "p_spec.h"
#include "serializer.h"
// Include all the Hexen stuff here to reduce compile time
#include "a_bats.cpp"

View file

@ -29,10 +29,11 @@ class AMWeapBloodscourge : public AMageWeapon
{
DECLARE_CLASS (AMWeapBloodscourge, AMageWeapon)
public:
void Serialize (FArchive &arc)
void Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << MStaffCount;
arc("mstaffcount", MStaffCount);
}
PalEntry GetBlend ()
{

View file

@ -22,7 +22,8 @@ class AThrustFloor : public AActor
DECLARE_CLASS (AThrustFloor, AActor)
HAS_OBJECT_POINTERS
public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Activate (AActor *activator);
void Deactivate (AActor *activator);
@ -34,10 +35,10 @@ IMPLEMENT_POINTY_CLASS (AThrustFloor)
DECLARE_POINTER (DirtClump)
END_POINTERS
void AThrustFloor::Serialize (FArchive &arc)
void AThrustFloor::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << DirtClump;
arc("dirtclump", DirtClump);
}
void AThrustFloor::Activate (AActor *activator)

View file

@ -43,7 +43,7 @@
#include "m_png.h"
#include "gstrings.h"
#include "wi_stuff.h"
#include "farchive.h"
#include "serializer.h"
//==========================================================================
@ -54,7 +54,7 @@
struct FHubInfo
{
int finished_ep;
int levelnum;
int maxkills;
int maxitems;
@ -65,7 +65,7 @@ struct FHubInfo
FHubInfo &operator=(const wbstartstruct_t &wbs)
{
finished_ep = wbs.finished_ep;
levelnum = wbs.finished_ep;
maxkills = wbs.maxkills;
maxsecret= wbs.maxsecret;
maxitems = wbs.maxitems;
@ -86,7 +86,7 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
{
for (i = 0; i < hubdata.Size(); i++)
{
if (hubdata[i].finished_ep==level.levelnum)
if (hubdata[i].levelnum == level.levelnum)
{
hubdata[i] = *wbs;
break;
@ -97,7 +97,7 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
hubdata[hubdata.Reserve(1)] = *wbs;
}
hubdata[i].finished_ep=level.levelnum;
hubdata[i].levelnum = level.levelnum;
if (!multiplayer && !deathmatch)
{
// The player counters don't work in hubs
@ -148,39 +148,41 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
// Serialize intermission info for hubs
//
//==========================================================================
#define HUBS_ID MAKE_ID('h','u','B','s')
static void G_SerializeHub(FArchive & arc)
FSerializer &Serialize(FSerializer &arc, const char *key, wbplayerstruct_t &h, wbplayerstruct_t *def)
{
int i=hubdata.Size();
arc << i;
if (i>0)
if (arc.BeginObject(key))
{
if (arc.IsStoring()) arc.Write(&hubdata[0], i * sizeof(FHubInfo));
else
{
hubdata.Resize(i);
arc.Read(&hubdata[0], i * sizeof(FHubInfo));
arc("in", h.in)
("kills", h.skills)
("items", h.sitems)
("secrets", h.ssecret)
("time", h.stime)
("fragcount", h.fragcount)
.Array("frags", h.frags, MAXPLAYERS)
.EndObject();
}
}
else hubdata.Clear();
return arc;
}
void G_WriteHubInfo (FILE *file)
FSerializer &Serialize(FSerializer &arc, const char *key, FHubInfo &h, FHubInfo *def)
{
FPNGChunkArchive arc(file, HUBS_ID);
G_SerializeHub(arc);
if (arc.BeginObject(key))
{
arc("levelnum", h.levelnum)
("maxkills", h.maxkills)
("maxitems", h.maxitems)
("maxsecret", h.maxsecret)
("maxfrags", h.maxfrags)
.Array("players", h.plyr, MAXPLAYERS)
.EndObject();
}
return arc;
}
void G_ReadHubInfo (PNGHandle *png)
void G_SerializeHub(FSerializer &arc)
{
int chunklen;
if ((chunklen = M_FindPNGChunk (png, HUBS_ID)) != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), HUBS_ID, chunklen);
G_SerializeHub(arc);
}
arc("hubinfo", hubdata);
}
void G_ClearHubInfo()

View file

@ -1,14 +1,11 @@
#ifndef __G_HUB_H
#define __G_HUB_H
#include <stdio.h>
struct PNGHandle;
struct cluster_info_t;
struct wbstartstruct_t;
class FSerializer;
void G_WriteHubInfo (FILE *file);
void G_ReadHubInfo (PNGHandle *png);
void G_SerializeHub (FSerializer &file);
void G_LeavingHub(int mode, cluster_info_t * cluster, struct wbstartstruct_t * wbs);
#endif

View file

@ -81,10 +81,10 @@
#include "a_sharedglobal.h"
#include "a_strifeglobal.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "r_renderer.h"
#include "r_utility.h"
#include "p_spec.h"
#include "serializer.h"
#include "gi.h"
@ -93,7 +93,7 @@
void STAT_StartNewGame(const char *lev);
void STAT_ChangeLevel(const char *newl);
EXTERN_CVAR(Bool, save_formatted)
EXTERN_CVAR (Float, sv_gravity)
EXTERN_CVAR (Float, sv_aircontrol)
EXTERN_CVAR (Int, disableautosave)
@ -822,7 +822,7 @@ void G_DoCompleted (void)
}
else
{ // Make sure we don't have a snapshot lying around from before.
level.info->ClearSnapshot();
level.info->Snapshot.Clean();
}
}
else
@ -1477,135 +1477,6 @@ void G_AirControlChanged ()
}
}
//==========================================================================
//
//
//==========================================================================
void gl_SerializeGlobals(FArchive &arc);
void G_SerializeLevel (FArchive &arc, bool hubLoad)
{
int i = level.totaltime;
Renderer->StartSerialize(arc);
if (arc.IsLoading()) P_DestroyThinkers(hubLoad);
gl_SerializeGlobals(arc);
arc << level.flags
<< level.flags2
<< level.fadeto
<< level.found_secrets
<< level.found_items
<< level.killed_monsters
<< level.gravity
<< level.aircontrol
<< level.teamdamage
<< level.maptime
<< i;
// Hub transitions must keep the current total time
if (!hubLoad)
level.totaltime = i;
arc << level.skytexture1 << level.skytexture2;
if (arc.IsLoading())
{
sky1texture = level.skytexture1;
sky2texture = level.skytexture2;
R_InitSkyMap();
}
G_AirControlChanged ();
BYTE t;
// Does this level have scrollers?
if (arc.IsStoring ())
{
t = level.Scrolls ? 1 : 0;
arc << t;
}
else
{
arc << t;
if (level.Scrolls)
{
delete[] level.Scrolls;
level.Scrolls = NULL;
}
if (t)
{
level.Scrolls = new FSectorScrollValues[numsectors];
memset (level.Scrolls, 0, sizeof(level.Scrolls)*numsectors);
}
}
FBehavior::StaticSerializeModuleStates (arc);
if (arc.IsLoading()) interpolator.ClearInterpolations();
P_SerializeWorld(arc);
P_SerializeThinkers (arc, hubLoad);
P_SerializeWorldActors(arc); // serializing actor pointers in the world data must be done after SerializeWorld has restored the entire sector state, otherwise LinkToWorld may fail.
P_SerializePolyobjs (arc);
P_SerializeSubsectors(arc);
StatusBar->Serialize (arc);
arc << level.total_monsters << level.total_items << level.total_secrets;
// Does this level have custom translations?
FRemapTable *trans;
WORD w;
if (arc.IsStoring ())
{
for (unsigned int i = 0; i < translationtables[TRANSLATION_LevelScripted].Size(); ++i)
{
trans = translationtables[TRANSLATION_LevelScripted][i];
if (trans != NULL && !trans->IsIdentity())
{
w = WORD(i);
arc << w;
trans->Serialize(arc);
}
}
w = 0xffff;
arc << w;
}
else
{
while (arc << w, w != 0xffff)
{
trans = translationtables[TRANSLATION_LevelScripted].GetVal(w);
if (trans == NULL)
{
trans = new FRemapTable;
translationtables[TRANSLATION_LevelScripted].SetVal(w, trans);
}
trans->Serialize(arc);
}
}
// This must be saved, too, of course!
FCanvasTextureInfo::Serialize (arc);
AM_SerializeMarkers(arc);
P_SerializePlayers (arc, hubLoad);
P_SerializeSounds (arc);
if (arc.IsLoading())
{
for (i = 0; i < numsectors; i++)
{
P_Recalculate3DFloors(&sectors[i]);
}
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].mo != NULL)
{
players[i].mo->SetupWeaponSlots();
}
}
}
Renderer->EndSerialize(arc);
}
//==========================================================================
//
// Archives the current level
@ -1614,19 +1485,18 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
void G_SnapshotLevel ()
{
if (level.info->snapshot)
delete level.info->snapshot;
level.info->Snapshot.Clean();
if (level.info->isValid())
{
level.info->snapshotVer = SAVEVER;
level.info->snapshot = new FCompressedMemFile;
level.info->snapshot->Open ();
FArchive arc (*level.info->snapshot);
FSerializer arc;
if (arc.OpenWriter(save_formatted))
{
SaveVersion = SAVEVER;
G_SerializeLevel(arc, false);
level.info->Snapshot = arc.GetCompressedOutput();
}
}
}
@ -1639,18 +1509,15 @@ void G_SnapshotLevel ()
void G_UnSnapshotLevel (bool hubLoad)
{
if (level.info->snapshot == NULL)
if (level.info->Snapshot.mBuffer == nullptr)
return;
if (level.info->isValid())
{
SaveVersion = level.info->snapshotVer;
level.info->snapshot->Reopen ();
FArchive arc (*level.info->snapshot);
if (hubLoad)
arc.SetHubTravel ();
FSerializer arc;
if (!arc.OpenReader(&level.info->Snapshot)) return;
G_SerializeLevel (arc, hubLoad);
arc.Close ();
level.FromSnapshot = true;
TThinkerIterator<APlayerPawn> it;
@ -1680,7 +1547,7 @@ void G_UnSnapshotLevel (bool hubLoad)
}
}
// No reason to keep the snapshot around once the level's been entered.
level.info->ClearSnapshot();
level.info->Snapshot.Clean();
if (hubLoad)
{
// Unlock ACS global strings that were locked when the snapshot was made.
@ -1693,81 +1560,68 @@ void G_UnSnapshotLevel (bool hubLoad)
//
//==========================================================================
static void writeSnapShot (FArchive &arc, level_info_t *i)
{
arc << i->snapshotVer << i->MapName;
i->snapshot->Serialize (arc);
}
//==========================================================================
//
//
//==========================================================================
void G_WriteSnapshots (FILE *file)
void G_WriteSnapshots(TArray<FString> &filenames, TArray<FCompressedBuffer> &buffers)
{
unsigned int i;
FString filename;
for (i = 0; i < wadlevelinfos.Size(); i++)
{
if (wadlevelinfos[i].snapshot)
if (wadlevelinfos[i].Snapshot.mCompressedSize > 0)
{
FPNGChunkArchive arc (file, SNAP_ID);
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]);
filename.Format("%s.map.json", wadlevelinfos[i].MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(wadlevelinfos[i].Snapshot);
}
}
if (TheDefaultLevelInfo.snapshot != NULL)
if (TheDefaultLevelInfo.Snapshot.mCompressedSize > 0)
{
FPNGChunkArchive arc (file, DSNP_ID);
writeSnapShot(arc, &TheDefaultLevelInfo);
filename.Format("%s.mapd.json", TheDefaultLevelInfo.MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(TheDefaultLevelInfo.Snapshot);
}
}
FPNGChunkArchive *arc = NULL;
//==========================================================================
//
//
//==========================================================================
void G_WriteVisited(FSerializer &arc)
{
if (arc.BeginArray("visited"))
{
// Write out which levels have been visited
for (i = 0; i < wadlevelinfos.Size(); ++i)
for (auto & wi : wadlevelinfos)
{
if (wadlevelinfos[i].flags & LEVEL_VISITED)
if (wi.flags & LEVEL_VISITED)
{
if (arc == NULL)
{
arc = new FPNGChunkArchive (file, VIST_ID);
}
(*arc) << wadlevelinfos[i].MapName;
arc.AddString(nullptr, wi.MapName);
}
}
if (arc != NULL)
{
FString empty = "";
(*arc) << empty;
delete arc;
arc.EndArray();
}
// Store player classes to be used when spawning a random class
if (multiplayer)
{
FPNGChunkArchive arc2 (file, RCLS_ID);
for (i = 0; i < MAXPLAYERS; ++i)
{
SBYTE cnum = SinglePlayerClass[i];
arc2 << cnum;
}
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
}
// Store player classes that are currently in use
FPNGChunkArchive arc3 (file, PCLS_ID);
for (i = 0; i < MAXPLAYERS; ++i)
if (arc.BeginObject("playerclasses"))
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
BYTE pnum;
if (playeringame[i])
{
pnum = i;
arc3 << pnum;
arc3.UserWriteClass (players[i].cls);
FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
pnum = 255;
arc3 << pnum;
}
arc.EndObject();
}
}
@ -1776,95 +1630,89 @@ void G_WriteSnapshots (FILE *file)
//
//==========================================================================
void G_ReadSnapshots (PNGHandle *png)
void G_ReadSnapshots(FResourceFile *resf)
{
DWORD chunkLen;
FString MapName;
level_info_t *i;
G_ClearSnapshots();
chunkLen = (DWORD)M_FindPNGChunk (png, SNAP_ID);
while (chunkLen != 0)
for (unsigned j = 0; j < resf->LumpCount(); j++)
{
FPNGChunkArchive arc (png->File->GetFile(), SNAP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
i = FindLevelInfo (MapName);
i->snapshotVer = snapver;
i->snapshot = new FCompressedMemFile;
i->snapshot->Serialize (arc);
chunkLen = (DWORD)M_NextPNGChunk (png, SNAP_ID);
}
chunkLen = (DWORD)M_FindPNGChunk (png, DSNP_ID);
if (chunkLen != 0)
FResourceLump * resl = resf->GetLump(j);
if (resl != nullptr)
{
FPNGChunkArchive arc (png->File->GetFile(), DSNP_ID, chunkLen);
DWORD snapver;
arc << snapver;
arc << MapName;
TheDefaultLevelInfo.snapshotVer = snapver;
TheDefaultLevelInfo.snapshot = new FCompressedMemFile;
TheDefaultLevelInfo.snapshot->Serialize (arc);
}
chunkLen = (DWORD)M_FindPNGChunk (png, VIST_ID);
if (chunkLen != 0)
auto ptr = strstr(resl->FullName, ".map.json");
if (ptr != nullptr)
{
FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen);
while (arc << MapName, MapName.Len() > 0)
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
i = FindLevelInfo(mapname);
if (i != nullptr)
{
i = FindLevelInfo(MapName);
i->flags |= LEVEL_VISITED;
i->Snapshot = resl->GetRawData();
}
}
chunkLen = (DWORD)M_FindPNGChunk (png, RCLS_ID);
if (chunkLen != 0)
else
{
FPNGChunkArchive arc (png->File->GetFile(), PCLS_ID, chunkLen);
SBYTE cnum;
for (DWORD j = 0; j < chunkLen; ++j)
auto ptr = strstr(resl->FullName, ".mapd.json");
if (ptr != nullptr)
{
arc << cnum;
SinglePlayerClass[j] = cnum;
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
TheDefaultLevelInfo.Snapshot = resl->GetRawData();
}
}
}
}
}
chunkLen = (DWORD)M_FindPNGChunk (png, PCLS_ID);
if (chunkLen != 0)
//==========================================================================
//
//
//==========================================================================
void G_ReadVisited(FSerializer &arc)
{
FPNGChunkArchive arc (png->File->GetFile(), RCLS_ID, chunkLen);
BYTE pnum;
arc << pnum;
while (pnum != 255)
if (arc.BeginArray("visited"))
{
arc.UserReadClass (players[pnum].cls);
arc << pnum;
for (int s = arc.ArraySize(); s > 0; s--)
{
FString str;
arc(nullptr, str);
auto i = FindLevelInfo(str);
if (i != nullptr) i->flags |= LEVEL_VISITED;
}
}
png->File->ResetFilePtr();
arc.EndArray();
}
arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
if (arc.BeginObject("playerclasses"))
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
arc.EndObject();
}
}
//==========================================================================
//
//
//==========================================================================
CCMD(listsnapshots)
{
for (unsigned i = 0; i < wadlevelinfos.Size(); ++i)
{
FCompressedMemFile *snapshot = wadlevelinfos[i].snapshot;
if (snapshot != NULL)
FCompressedBuffer *snapshot = &wadlevelinfos[i].Snapshot;
if (snapshot->mBuffer != nullptr)
{
unsigned int comp, uncomp;
snapshot->GetSizes(comp, uncomp);
Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), comp, uncomp);
Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), snapshot->mCompressedSize, snapshot->mSize);
}
}
}
@ -1874,38 +1722,32 @@ CCMD(listsnapshots)
//
//==========================================================================
static void writeDefereds (FArchive &arc, level_info_t *i)
void P_WriteACSDefereds (FSerializer &arc)
{
arc << i->MapName << i->defered;
}
bool found = false;
//==========================================================================
//
//
//==========================================================================
void P_WriteACSDefereds (FILE *file)
// only write this stuff if needed
for (auto &wi : wadlevelinfos)
{
FPNGChunkArchive *arc = NULL;
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
if (wi.deferred.Size() > 0)
{
if (wadlevelinfos[i].defered)
{
if (arc == NULL)
{
arc = new FPNGChunkArchive (file, ACSD_ID);
}
writeDefereds (*arc, (level_info_t *)&wadlevelinfos[i]);
found = true;
break;
}
}
if (arc != NULL)
if (found && arc.BeginObject("deferred"))
{
// Signal end of defereds
FString empty = "";
(*arc) << empty;
delete arc;
for (auto &wi : wadlevelinfos)
{
if (wi.deferred.Size() > 0)
{
if (wi.deferred.Size() > 0)
{
arc(wi.MapName, wi.deferred);
}
}
}
arc.EndObject();
}
}
@ -1914,28 +1756,27 @@ void P_WriteACSDefereds (FILE *file)
//
//==========================================================================
void P_ReadACSDefereds (PNGHandle *png)
void P_ReadACSDefereds (FSerializer &arc)
{
FString MapName;
size_t chunklen;
P_RemoveDefereds ();
if ((chunklen = M_FindPNGChunk (png, ACSD_ID)) != 0)
if (arc.BeginObject("deferred"))
{
FPNGChunkArchive arc (png->File->GetFile(), ACSD_ID, chunklen);
const char *key;
while (arc << MapName, MapName.Len() > 0)
while ((key = arc.GetKey()))
{
level_info_t *i = FindLevelInfo(MapName);
level_info_t *i = FindLevelInfo(key);
if (i == NULL)
{
I_Error("Unknown map '%s' in savegame", MapName.GetChars());
I_Error("Unknown map '%s' in savegame", key);
}
arc << i->defered;
arc(nullptr, i->deferred);
}
arc.EndObject();
}
png->File->ResetFilePtr();
}
@ -1947,9 +1788,9 @@ void P_ReadACSDefereds (PNGHandle *png)
void FLevelLocals::Tick ()
{
// Reset carry sectors
if (Scrolls != NULL)
if (Scrolls.Size() > 0)
{
memset (Scrolls, 0, sizeof(*Scrolls)*numsectors);
memset (&Scrolls[0], 0, sizeof(Scrolls[0])*Scrolls.Size());
}
}
@ -1964,10 +1805,10 @@ void FLevelLocals::AddScroller (int secnum)
{
return;
}
if (Scrolls == NULL)
if (Scrolls.Size() == 0)
{
Scrolls = new FSectorScrollValues[numsectors];
memset (Scrolls, 0, sizeof(*Scrolls)*numsectors);
Scrolls.Resize(numsectors);
memset (&Scrolls[0], 0, sizeof(Scrolls[0])*numsectors);
}
}

View file

@ -38,7 +38,9 @@
#include "doomdef.h"
#include "sc_man.h"
#include "s_sound.h"
#include "p_acs.h"
#include "textures/textures.h"
#include "resourcefiles/file_zip.h"
struct level_info_t;
struct cluster_info_t;
@ -223,8 +225,6 @@ enum ELevelFlags : unsigned int
};
struct acsdefered_t;
struct FSpecialAction
{
FName Type; // this is initialized before the actors...
@ -232,7 +232,6 @@ struct FSpecialAction
int Args[5]; // must allow 16 bit tags for 666 & 667!
};
class FCompressedMemFile;
class DScroller;
class FScanner;
@ -295,9 +294,8 @@ struct level_info_t
FString LevelName;
SBYTE WallVertLight, WallHorizLight;
int musicorder;
FCompressedMemFile *snapshot;
DWORD snapshotVer;
struct acsdefered_t *defered;
FCompressedBuffer Snapshot;
TArray<acsdefered_t> deferred;
float skyspeed1;
float skyspeed2;
DWORD fadeto;
@ -346,14 +344,16 @@ struct level_info_t
}
~level_info_t()
{
ClearSnapshot();
Snapshot.Clean();
ClearDefered();
}
void Reset();
bool isValid();
FString LookupLevelName ();
void ClearSnapshot();
void ClearDefered();
void ClearDefered()
{
deferred.Clear();
}
level_info_t *CheckLevelRedirect ();
template<class T>
@ -375,17 +375,12 @@ struct level_info_t
}
};
// [RH] These get zeroed every tic and are updated by thinkers.
struct FSectorScrollValues
{
DVector2 Scroll;
};
struct FLevelLocals
{
void Tick ();
void AddScroller (int secnum);
BYTE md5[16]; // for savegame validation. If the MD5 does not match the savegame won't be loaded.
int time; // time in the hub
int maptime; // time in the map
int totaltime; // time in the game
@ -436,7 +431,7 @@ struct FLevelLocals
int airsupply;
int DefaultEnvironment; // Default sound environment.
FSectorScrollValues *Scrolls; // NULL if no DScrollers in this level
TArray<DVector2> Scrolls; // NULL if no DScrollers in this level
SBYTE WallVertLight; // Light diffs for vert/horiz walls
SBYTE WallHorizLight;
@ -537,9 +532,10 @@ void G_ClearSnapshots (void);
void P_RemoveDefereds ();
void G_SnapshotLevel (void);
void G_UnSnapshotLevel (bool keepPlayers);
struct PNGHandle;
void G_ReadSnapshots (PNGHandle *png);
void G_WriteSnapshots (FILE *file);
void G_ReadSnapshots (FResourceFile *);
void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteVisited(FSerializer &arc);
void G_ReadVisited(FSerializer &arc);
void G_ClearHubInfo();
enum ESkillProperty

View file

@ -45,7 +45,6 @@
#include "i_system.h"
#include "gi.h"
#include "gstrings.h"
#include "farchive.h"
#include "p_acs.h"
#include "doomstat.h"
#include "d_player.h"
@ -196,7 +195,7 @@ void G_ClearSnapshots (void)
{
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
{
wadlevelinfos[i].ClearSnapshot();
wadlevelinfos[i].Snapshot.Clean();
}
// Since strings are only locked when snapshotting a level, unlock them
// all now, since we got rid of all the snapshots that cared about them.
@ -248,9 +247,8 @@ void level_info_t::Reset()
WallVertLight = +8;
F1Pic = "";
musicorder = 0;
snapshot = NULL;
snapshotVer = 0;
defered = 0;
Snapshot = { 0,0,0,0,0,nullptr };
deferred.Clear();
skyspeed1 = skyspeed2 = 0.f;
fadeto = 0;
outsidefog = 0xff000000;
@ -334,34 +332,6 @@ FString level_info_t::LookupLevelName()
}
//==========================================================================
//
//
//==========================================================================
void level_info_t::ClearSnapshot()
{
if (snapshot != NULL) delete snapshot;
snapshot = NULL;
}
//==========================================================================
//
//
//==========================================================================
void level_info_t::ClearDefered()
{
acsdefered_t *def = defered;
while (def)
{
acsdefered_t *next = def->next;
delete def;
def = next;
}
defered = NULL;
}
//==========================================================================
//
//

View file

@ -11,9 +11,9 @@
#include "thingdef/thingdef.h"
#include "g_level.h"
#include "doomstat.h"
#include "farchive.h"
#include "a_pickups.h"
#include "d_player.h"
#include "serializer.h"
#define MAULATORTICS (25*35)
@ -79,10 +79,10 @@ void AMinotaurFriend::BeginPlay ()
StartTime = -1;
}
void AMinotaurFriend::Serialize (FArchive &arc)
void AMinotaurFriend::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << StartTime;
arc("starttime", StartTime);
}
void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags)

View file

@ -23,7 +23,8 @@ public:
void Die (AActor *source, AActor *inflictor, int dmgflags);
bool OkayToSwitchTarget (AActor *other);
void BeginPlay ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
};
#endif //__RAVENSHARED_H__

View file

@ -11,7 +11,7 @@
#include "p_enemy.h"
#include "statnums.h"
#include "templates.h"
#include "farchive.h"
#include "serializer.h"
#include "r_data/r_translate.h"
static FRandom pr_freezedeath ("FreezeDeath");
@ -361,7 +361,7 @@ class DCorpsePointer : public DThinker
public:
DCorpsePointer (AActor *ptr);
void Destroy ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
TObjPtr<AActor> Corpse;
DWORD Count; // Only the first corpse pointer's count is valid.
private:
@ -435,10 +435,11 @@ void DCorpsePointer::Destroy ()
Super::Destroy ();
}
void DCorpsePointer::Serialize (FArchive &arc)
void DCorpsePointer::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << Corpse << Count;
arc("corpse", Corpse)
("count", Count);
}

View file

@ -6,7 +6,7 @@
#include "templates.h"
#include "g_level.h"
#include "d_player.h"
#include "farchive.h"
#include "serializer.h"
IMPLEMENT_CLASS (AArmor)
@ -21,10 +21,17 @@ IMPLEMENT_CLASS (AHexenArmor)
//
//===========================================================================
void ABasicArmor::Serialize (FArchive &arc)
void ABasicArmor::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << SavePercent << BonusCount << MaxAbsorb << MaxFullAbsorb << AbsorbCount << ArmorType << ActualSaveAmount;
auto def = (ABasicArmor *)GetDefault();
arc("savepercent", SavePercent, def->SavePercent)
("bonuscount", BonusCount, def->BonusCount)
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb)
("absorbcount", AbsorbCount, def->AbsorbCount)
("armortype", ArmorType, def->ArmorType)
("actualsaveamount", ActualSaveAmount, def->ActualSaveAmount);
}
//===========================================================================
@ -192,11 +199,15 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
//
//===========================================================================
void ABasicArmorPickup::Serialize (FArchive &arc)
void ABasicArmorPickup::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << SavePercent << SaveAmount << MaxAbsorb << MaxFullAbsorb;
arc << DropTime;
auto def = (ABasicArmorPickup *)GetDefault();
arc("savepercent", SavePercent, def->SavePercent)
("saveamount", SaveAmount, def->SaveAmount)
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb);
}
//===========================================================================
@ -274,11 +285,17 @@ bool ABasicArmorPickup::Use (bool pickup)
//
//===========================================================================
void ABasicArmorBonus::Serialize (FArchive &arc)
void ABasicArmorBonus::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << SavePercent << SaveAmount << MaxSaveAmount << BonusCount << BonusMax
<< MaxAbsorb << MaxFullAbsorb;
auto def = (ABasicArmorBonus *)GetDefault();
arc("savepercent", SavePercent, def->SavePercent)
("saveamount", SaveAmount, def->SaveAmount)
("maxsaveamount", MaxSaveAmount, def->MaxSaveAmount)
("bonuscount", BonusCount, def->BonusCount)
("bonusmax", BonusMax, def->BonusMax)
("maxabsorb", MaxAbsorb, def->MaxAbsorb)
("maxfullabsorb", MaxFullAbsorb, def->MaxFullAbsorb);
}
//===========================================================================
@ -371,13 +388,12 @@ bool ABasicArmorBonus::Use (bool pickup)
//
//===========================================================================
void AHexenArmor::Serialize (FArchive &arc)
void AHexenArmor::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Slots[0] << Slots[1] << Slots[2] << Slots[3]
<< Slots[4]
<< SlotsIncrement[0] << SlotsIncrement[1] << SlotsIncrement[2]
<< SlotsIncrement[3];
auto def = (AHexenArmor *)GetDefault();
arc.Array("slots", Slots, def->Slots, 5, true)
.Array("slotsincrement", SlotsIncrement, def->SlotsIncrement, 4);
}
//===========================================================================

View file

@ -19,7 +19,7 @@
#include "g_level.h"
#include "doomstat.h"
#include "v_palette.h"
#include "farchive.h"
#include "serializer.h"
#include "r_utility.h"
#include "r_data/colormaps.h"
@ -101,12 +101,15 @@ bool APowerupGiver::Use (bool pickup)
//
//===========================================================================
void APowerupGiver::Serialize (FArchive &arc)
void APowerupGiver::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << PowerupType;
arc << EffectTics << BlendColor << Mode;
arc << Strength;
auto def = (APowerupGiver*)GetDefault();
arc("poweruptype", PowerupType, def->PowerupType)
("effecttics", EffectTics, def->EffectTics)
("blendcolor", BlendColor, def->BlendColor)
("mode", Mode, def->Mode)
("strength", Strength, def->Strength);
}
// Powerup -------------------------------------------------------------------
@ -136,11 +139,14 @@ void APowerup::Tick ()
//
//===========================================================================
void APowerup::Serialize (FArchive &arc)
void APowerup::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << EffectTics << BlendColor << Mode;
arc << Strength;
auto def = (APowerup*)GetDefault();
arc("effecttics", EffectTics, def->EffectTics)
("blendcolor", BlendColor, def->BlendColor)
("mode", Mode, def->Mode)
("strength", Strength, def->Strength);
}
//===========================================================================
@ -901,10 +907,11 @@ IMPLEMENT_CLASS (APowerTorch)
//
//===========================================================================
void APowerTorch::Serialize (FArchive &arc)
void APowerTorch::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << NewTorch << NewTorchDelta;
arc("newtorch", NewTorch)
("newtorchdelta", NewTorchDelta);
}
//===========================================================================
@ -963,10 +970,10 @@ IMPLEMENT_CLASS (APowerFlight)
//
//===========================================================================
void APowerFlight::Serialize (FArchive &arc)
void APowerFlight::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << HitCenterFrame;
arc("hitcenterframe", HitCenterFrame);
}
//===========================================================================
@ -1217,10 +1224,10 @@ IMPLEMENT_CLASS (APowerSpeed)
//
//===========================================================================
void APowerSpeed::Serialize(FArchive &arc)
void APowerSpeed::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << SpeedFlags;
arc("speedflags", SpeedFlags);
}
//===========================================================================
@ -1899,11 +1906,14 @@ IMPLEMENT_CLASS(APowerMorph)
//
//===========================================================================
void APowerMorph::Serialize (FArchive &arc)
void APowerMorph::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << PlayerClass << MorphStyle << MorphFlash << UnMorphFlash;
arc << Player;
arc("playerclass", PlayerClass)
("morphstyle", MorphStyle)
("morphflash", MorphFlash)
("unmorphflash", UnMorphFlash)
("player", Player);
}
//===========================================================================

View file

@ -16,7 +16,8 @@ public:
virtual bool HandlePickup (AInventory *item);
virtual AInventory *CreateCopy (AActor *other);
virtual AInventory *CreateTossable ();
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void OwnerDied ();
virtual bool GetNoTeleportFreeze();
virtual PalEntry GetBlend ();
@ -51,7 +52,8 @@ class APowerupGiver : public AInventory
DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver)
public:
virtual bool Use (bool pickup);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
PClassActor *PowerupType;
@ -121,7 +123,8 @@ class APowerTorch : public APowerLightAmp
{
DECLARE_CLASS (APowerTorch, APowerLightAmp)
public:
void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
protected:
void DoEffect ();
int NewTorch, NewTorchDelta;
@ -132,7 +135,8 @@ class APowerFlight : public APowerup
DECLARE_CLASS (APowerFlight, APowerup)
public:
bool DrawPowerup (int x, int y);
void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
protected:
void InitEffect ();
@ -155,7 +159,8 @@ class APowerSpeed : public APowerup
DECLARE_CLASS (APowerSpeed, APowerup)
protected:
void DoEffect ();
void Serialize(FArchive &arc);
virtual void Serialize(FSerializer &arc);
double GetSpeedFactor();
public:
int SpeedFlags;
@ -272,7 +277,8 @@ class APowerMorph : public APowerup
{
DECLARE_CLASS( APowerMorph, APowerup )
public:
void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
void SetNoCallUndoMorph() { bNoCallUndoMorph = true; }
FNameNoInit PlayerClass, MorphFlash, UnMorphFlash;

View file

@ -36,7 +36,7 @@
#include "info.h"
#include "a_sharedglobal.h"
#include "p_local.h"
#include "farchive.h"
#include "serializer.h"
#include "math/cmath.h"
/*
@ -55,7 +55,8 @@ public:
void PostBeginPlay ();
void Tick ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
protected:
DAngle Center;
DAngle Acc;
@ -65,10 +66,13 @@ protected:
IMPLEMENT_CLASS (ASecurityCamera)
void ASecurityCamera::Serialize (FArchive &arc)
void ASecurityCamera::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Center << Acc << Delta << Range;
arc("center", Center)
("acc", Acc)
("delta", Delta)
("range", Range);
}
void ASecurityCamera::PostBeginPlay ()
@ -114,17 +118,18 @@ public:
void PostBeginPlay ();
void Tick ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
protected:
DAngle MaxPitchChange;
};
IMPLEMENT_CLASS (AAimingCamera)
void AAimingCamera::Serialize (FArchive &arc)
void AAimingCamera::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << MaxPitchChange;
arc("maxpitchchange", MaxPitchChange);
}
void AAimingCamera::PostBeginPlay ()

View file

@ -44,8 +44,9 @@
#include "d_net.h"
#include "colormatcher.h"
#include "v_palette.h"
#include "farchive.h"
#include "serializer.h"
#include "doomdata.h"
#include "r_state.h"
static double DecalWidth, DecalLeft, DecalRight;
static double SpreadZ;
@ -58,6 +59,7 @@ static int ImpactCount;
CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE)
IMPLEMENT_POINTY_CLASS (DBaseDecal)
DECLARE_POINTER(WallPrev)
DECLARE_POINTER(WallNext)
END_POINTERS
@ -75,7 +77,7 @@ DBaseDecal::DBaseDecal ()
DBaseDecal::DBaseDecal (double z)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(1.), ScaleY(1.), Alpha(1.),
AlphaColor(0), Translation(0), RenderFlags(0)
AlphaColor(0), Translation(0), RenderFlags(0), Side(nullptr), Sector(nullptr)
{
RenderStyle = STYLE_None;
PicNum.SetInvalid();
@ -83,8 +85,8 @@ DBaseDecal::DBaseDecal (double z)
DBaseDecal::DBaseDecal (int statnum, double z)
: DThinker(statnum),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(1.), ScaleY(1.), Alpha(1.),
AlphaColor(0), Translation(0), RenderFlags(0)
WallNext(nullptr), WallPrev(nullptr), LeftDistance(0), Z(z), ScaleX(1.), ScaleY(1.), Alpha(1.),
AlphaColor(0), Translation(0), RenderFlags(0), Side(nullptr), Sector(nullptr)
{
RenderStyle = STYLE_None;
PicNum.SetInvalid();
@ -92,17 +94,17 @@ DBaseDecal::DBaseDecal (int statnum, double z)
DBaseDecal::DBaseDecal (const AActor *basis)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(basis->Z()), ScaleX(basis->Scale.X), ScaleY(basis->Scale.Y),
WallNext(nullptr), WallPrev(nullptr), LeftDistance(0), Z(basis->Z()), ScaleX(basis->Scale.X), ScaleY(basis->Scale.Y),
Alpha(basis->Alpha), AlphaColor(basis->fillcolor), Translation(basis->Translation), PicNum(basis->picnum),
RenderFlags(basis->renderflags), RenderStyle(basis->RenderStyle)
RenderFlags(basis->renderflags), RenderStyle(basis->RenderStyle), Side(nullptr), Sector(nullptr)
{
}
DBaseDecal::DBaseDecal (const DBaseDecal *basis)
: DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(basis->LeftDistance), Z(basis->Z), ScaleX(basis->ScaleX),
WallNext(nullptr), WallPrev(nullptr), LeftDistance(basis->LeftDistance), Z(basis->Z), ScaleX(basis->ScaleX),
ScaleY(basis->ScaleY), Alpha(basis->Alpha), AlphaColor(basis->AlphaColor), Translation(basis->Translation),
PicNum(basis->PicNum), RenderFlags(basis->RenderFlags), RenderStyle(basis->RenderStyle)
PicNum(basis->PicNum), RenderFlags(basis->RenderFlags), RenderStyle(basis->RenderStyle), Side(nullptr), Sector(nullptr)
{
}
@ -114,64 +116,35 @@ void DBaseDecal::Destroy ()
void DBaseDecal::Remove ()
{
DBaseDecal **prev = WallPrev;
DBaseDecal *next = WallNext;
if (prev && (*prev = next))
next->WallPrev = prev;
WallPrev = NULL;
WallNext = NULL;
if (WallPrev == nullptr)
{
if (Side != nullptr) Side->AttachedDecals = WallNext;
}
else WallPrev->WallNext = WallNext;
if (WallNext != nullptr) WallNext->WallPrev = WallPrev;
WallPrev = nullptr;
WallNext = nullptr;
}
void DBaseDecal::Serialize (FArchive &arc)
void DBaseDecal::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << LeftDistance
<< Z
<< ScaleX << ScaleY
<< Alpha
<< AlphaColor
<< Translation
<< PicNum
<< RenderFlags
<< RenderStyle
<< Sector;
}
void DBaseDecal::SerializeChain (FArchive &arc, DBaseDecal **first)
{
DWORD numInChain;
DBaseDecal *fresh;
DBaseDecal **firstptr = first;
if (arc.IsLoading ())
{
numInChain = arc.ReadCount ();
while (numInChain--)
{
arc << fresh;
*firstptr = fresh;
fresh->WallPrev = firstptr;
firstptr = &fresh->WallNext;
}
}
else
{
numInChain = 0;
fresh = *firstptr;
while (fresh != NULL)
{
fresh = fresh->WallNext;
++numInChain;
}
arc.WriteCount (numInChain);
fresh = *firstptr;
while (numInChain--)
{
arc << fresh;
fresh = fresh->WallNext;
}
}
arc("wallprev", WallPrev)
("wallnext", WallNext)
("leftdistance", LeftDistance)
("z", Z)
("scalex", ScaleX)
("scaley", ScaleY)
("alpha", Alpha)
("alphacolor", AlphaColor)
("translation", Translation)
("picnum", PicNum)
("renderflags", RenderFlags)
("renderstyle", RenderStyle)
("side", Side)
("sector", Sector);
}
void DBaseDecal::GetXY (side_t *wall, double &ox, double &oy) const
@ -211,26 +184,18 @@ void DBaseDecal::SetShade (int r, int g, int b)
// Returns the texture the decal stuck to.
FTextureID DBaseDecal::StickToWall (side_t *wall, double x, double y, F3DFloor *ffloor)
{
// Stick the decal at the end of the chain so it appears on top
DBaseDecal *next, **prev;
Side = wall;
WallPrev = wall->AttachedDecals;
prev = &wall->AttachedDecals;
while (*prev != NULL)
while (WallPrev != nullptr && WallPrev->WallNext != nullptr)
{
next = *prev;
prev = &next->WallNext;
WallPrev = WallPrev->WallNext;
}
if (WallPrev != nullptr) WallPrev->WallNext = this;
else wall->AttachedDecals = this;
WallNext = nullptr;
*prev = this;
WallNext = NULL;
WallPrev = prev;
/*
WallNext = wall->AttachedDecals;
WallPrev = &wall->AttachedDecals;
if (WallNext)
WallNext->WallPrev = &WallNext;
wall->AttachedDecals = this;
*/
sector_t *front, *back;
line_t *line;
FTextureID tex;
@ -592,28 +557,6 @@ CUSTOM_CVAR (Int, cl_maxdecals, 1024, CVAR_ARCHIVE)
}
}
// Uses: target points to previous impact decal
// tracer points to next impact decal
//
// Note that this means we can't simply serialize an impact decal as-is
// because doing so when many are present in a level could result in
// a lot of recursion and we would run out of stack. Not nice. So instead,
// the save game code calls DImpactDecal::SerializeAll to serialize a
// list of impact decals.
void DImpactDecal::SerializeTime (FArchive &arc)
{
if (arc.IsLoading ())
{
ImpactCount = 0;
}
}
void DImpactDecal::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
DImpactDecal::DImpactDecal ()
: DBaseDecal (STAT_AUTODECAL, 0.)
{

View file

@ -1,7 +1,7 @@
#include "a_sharedglobal.h"
#include "g_level.h"
#include "d_player.h"
#include "farchive.h"
#include "serializer.h"
IMPLEMENT_POINTY_CLASS (DFlashFader)
DECLARE_POINTER (ForWho)
@ -26,13 +26,13 @@ void DFlashFader::Destroy ()
Super::Destroy();
}
void DFlashFader::Serialize (FArchive &arc)
void DFlashFader::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TotalTics << StartTic << ForWho;
for (int i = 1; i >= 0; --i)
for (int j = 3; j >= 0; --j)
arc << Blends[i][j];
arc("totaltics", TotalTics)
("starttic", StartTic)
("forwho", ForWho)
.Array("blends", Blends[0], 8);
}
void DFlashFader::Tick ()

View file

@ -9,7 +9,7 @@
#include "r_sky.h"
#include "g_level.h"
#include "r_state.h"
#include "farchive.h"
#include "serializer.h"
static FRandom pr_lightning ("Lightning");
@ -19,44 +19,24 @@ DLightningThinker::DLightningThinker ()
: DThinker (STAT_LIGHTNING)
{
Stopped = false;
LightningLightLevels = NULL;
LightningFlashCount = 0;
NextLightningFlash = ((pr_lightning()&15)+5)*35; // don't flash at level start
LightningLightLevels = new short[numsectors];
clearbufshort(LightningLightLevels, numsectors, SHRT_MAX);
LightningLightLevels.Resize(numsectors);
clearbufshort(&LightningLightLevels[0], numsectors, SHRT_MAX);
}
DLightningThinker::~DLightningThinker ()
{
if (LightningLightLevels != NULL)
{
delete[] LightningLightLevels;
}
}
void DLightningThinker::Serialize (FArchive &arc)
void DLightningThinker::Serialize(FSerializer &arc)
{
int i;
short *lights;
Super::Serialize (arc);
arc << Stopped << NextLightningFlash << LightningFlashCount;
if (arc.IsLoading ())
{
if (LightningLightLevels != NULL)
{
delete[] LightningLightLevels;
}
LightningLightLevels = new short[numsectors];
}
lights = LightningLightLevels;
for (i = numsectors; i > 0; ++lights, --i)
{
arc << *lights;
}
arc("stopped", Stopped)
("next", NextLightningFlash)
("count", LightningFlashCount)
("levels", LightningLightLevels);
}
void DLightningThinker::Tick ()
@ -107,7 +87,7 @@ void DLightningThinker::LightningFlash ()
tempSec->SetLightLevel(LightningLightLevels[j]);
}
}
clearbufshort(LightningLightLevels, numsectors, SHRT_MAX);
clearbufshort(&LightningLightLevels[0], numsectors, SHRT_MAX);
level.flags &= ~LEVEL_SWAPSKIES;
}
return;

View file

@ -13,7 +13,7 @@ class DLightningThinker : public DThinker
public:
DLightningThinker ();
~DLightningThinker ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
void ForceLightning (int mode);
void TerminateLightning();
@ -24,7 +24,7 @@ protected:
int NextLightningFlash;
int LightningFlashCount;
bool Stopped;
short *LightningLightLevels;
TArray<short> LightningLightLevels;
};
void P_StartLightning ();

View file

@ -11,9 +11,10 @@
#include "a_morph.h"
#include "doomstat.h"
#include "g_level.h"
#include "farchive.h"
#include "serializer.h"
#include "p_enemy.h"
#include "d_player.h"
#include "r_data/sprites.h"
static FRandom pr_morphmonst ("MorphMonster");
@ -634,10 +635,16 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damaget
return -1;
}
void AMorphProjectile::Serialize (FArchive &arc)
void AMorphProjectile::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << PlayerClass << MonsterClass << Duration << MorphStyle << MorphFlash << UnMorphFlash;
auto def = (AMorphProjectile*)GetDefault();
arc("playerclass", PlayerClass, def->PlayerClass)
("monsterclass", MonsterClass, def->MonsterClass)
("duration", Duration, def->Duration)
("morphstyle", MorphStyle, def->MorphStyle)
("morphflash", MorphFlash, def->MorphFlash)
("unmorphflash", UnMorphFlash, def->UnMorphFlash);
}
@ -647,10 +654,14 @@ IMPLEMENT_POINTY_CLASS (AMorphedMonster)
DECLARE_POINTER (UnmorphedMe)
END_POINTERS
void AMorphedMonster::Serialize (FArchive &arc)
void AMorphedMonster::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << UnmorphedMe << UnmorphTime << MorphStyle << MorphExitFlash << FlagsSave;
arc("unmorphedme", UnmorphedMe)
("unmorphtime", UnmorphTime)
("morphstyle", MorphStyle)
("morphexitflash", MorphExitFlash)
("flagsave", FlagsSave);
}
void AMorphedMonster::Destroy ()

View file

@ -37,7 +37,7 @@
#include "p_local.h"
#include "p_lnspec.h"
#include "doomstat.h"
#include "farchive.h"
#include "serializer.h"
/*
== InterpolationPoint: node along a camera's path
@ -60,7 +60,8 @@ public:
AInterpolationPoint *ScanForLoop ();
void FormChain ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
TObjPtr<AInterpolationPoint> Next;
};
@ -69,10 +70,10 @@ IMPLEMENT_POINTY_CLASS (AInterpolationPoint)
DECLARE_POINTER (Next)
END_POINTERS
void AInterpolationPoint::Serialize (FArchive &arc)
void AInterpolationPoint::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Next;
arc("next", Next);
}
void AInterpolationPoint::BeginPlay ()
@ -166,7 +167,8 @@ protected:
virtual bool Interpolate ();
virtual void NewNode ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool bActive, bJustStepped;
TObjPtr<AInterpolationPoint> PrevNode, CurrNode;
@ -179,10 +181,15 @@ IMPLEMENT_POINTY_CLASS (APathFollower)
DECLARE_POINTER (CurrNode)
END_POINTERS
void APathFollower::Serialize (FArchive &arc)
void APathFollower::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << bActive << bJustStepped << PrevNode << CurrNode << Time << HoldTime;
arc("active", bActive)
("juststepped", bJustStepped)
("prevnode", PrevNode)
("currnode", CurrNode)
("time", Time)
("holdtime", HoldTime);
}
// Interpolate between p2 and p3 along a Catmull-Rom spline
@ -577,7 +584,8 @@ class AMovingCamera : public APathFollower
public:
void PostBeginPlay ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
protected:
bool Interpolate ();
@ -588,10 +596,10 @@ IMPLEMENT_POINTY_CLASS (AMovingCamera)
DECLARE_POINTER (Activator)
END_POINTERS
void AMovingCamera::Serialize (FArchive &arc)
void AMovingCamera::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Activator;
arc("activator", Activator);
}
void AMovingCamera::PostBeginPlay ()

View file

@ -18,9 +18,9 @@
#include "g_level.h"
#include "g_game.h"
#include "doomstat.h"
#include "farchive.h"
#include "d_player.h"
#include "p_spec.h"
#include "serializer.h"
static FRandom pr_restore ("RestorePos");
@ -89,10 +89,12 @@ IMPLEMENT_CLASS (AAmmo)
//
//===========================================================================
void AAmmo::Serialize (FArchive &arc)
void AAmmo::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << BackpackAmount << BackpackMaxAmount;
auto def = (AAmmo*)GetDefault();
arc("backpackamount", BackpackAmount, def->BackpackAmount)
("backpackmaxamount", BackpackMaxAmount, def->BackpackMaxAmount);
}
//===========================================================================
@ -514,10 +516,21 @@ void AInventory::Tick ()
//
//===========================================================================
void AInventory::Serialize (FArchive &arc)
void AInventory::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Owner << Amount << MaxAmount << RespawnTics << ItemFlags << Icon << PickupSound << SpawnPointClass;
auto def = (AInventory*)GetDefault();
arc("owner", Owner)
("amount", Amount, def->Amount)
("maxamount", MaxAmount, def->MaxAmount)
("interhubamount", InterHubAmount, def->InterHubAmount)
("respawntics", RespawnTics, def->RespawnTics)
("itemflags", ItemFlags, def->ItemFlags)
("icon", Icon, def->Icon)
("pickupsound", PickupSound, def->PickupSound)
("spawnpointclass", SpawnPointClass, def->SpawnPointClass)
("droptime", DropTime, def->DropTime);
}
//===========================================================================
@ -1809,10 +1822,11 @@ bool AHealthPickup::Use (bool pickup)
//
//===========================================================================
void AHealthPickup::Serialize (FArchive &arc)
void AHealthPickup::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << autousemode;
auto def = (AHealthPickup*)GetDefault();
arc("autousemode", autousemode, def->autousemode);
}
// Backpack -----------------------------------------------------------------
@ -1823,10 +1837,11 @@ void AHealthPickup::Serialize (FArchive &arc)
//
//===========================================================================
void ABackpackItem::Serialize (FArchive &arc)
void ABackpackItem::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << bDepleted;
auto def = (ABackpackItem*)GetDefault();
arc("bdepleted", bDepleted, def->bDepleted);
}
//===========================================================================

View file

@ -153,7 +153,8 @@ class AInventory : public AActor
HAS_OBJECT_POINTERS
public:
virtual void Touch (AActor *toucher);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void MarkPrecacheSounds() const;
virtual void BeginPlay ();
@ -185,7 +186,7 @@ public:
int RespawnTics; // Tics from pickup time to respawn time
FTextureID Icon; // Icon to show on status bar or HUD
int DropTime; // Countdown after dropping
const PClass *SpawnPointClass; // For respawning like Heretic's mace
PClassActor *SpawnPointClass; // For respawning like Heretic's mace
DWORD ItemFlags;
PClassActor *PickupFlash; // actor to spawn as pickup flash
@ -254,7 +255,8 @@ class AAmmo : public AInventory
{
DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo)
public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
AInventory *CreateCopy (AActor *other);
bool HandlePickup (AInventory *item);
PClassActor *GetParentAmmo () const;
@ -311,7 +313,8 @@ public:
bool bAltFire; // Set when this weapon's alternate fire is used.
virtual void MarkPrecacheSounds() const;
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual bool ShouldStay ();
virtual void AttachToOwner (AActor *other);
virtual bool HandlePickup (AInventory *item);
@ -395,7 +398,8 @@ class AWeaponGiver : public AWeapon
public:
bool TryPickup(AActor *&toucher);
void Serialize(FArchive &arc);
void Serialize(FSerializer &arc);
double DropAmmoFactor;
};
@ -431,7 +435,8 @@ class AHealthPickup : public AInventory
public:
int autousemode;
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other);
virtual AInventory *CreateTossable ();
virtual bool HandlePickup (AInventory *item);
@ -451,7 +456,8 @@ class ABasicArmor : public AArmor
{
DECLARE_CLASS (ABasicArmor, AArmor)
public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void Tick ();
virtual AInventory *CreateCopy (AActor *other);
virtual bool HandlePickup (AInventory *item);
@ -471,7 +477,8 @@ class ABasicArmorPickup : public AArmor
{
DECLARE_CLASS (ABasicArmorPickup, AArmor)
public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup);
@ -486,7 +493,8 @@ class ABasicArmorBonus : public AArmor
{
DECLARE_CLASS (ABasicArmorBonus, AArmor)
public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup);
@ -505,7 +513,8 @@ class AHexenArmor : public AArmor
{
DECLARE_CLASS (AHexenArmor, AArmor)
public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other);
virtual AInventory *CreateTossable ();
virtual bool HandlePickup (AInventory *item);
@ -533,7 +542,7 @@ class APuzzleItem : public AInventory
{
DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem)
public:
void Serialize (FArchive &arc);
bool ShouldStay ();
bool Use (bool pickup);
bool HandlePickup (AInventory *item);
@ -555,7 +564,8 @@ class ABackpackItem : public AInventory
{
DECLARE_CLASS (ABackpackItem, AInventory)
public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool HandlePickup (AInventory *item);
AInventory *CreateCopy (AActor *other);
AInventory *CreateTossable ();

View file

@ -7,7 +7,6 @@
#include "c_console.h"
#include "doomstat.h"
#include "v_font.h"
#include "farchive.h"
IMPLEMENT_CLASS(PClassPuzzleItem)
@ -20,12 +19,6 @@ void PClassPuzzleItem::DeriveData(PClass *newclass)
IMPLEMENT_CLASS(APuzzleItem)
void APuzzleItem::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << PuzzleItemNumber;
}
bool APuzzleItem::HandlePickup (AInventory *item)
{
// Can't carry more than 1 of each puzzle item in coop netplay

View file

@ -8,7 +8,7 @@
#include "s_sound.h"
#include "a_sharedglobal.h"
#include "statnums.h"
#include "farchive.h"
#include "serializer.h"
#include "d_player.h"
#include "r_utility.h"
@ -64,15 +64,23 @@ DEarthquake::DEarthquake(AActor *center, int intensityX, int intensityY, int int
//
//==========================================================================
void DEarthquake::Serialize (FArchive &arc)
void DEarthquake::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << m_Spot << m_Intensity << m_Countdown
<< m_TremorRadius << m_DamageRadius
<< m_QuakeSFX << m_Flags << m_CountdownStart
<< m_WaveSpeed
<< m_Falloff << m_Highpoint << m_MiniCount
<< m_RollIntensity << m_RollWave;
arc("spot", m_Spot)
("intensity", m_Intensity)
("countdown", m_Countdown)
("tremorradius", m_TremorRadius)
("damageradius", m_DamageRadius)
("quakesfx", m_QuakeSFX)
("quakeflags", m_Flags)
("countdownstart", m_CountdownStart)
("wavespeed", m_WaveSpeed)
("falloff", m_Falloff)
("highpoint", m_Highpoint)
("minicount", m_MiniCount)
("rollintensity", m_RollIntensity)
("rollwave", m_RollWave);
}
//==========================================================================

View file

@ -48,6 +48,8 @@ bool ASectorAction::IsActivatedByUse() const
}
void ASectorAction::Destroy ()
{
if (Sector != nullptr)
{
// Remove ourself from this sector's list of actions
AActor *probe = Sector->SecActTarget;
@ -63,10 +65,12 @@ void ASectorAction::Destroy ()
prev.act = &probe->tracer;
probe = probe->tracer;
}
if (probe != NULL)
if (probe != nullptr)
{
*prev.act = probe->tracer;
}
Sector = nullptr;
}
Super::Destroy ();
}

View file

@ -24,7 +24,7 @@ public:
DBaseDecal (const AActor *actor);
DBaseDecal (const DBaseDecal *basis);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Destroy ();
FTextureID StickToWall(side_t *wall, double x, double y, F3DFloor * ffloor);
double GetRealZ (const side_t *wall) const;
@ -33,9 +33,7 @@ public:
void Spread (const FDecalTemplate *tpl, side_t *wall, double x, double y, double z, F3DFloor * ffloor);
void GetXY (side_t *side, double &x, double &y) const;
static void SerializeChain (FArchive &arc, DBaseDecal **firstptr);
DBaseDecal *WallNext, **WallPrev;
DBaseDecal *WallNext, *WallPrev;
double LeftDistance;
double Z;
@ -46,7 +44,8 @@ public:
FTextureID PicNum;
DWORD RenderFlags;
FRenderStyle RenderStyle;
sector_t * Sector; // required for 3D floors
side_t *Side;
sector_t *Sector;
protected:
virtual DBaseDecal *CloneSelf(const FDecalTemplate *tpl, double x, double y, double z, side_t *wall, F3DFloor * ffloor) const;
@ -70,9 +69,6 @@ public:
void BeginPlay ();
void Destroy ();
void Serialize (FArchive &arc);
static void SerializeTime (FArchive &arc);
protected:
DBaseDecal *CloneSelf(const FDecalTemplate *tpl, double x, double y, double z, side_t *wall, F3DFloor * ffloor) const;
static void CheckMax ();
@ -122,7 +118,7 @@ public:
float r2, float g2, float b2, float a2,
float time, AActor *who);
void Destroy ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
AActor *WhoFor() { return ForWho; }
void Cancel ();
@ -165,7 +161,7 @@ public:
int damrad, int tremrad, FSoundID quakesfx, int flags,
double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
TObjPtr<AActor> m_Spot;
double m_TremorRadius, m_DamageRadius;
@ -194,7 +190,8 @@ class AMorphProjectile : public AActor
DECLARE_CLASS (AMorphProjectile, AActor)
public:
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
FNameNoInit PlayerClass, MonsterClass, MorphFlash, UnMorphFlash;
int Duration, MorphStyle;
@ -206,7 +203,8 @@ class AMorphedMonster : public AActor
HAS_OBJECT_POINTERS
public:
void Tick ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Die (AActor *source, AActor *inflictor, int dmgflags);
void Destroy ();

View file

@ -36,8 +36,8 @@
#include "a_sharedglobal.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "farchive.h"
#include "r_sky.h"
#include "r_state.h"
#include "portal.h"
// arg0 = Visibility*4 for this skybox
@ -169,8 +169,11 @@ void ASectorSilencer::BeginPlay ()
}
void ASectorSilencer::Destroy ()
{
if (Sector != nullptr)
{
Sector->Flags &= ~SECF_SILENT;
}
Super::Destroy ();
}

View file

@ -59,7 +59,7 @@ void ASoundEnvironment::PostBeginPlay ()
void ASoundEnvironment::Activate (AActor *activator)
{
zones[Sector->ZoneNumber].Environment = S_FindEnvironment ((args[0]<<8) | (args[1]));
Zones[Sector->ZoneNumber].Environment = S_FindEnvironment ((args[0]<<8) | (args[1]));
}
// Deactivate just exists so that you can flag the thing as dormant in an editor

View file

@ -65,7 +65,7 @@
#include "s_sound.h"
#include "m_random.h"
#include "s_sndseq.h"
#include "farchive.h"
#include "serializer.h"
// SoundSequenceSlot --------------------------------------------------------
@ -74,7 +74,8 @@ class ASoundSequenceSlot : public AActor
DECLARE_CLASS (ASoundSequenceSlot, AActor)
HAS_OBJECT_POINTERS
public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
TObjPtr<DSeqNode> Sequence;
};
@ -89,10 +90,10 @@ END_POINTERS
//
//==========================================================================
void ASoundSequenceSlot::Serialize (FArchive &arc)
void ASoundSequenceSlot::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << Sequence;
arc("sequence", Sequence);
}
// SoundSequence ------------------------------------------------------------

View file

@ -39,7 +39,7 @@
#include "i_system.h"
#include "thingdef/thingdef.h"
#include "doomstat.h"
#include "farchive.h"
#include "serializer.h"
#include "a_pickups.h"
static FRandom pr_spot ("SpecialSpot");
@ -58,7 +58,7 @@ TObjPtr<DSpotState> DSpotState::SpotState;
struct FSpotList
{
const PClass *Type;
PClassActor *Type;
TArray<ASpecialSpot*> Spots;
unsigned Index;
int SkipCount;
@ -68,7 +68,7 @@ struct FSpotList
{
}
FSpotList(const PClass *type)
FSpotList(PClassActor *type)
{
Type = type;
Index = 0;
@ -82,17 +82,6 @@ struct FSpotList
//
//----------------------------------------------------------------------------
void Serialize(FArchive &arc)
{
arc << Type << Spots << Index << SkipCount << numcalls;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
bool Add(ASpecialSpot *newspot)
{
for(unsigned i = 0; i < Spots.Size(); i++)
@ -194,6 +183,26 @@ struct FSpotList
//
//----------------------------------------------------------------------------
FSerializer &Serialize(FSerializer &arc, const char *key, FSpotList &list, FSpotList *def)
{
if (arc.BeginObject(key))
{
arc("type", list.Type)
("spots", list.Spots)
("index", list.Index)
("skipcount", list.SkipCount)
("numcalls", list.numcalls)
.EndObject();
}
return arc;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
DSpotState::DSpotState ()
: DThinker (STAT_INFO)
{
@ -215,10 +224,6 @@ DSpotState::DSpotState ()
void DSpotState::Destroy ()
{
for(unsigned i = 0; i < SpotLists.Size(); i++)
{
delete SpotLists[i];
}
SpotLists.Clear();
SpotLists.ShrinkToFit();
@ -254,13 +259,13 @@ DSpotState *DSpotState::GetSpotState(bool create)
//
//----------------------------------------------------------------------------
FSpotList *DSpotState::FindSpotList(const PClass *type)
FSpotList *DSpotState::FindSpotList(PClassActor *type)
{
for(unsigned i = 0; i < SpotLists.Size(); i++)
{
if (SpotLists[i]->Type == type) return SpotLists[i];
if (SpotLists[i].Type == type) return &SpotLists[i];
}
return SpotLists[SpotLists.Push(new FSpotList(type))];
return &SpotLists[SpotLists.Push(FSpotList(type))];
}
//----------------------------------------------------------------------------
@ -295,27 +300,10 @@ bool DSpotState::RemoveSpot(ASpecialSpot *spot)
//
//----------------------------------------------------------------------------
void DSpotState::Serialize(FArchive &arc)
void DSpotState::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
if (arc.IsStoring())
{
arc.WriteCount(SpotLists.Size());
for(unsigned i = 0; i < SpotLists.Size(); i++)
{
SpotLists[i]->Serialize(arc);
}
}
else
{
unsigned c = arc.ReadCount();
SpotLists.Resize(c);
for(unsigned i = 0; i < SpotLists.Size(); i++)
{
SpotLists[i] = new FSpotList;
SpotLists[i]->Serialize(arc);
}
}
arc("spots", SpotLists);
}
//----------------------------------------------------------------------------
@ -324,7 +312,7 @@ void DSpotState::Serialize(FArchive &arc)
//
//----------------------------------------------------------------------------
ASpecialSpot *DSpotState::GetNextInList(const PClass *type, int skipcounter)
ASpecialSpot *DSpotState::GetNextInList(PClassActor *type, int skipcounter)
{
FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetNextInList(skipcounter);
@ -337,7 +325,7 @@ ASpecialSpot *DSpotState::GetNextInList(const PClass *type, int skipcounter)
//
//----------------------------------------------------------------------------
ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(const PClass *type, double x, double y, double mindist, double maxdist)
ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist)
{
FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist);
@ -350,7 +338,7 @@ ASpecialSpot *DSpotState::GetSpotWithMinMaxDistance(const PClass *type, double x
//
//----------------------------------------------------------------------------
ASpecialSpot *DSpotState::GetRandomSpot(const PClass *type, bool onlyonce)
ASpecialSpot *DSpotState::GetRandomSpot(PClassActor *type, bool onlyonce)
{
FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetRandomSpot(onlyonce);

View file

@ -22,7 +22,7 @@ class DSpotState : public DThinker
{
DECLARE_CLASS(DSpotState, DThinker)
static TObjPtr<DSpotState> SpotState;
TArray<FSpotList *> SpotLists;
TArray<FSpotList> SpotLists;
public:
@ -31,13 +31,13 @@ public:
void Destroy ();
void Tick ();
static DSpotState *GetSpotState(bool create = true);
FSpotList *FindSpotList(const PClass *type);
FSpotList *FindSpotList(PClassActor *type);
bool AddSpot(ASpecialSpot *spot);
bool RemoveSpot(ASpecialSpot *spot);
void Serialize(FArchive &arc);
ASpecialSpot *GetNextInList(const PClass *type, int skipcounter);
ASpecialSpot *GetSpotWithMinMaxDistance(const PClass *type, double x, double y, double mindist, double maxdist);
ASpecialSpot *GetRandomSpot(const PClass *type, bool onlyonce = false);
void Serialize(FSerializer &arc);
ASpecialSpot *GetNextInList(PClassActor *type, int skipcounter);
ASpecialSpot *GetSpotWithMinMaxDistance(PClassActor *type, double x, double y, double mindist, double maxdist);
ASpecialSpot *GetRandomSpot(PClassActor *type, bool onlyonce = false);
};

View file

@ -1,7 +1,7 @@
#include "a_pickups.h"
#include "a_weaponpiece.h"
#include "doomstat.h"
#include "farchive.h"
#include "serializer.h"
IMPLEMENT_CLASS(PClassWeaponPiece)
IMPLEMENT_CLASS (AWeaponHolder)
@ -17,10 +17,11 @@ void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass)
}
void AWeaponHolder::Serialize (FArchive &arc)
void AWeaponHolder::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << PieceMask << PieceWeapon;
arc("piecemask", PieceMask)
("pieceweapon", PieceWeapon);
}
@ -29,10 +30,13 @@ IMPLEMENT_POINTY_CLASS (AWeaponPiece)
END_POINTERS
void AWeaponPiece::Serialize (FArchive &arc)
void AWeaponPiece::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << WeaponClass << FullWeapon << PieceValue;
auto def = (AWeaponPiece*)GetDefault();
arc("weaponclass", WeaponClass, def->WeaponClass)
("fullweapon", FullWeapon)
("piecevalue", PieceValue, def->PieceValue);
}
//==========================================================================

View file

@ -15,7 +15,8 @@ class AWeaponPiece : public AInventory
protected:
bool PrivateShouldStay ();
public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool TryPickup (AActor *&toucher);
bool TryPickupRestricted (AActor *&toucher);
bool ShouldStay ();
@ -23,7 +24,7 @@ public:
virtual void PlayPickupSound (AActor *toucher);
int PieceValue;
PClassWeapon *WeaponClass;
PClassActor *WeaponClass;
TObjPtr<AWeapon> FullWeapon;
};
@ -35,7 +36,8 @@ class AWeaponHolder : public AInventory
public:
int PieceMask;
const PClass * PieceWeapon;
PClassActor * PieceWeapon;
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
};

View file

@ -17,7 +17,7 @@
#include "doomstat.h"
#include "g_level.h"
#include "d_net.h"
#include "farchive.h"
#include "serializer.h"
#define BONUSADD 6
@ -73,28 +73,45 @@ void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass)
//
//===========================================================================
void AWeapon::Serialize (FArchive &arc)
void AWeapon::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << WeaponFlags
<< AmmoType1 << AmmoType2
<< AmmoGive1 << AmmoGive2
<< MinAmmo1 << MinAmmo2
<< AmmoUse1 << AmmoUse2
<< Kickback
<< YAdjust
<< UpSound << ReadySound
<< SisterWeaponType
<< ProjectileType << AltProjectileType
<< SelectionOrder
<< MoveCombatDist
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
<< bAltFire
<< ReloadCounter
<< BobStyle << BobSpeed << BobRangeX << BobRangeY
<< FOVScale
<< Crosshair
<< MinSelAmmo1 << MinSelAmmo2;
auto def = (AWeapon*)GetDefault();
arc("weaponflags", WeaponFlags, def->WeaponFlags)
("ammogive1", AmmoGive1, def->AmmoGive1)
("ammogive2", AmmoGive2, def->AmmoGive2)
("minammo1", MinAmmo1, def->MinAmmo1)
("minammo2", MinAmmo2, def->MinAmmo2)
("ammouse1", AmmoUse1, def->AmmoUse1)
("ammouse2", AmmoUse2, def->AmmoUse2)
("kickback", Kickback, Kickback)
("yadjust", YAdjust, def->YAdjust)
("upsound", UpSound, def->UpSound)
("readysound", ReadySound, def->ReadySound)
("selectionorder", SelectionOrder, def->SelectionOrder)
("ammo1", Ammo1)
("ammo2", Ammo2)
("sisterweapon", SisterWeapon)
("givenasmorphweapon", GivenAsMorphWeapon, def->GivenAsMorphWeapon)
("altfire", bAltFire, def->bAltFire)
("reloadcounter", ReloadCounter, def->ReloadCounter)
("bobstyle", BobStyle, def->BobStyle)
("bobspeed", BobSpeed, def->BobSpeed)
("bobrangex", BobRangeX, def->BobRangeX)
("bobrangey", BobRangeY, def->BobRangeY)
("fovscale", FOVScale, def->FOVScale)
("crosshair", Crosshair, def->Crosshair)
("minselammo1", MinSelAmmo1, def->MinSelAmmo1)
("minselammo2", MinSelAmmo2, def->MinSelAmmo2);
/* these can never change
("ammotype1", AmmoType1, def->AmmoType1)
("ammotype2", AmmoType2, def->AmmoType2)
("sisterweapontype", SisterWeaponType, def->SisterWeaponType)
("projectiletype", ProjectileType, def->ProjectileType)
("altprojectiletype", AltProjectileType, def->AltProjectileType)
("movecombatdist", MoveCombatDist, def->MoveCombatDist)
*/
}
//===========================================================================
@ -741,10 +758,11 @@ FState *AWeapon::GetStateForButtonName (FName button)
IMPLEMENT_CLASS(AWeaponGiver)
void AWeaponGiver::Serialize(FArchive &arc)
void AWeaponGiver::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << DropAmmoFactor;
auto def = (AWeaponGiver *)GetDefault();
arc("dropammofactor", DropAmmoFactor, def->DropAmmoFactor);
}
bool AWeaponGiver::TryPickup(AActor *&toucher)

View file

@ -39,7 +39,7 @@
#include "v_video.h"
#include "cmdlib.h"
#include "doomstat.h"
#include "farchive.h"
#include "serializer.h"
EXTERN_CVAR(Int, con_scaletext)
int active_con_scaletext();
@ -56,14 +56,6 @@ IMPLEMENT_CLASS (DHUDMessageTypeOnFadeOut)
* Basic HUD message. Appears and disappears without any special effects *
*************************************************************************/
inline FArchive &operator<< (FArchive &arc, EColorRange &i)
{
BYTE val = (BYTE)i;
arc << val;
i = (EColorRange)val;
return arc;
}
//============================================================================
//
// DHUDMessage Constructor
@ -180,20 +172,34 @@ DHUDMessage::~DHUDMessage ()
//
//============================================================================
void DHUDMessage::Serialize(FArchive &arc)
void DHUDMessage::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << Left << Top << CenterX << HoldTics
<< Tics << State << TextColor
<< SBarID << SourceText << Font << Next
<< HUDWidth << HUDHeight
<< NoWrap
<< ClipX << ClipY << ClipWidth << ClipHeight
<< WrapWidth
<< HandleAspect
<< VisibilityFlags
<< Style << Alpha;
if (arc.IsLoading())
arc("left", Left)
("top", Top)
("centerx", CenterX)
("holdtics", HoldTics)
("tics", Tics)
("state", State)
.Enum("textcolor", TextColor)
("sbarid", SBarID)
("sourcetext", SourceText)
("font", Font)
("next", Next)
("hudwidth", HUDWidth)
("hudheight", HUDHeight)
("nowrap", NoWrap)
("clipx", ClipX)
("clipy", ClipY)
("clipwidth", ClipWidth)
("clipheight", ClipHeight)
("wrapwidth", WrapWidth)
("handleaspect", HandleAspect)
("visibilityflags", VisibilityFlags)
("style", Style)
("alpha", Alpha);
if (arc.isReading())
{
Lines = NULL;
ResetText(SourceText);
@ -504,10 +510,10 @@ DHUDMessageFadeOut::DHUDMessageFadeOut (FFont *font, const char *text, float x,
//
//============================================================================
void DHUDMessageFadeOut::Serialize (FArchive &arc)
void DHUDMessageFadeOut::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << FadeOutTics;
arc("fadeouttics", FadeOutTics);
}
//============================================================================
@ -609,10 +615,10 @@ DHUDMessageFadeInOut::DHUDMessageFadeInOut (FFont *font, const char *text, float
//
//============================================================================
void DHUDMessageFadeInOut::Serialize (FArchive &arc)
void DHUDMessageFadeInOut::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << FadeInTics;
arc("fadeintics", FadeInTics);
}
//============================================================================
@ -718,10 +724,13 @@ DHUDMessageTypeOnFadeOut::DHUDMessageTypeOnFadeOut (FFont *font, const char *tex
//
//============================================================================
void DHUDMessageTypeOnFadeOut::Serialize (FArchive &arc)
void DHUDMessageTypeOnFadeOut::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << TypeOnTime << CurrLine << LineVisible << LineLen;
arc("typeontime", TypeOnTime)
("currline", CurrLine)
("linevisible", LineVisible)
("linelen", LineLen);
}
//============================================================================

View file

@ -71,7 +71,7 @@ public:
EColorRange textColor, float holdTime);
virtual ~DHUDMessage ();
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
void Draw (int bottom, int visibility);
virtual void ResetText (const char *text);
@ -157,7 +157,7 @@ public:
DHUDMessageFadeOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime, float fadeOutTime);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick ();
@ -176,7 +176,7 @@ public:
DHUDMessageFadeInOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime, float fadeInTime, float fadeOutTime);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick ();
@ -195,7 +195,7 @@ public:
DHUDMessageTypeOnFadeOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float typeTime, float holdTime, float fadeOutTime);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick ();
virtual void ScreenSizeChanged ();
@ -355,7 +355,8 @@ public:
static void AddBlend (float r, float g, float b, float a, float v_blend[4]);
virtual void Serialize (FArchive &arc);
// do not make this a DObject Serialize function because it's not used like one!
void SerializeMessages(FSerializer &arc);
virtual void Tick ();
virtual void Draw (EHudState state);

View file

@ -51,8 +51,9 @@
#include "colormatcher.h"
#include "v_palette.h"
#include "d_player.h"
#include "farchive.h"
#include "serializer.h"
#include "gstrings.h"
#include "r_utility.h"
#include "../version.h"
@ -1654,12 +1655,9 @@ void DBaseStatusBar::ReceivedWeapon (AWeapon *weapon)
{
}
void DBaseStatusBar::Serialize (FArchive &arc)
void DBaseStatusBar::SerializeMessages(FSerializer &arc)
{
for (size_t i = 0; i < countof(Messages); ++i)
{
arc << Messages[i];
}
arc.Array("hudmessages", Messages, 3, true);
}
void DBaseStatusBar::ScreenSizeChanged ()

View file

@ -55,7 +55,8 @@ class ASigil : public AWeapon
public:
bool HandlePickup (AInventory *item);
AInventory *CreateCopy (AActor *other);
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool SpecialDropAction (AActor *dropper);
static int GiveSigilPiece (AActor *daPlayer);
void BeginPlay();

View file

@ -18,7 +18,7 @@
#include "templates.h"
#include "d_event.h"
#include "v_font.h"
#include "farchive.h"
#include "serializer.h"
#include "p_spec.h"
#include "portal.h"

View file

@ -753,10 +753,11 @@ void ASigil::BeginPlay()
//
//============================================================================
void ASigil::Serialize (FArchive &arc)
void ASigil::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc << NumPieces << DownPieces;
arc("numpieces", NumPieces)
("downpieces", DownPieces);
}
//============================================================================

View file

@ -375,6 +375,9 @@ void PClassActor::InitializeNativeDefaults()
else
{
memset (Defaults, 0, Size);
// Non-DECORATE properties that must be set.
((AActor*)Defaults)->DamageMultiply = 1.; // fixme: Make this a DECORATE property.
((AActor*)Defaults)->ConversationRoot = -1;
}
}

View file

@ -52,7 +52,6 @@
struct Baggage;
class FScanner;
struct FActorInfo;
class FArchive;
class FIntCVar;
enum EStateType
@ -168,10 +167,6 @@ struct FStateLabels
void Destroy(); // intentionally not a destructor!
};
FArchive &operator<< (FArchive &arc, FState *&state);
#include "gametype.h"
struct DmgFactors : public TMap<FName, double>

View file

@ -45,7 +45,7 @@
#include "d_net.h"
#include "d_dehacked.h"
#include "gi.h"
#include "farchive.h"
#include "serializer.h"
#include "r_utility.h"
#include "a_morph.h"
@ -1026,10 +1026,10 @@ public:
}
// You'll probably never be able to catch this in a save game, but
// just in case, add a proper serializer.
void Serialize(FArchive &arc)
void Serialize(FSerializer &arc)
{
Super::Serialize(arc);
arc << Pawn;
arc("pawn", Pawn);
}
};

View file

@ -449,10 +449,15 @@ struct pcx_t
};
inline void putc(unsigned char chr, FileWriter *file)
{
file->Write(&chr, 1);
}
//
// WritePCXfile
//
void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette,
void WritePCXfile (FileWriter *file, const BYTE *buffer, const PalEntry *palette,
ESSType color_type, int width, int height, int pitch)
{
BYTE temprow[MAXWIDTH * 3];
@ -480,7 +485,7 @@ void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette,
pcx.palette_type = 1; // not a grey scale
memset (pcx.filler, 0, sizeof(pcx.filler));
fwrite (&pcx, 128, 1, file);
file->Write(&pcx, 128);
bytes_per_row_minus_one = ((color_type == SS_PAL) ? width : width * 3) - 1;
@ -593,7 +598,7 @@ void WritePCXfile (FILE *file, const BYTE *buffer, const PalEntry *palette,
//
// WritePNGfile
//
void WritePNGfile (FILE *file, const BYTE *buffer, const PalEntry *palette,
void WritePNGfile (FileWriter *file, const BYTE *buffer, const PalEntry *palette,
ESSType color_type, int width, int height, int pitch)
{
char software[100];
@ -655,7 +660,7 @@ static bool FindFreeName (FString &fullname, const char *extension)
void M_ScreenShot (const char *filename)
{
FILE *file;
FileWriter *file;
FString autoname;
bool writepcx = (stricmp (screenshot_type, "pcx") == 0); // PNG is the default
@ -709,7 +714,7 @@ void M_ScreenShot (const char *filename)
{
screen->GetFlashedPalette(palette);
}
file = fopen (autoname, "wb");
file = FileWriter::Open(autoname);
if (file == NULL)
{
Printf ("Could not open %s\n", autoname.GetChars());
@ -726,7 +731,7 @@ void M_ScreenShot (const char *filename)
WritePNGfile(file, buffer, palette, color_type,
screen->GetWidth(), screen->GetHeight(), pitch);
}
fclose(file);
delete file;
screen->ReleaseScreenshotBuffer();
if (!screenshot_quiet)

View file

@ -80,7 +80,7 @@ PNGHandle::PNGHandle (FILE *file) : File(0), bDeleteFilePtr(true), ChunkPt(0)
File = new FileReader(file);
}
PNGHandle::PNGHandle (FileReader *file) : File(file), bDeleteFilePtr(false), ChunkPt(0) {}
PNGHandle::PNGHandle (FileReader *file, bool takereader) : File(file), bDeleteFilePtr(takereader), ChunkPt(0) {}
PNGHandle::~PNGHandle ()
{
for (unsigned int i = 0; i < TextChunks.Size(); ++i)
@ -101,7 +101,7 @@ PNGHandle::~PNGHandle ()
static inline void MakeChunk (void *where, DWORD type, size_t len);
static inline void StuffPalette (const PalEntry *from, BYTE *to);
static bool WriteIDAT (FILE *file, const BYTE *data, int len);
static bool WriteIDAT (FileWriter *file, const BYTE *data, int len);
static void UnfilterRow (int width, BYTE *dest, BYTE *stream, BYTE *prev, int bpp);
static void UnpackPixels (int width, int bytesPerRow, int bitdepth, const BYTE *rowin, BYTE *rowout, bool grayscale);
@ -131,7 +131,7 @@ CVAR(Float, png_gamma, 0.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
//
//==========================================================================
bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette,
bool M_CreatePNG (FileWriter *file, const BYTE *buffer, const PalEntry *palette,
ESSType color_type, int width, int height, int pitch)
{
BYTE work[8 + // signature
@ -171,7 +171,7 @@ bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette,
work_len = sizeof(work) - (12+256*3);
}
if (fwrite (work, 1, work_len, file) != work_len)
if (file->Write (work, work_len) != work_len)
return false;
return M_SaveBitmap (buffer, color_type, width, height, pitch, file);
@ -185,7 +185,7 @@ bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *palette,
//
//==========================================================================
bool M_CreateDummyPNG (FILE *file)
bool M_CreateDummyPNG (FileWriter *file)
{
static const BYTE dummyPNG[] =
{
@ -195,7 +195,7 @@ bool M_CreateDummyPNG (FILE *file)
0,0,0,10,'I','D','A','T',
104,222,99,96,0,0,0,2,0,1,0x9f,0x65,0x0e,0x18
};
return fwrite (dummyPNG, 1, sizeof(dummyPNG), file) == sizeof(dummyPNG);
return file->Write (dummyPNG, sizeof(dummyPNG)) == sizeof(dummyPNG);
}
@ -207,10 +207,10 @@ bool M_CreateDummyPNG (FILE *file)
//
//==========================================================================
bool M_FinishPNG (FILE *file)
bool M_FinishPNG (FileWriter *file)
{
static const BYTE iend[12] = { 0,0,0,0,73,69,78,68,174,66,96,130 };
return fwrite (iend, 1, 12, file) == 12;
return file->Write (iend, 12) == 12;
}
//==========================================================================
@ -221,13 +221,13 @@ bool M_FinishPNG (FILE *file)
//
//==========================================================================
bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD len)
bool M_AppendPNGChunk (FileWriter *file, DWORD chunkID, const BYTE *chunkData, DWORD len)
{
DWORD head[2] = { BigLong((unsigned int)len), chunkID };
DWORD crc;
if (fwrite (head, 1, 8, file) == 8 &&
(len == 0 || fwrite (chunkData, 1, len, file) == len))
if (file->Write (head, 8) == 8 &&
(len == 0 || file->Write (chunkData, len) == len))
{
crc = CalcCRC32 ((BYTE *)&head[1], 4);
if (len != 0)
@ -235,7 +235,7 @@ bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD l
crc = AddCRC32 (crc, chunkData, len);
}
crc = BigLong((unsigned int)crc);
return fwrite (&crc, 1, 4, file) == 4;
return file->Write (&crc, 4) == 4;
}
return false;
}
@ -248,7 +248,7 @@ bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD l
//
//==========================================================================
bool M_AppendPNGText (FILE *file, const char *keyword, const char *text)
bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text)
{
struct { DWORD len, id; char key[80]; } head;
int len = (int)strlen (text);
@ -261,8 +261,8 @@ bool M_AppendPNGText (FILE *file, const char *keyword, const char *text)
strncpy (head.key, keyword, keylen);
head.key[keylen] = 0;
if ((int)fwrite (&head, 1, keylen + 9, file) == keylen + 9 &&
(int)fwrite (text, 1, len, file) == len)
if ((int)file->Write (&head, keylen + 9) == keylen + 9 &&
(int)file->Write (text, len) == len)
{
crc = CalcCRC32 ((BYTE *)&head+4, keylen + 5);
if (len != 0)
@ -270,7 +270,7 @@ bool M_AppendPNGText (FILE *file, const char *keyword, const char *text)
crc = AddCRC32 (crc, (BYTE *)text, len);
}
crc = BigLong((unsigned int)crc);
return fwrite (&crc, 1, 4, file) == 4;
return file->Write (&crc, 4) == 4;
}
return false;
}
@ -374,15 +374,14 @@ bool M_GetPNGText (PNGHandle *png, const char *keyword, char *buffer, size_t buf
//
//==========================================================================
PNGHandle *M_VerifyPNG (FILE *file)
PNGHandle *M_VerifyPNG (FileReader *filer, bool takereader)
{
PNGHandle::Chunk chunk;
FileReader *filer;
PNGHandle *png;
DWORD data[2];
bool sawIDAT = false;
if (fread (&data, 1, 8, file) != 8)
if (filer->Read(&data, 8) != 8)
{
return NULL;
}
@ -390,7 +389,7 @@ PNGHandle *M_VerifyPNG (FILE *file)
{ // Does not have PNG signature
return NULL;
}
if (fread (&data, 1, 8, file) != 8)
if (filer->Read (&data, 8) != 8)
{
return NULL;
}
@ -400,8 +399,7 @@ PNGHandle *M_VerifyPNG (FILE *file)
}
// It looks like a PNG so far, so start creating a PNGHandle for it
png = new PNGHandle (file);
filer = png->File;
png = new PNGHandle (filer, takereader);
chunk.ID = data[1];
chunk.Offset = 16;
chunk.Size = BigLong((unsigned int)data[0]);
@ -430,7 +428,7 @@ PNGHandle *M_VerifyPNG (FILE *file)
sawIDAT = true;
}
chunk.ID = data[1];
chunk.Offset = ftell (file);
chunk.Offset = filer->Tell();
chunk.Size = BigLong((unsigned int)data[0]);
png->Chunks.Push (chunk);
@ -454,6 +452,12 @@ PNGHandle *M_VerifyPNG (FILE *file)
return NULL;
}
PNGHandle *M_VerifyPNG(FILE *file)
{
FileReader *fr = new FileReader(file);
return M_VerifyPNG(fr, true);
}
//==========================================================================
//
// M_FreePNG
@ -900,7 +904,7 @@ static int SelectFilter(Byte row[5][1 + MAXWIDTH*3], Byte prior[MAXWIDTH*3], int
//
//==========================================================================
bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FILE *file)
bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FileWriter *file)
{
#if USE_FILTER_HEURISTIC
Byte prior[MAXWIDTH*3];
@ -1040,7 +1044,7 @@ bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, i
//
//==========================================================================
static bool WriteIDAT (FILE *file, const BYTE *data, int len)
static bool WriteIDAT (FileWriter *file, const BYTE *data, int len)
{
DWORD foo[2], crc;
@ -1049,9 +1053,9 @@ static bool WriteIDAT (FILE *file, const BYTE *data, int len)
crc = CalcCRC32 ((BYTE *)&foo[1], 4);
crc = BigLong ((unsigned int)AddCRC32 (crc, data, len));
if (fwrite (foo, 1, 8, file) != 8 ||
fwrite (data, 1, len, file) != (size_t)len ||
fwrite (&crc, 1, 4, file) != 4)
if (file->Write (foo, 8) != 8 ||
file->Write (data, len) != (size_t)len ||
file->Write (&crc, 4) != 4)
{
return false;
}

View file

@ -36,6 +36,7 @@
#include <stdio.h>
#include "doomtype.h"
#include "v_video.h"
#include "files.h"
// PNG Writing --------------------------------------------------------------
@ -43,22 +44,22 @@
// The passed file should be a newly created file.
// This function writes the PNG signature and the IHDR, gAMA, PLTE, and IDAT
// chunks.
bool M_CreatePNG (FILE *file, const BYTE *buffer, const PalEntry *pal,
bool M_CreatePNG (FileWriter *file, const BYTE *buffer, const PalEntry *pal,
ESSType color_type, int width, int height, int pitch);
// Creates a grayscale 1x1 PNG file. Used for savegames without savepics.
bool M_CreateDummyPNG (FILE *file);
bool M_CreateDummyPNG (FileWriter *file);
// Appends any chunk to a PNG file started with M_CreatePNG.
bool M_AppendPNGChunk (FILE *file, DWORD chunkID, const BYTE *chunkData, DWORD len);
bool M_AppendPNGChunk (FileWriter *file, DWORD chunkID, const BYTE *chunkData, DWORD len);
// Adds a tEXt chunk to a PNG file started with M_CreatePNG.
bool M_AppendPNGText (FILE *file, const char *keyword, const char *text);
bool M_AppendPNGText (FileWriter *file, const char *keyword, const char *text);
// Appends the IEND chunk to a PNG file.
bool M_FinishPNG (FILE *file);
bool M_FinishPNG (FileWriter *file);
bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FILE *file);
bool M_SaveBitmap(const BYTE *from, ESSType color_type, int width, int height, int pitch, FileWriter *file);
// PNG Reading --------------------------------------------------------------
@ -79,7 +80,7 @@ struct PNGHandle
unsigned int ChunkPt;
PNGHandle(FILE *file);
PNGHandle(FileReader *file);
PNGHandle(FileReader *file, bool takereader = false);
~PNGHandle();
};
@ -87,7 +88,7 @@ struct PNGHandle
// the signature, but also checking for the IEND chunk. CRC checking of
// each chunk is not done. If it is valid, you get a PNGHandle to pass to
// the following functions.
PNGHandle *M_VerifyPNG (FileReader *file);
PNGHandle *M_VerifyPNG (FileReader *file, bool takereader = false);
PNGHandle *M_VerifyPNG (FILE *file);
// Finds a chunk in a PNG file. The file pointer will be positioned at the

View file

@ -61,7 +61,7 @@
#include "doomstat.h"
#include "m_random.h"
#include "farchive.h"
#include "serializer.h"
#include "b_bot.h"
#include "m_png.h"
#include "m_crc32.h"
@ -291,25 +291,30 @@ DWORD FRandom::StaticSumSeeds ()
//
//==========================================================================
void FRandom::StaticWriteRNGState (FILE *file)
void FRandom::StaticWriteRNGState (FSerializer &arc)
{
FRandom *rng;
FPNGChunkArchive arc (file, RAND_ID);
arc << rngseed;
arc("rngseed", rngseed);
if (arc.BeginArray("rngs"))
{
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
{
// Only write those RNGs that have names
if (rng->NameCRC != 0)
{
arc << rng->NameCRC << rng->idx;
for (int i = 0; i < SFMT::N32; ++i)
if (arc.BeginObject(nullptr))
{
arc << rng->sfmt.u[i];
arc("crc", rng->NameCRC)
("index", rng->idx)
.Array("u", rng->sfmt.u, SFMT::N32)
.EndObject();
}
}
}
arc.EndArray();
}
}
//==========================================================================
@ -321,51 +326,35 @@ void FRandom::StaticWriteRNGState (FILE *file)
//
//==========================================================================
void FRandom::StaticReadRNGState (PNGHandle *png)
void FRandom::StaticReadRNGState(FSerializer &arc)
{
FRandom *rng;
size_t len = M_FindPNGChunk (png, RAND_ID);
if (len != 0)
arc("rngseed", rngseed);
if (arc.BeginArray("rngs"))
{
const size_t sizeof_rng = sizeof(rng->NameCRC) + sizeof(rng->idx) + sizeof(rng->sfmt.u);
const int rngcount = (int)((len-4) / sizeof_rng);
int i;
DWORD crc;
int count = arc.ArraySize();
FPNGChunkArchive arc (png->File->GetFile(), RAND_ID, len);
arc << rngseed;
FRandom::StaticClearRandom ();
for (i = rngcount; i; --i)
for (int i = 0; i < count; i++)
{
arc << crc;
if (arc.BeginObject(nullptr))
{
uint32_t crc;
arc("crc", crc);
for (rng = FRandom::RNGList; rng != NULL; rng = rng->Next)
{
if (rng->NameCRC == crc)
{
arc << rng->idx;
for (int i = 0; i < SFMT::N32; ++i)
{
arc << rng->sfmt.u[i];
}
arc("index", rng->idx)
.Array("u", rng->sfmt.u, SFMT::N32);
break;
}
}
if (rng == NULL)
{ // The RNG was removed. Skip it.
int idx;
DWORD sfmt;
arc << idx;
for (int i = 0; i < SFMT::N32; ++i)
{
arc << sfmt;
arc.EndObject();
}
}
}
png->File->ResetFilePtr();
arc.EndArray();
}
}

View file

@ -39,7 +39,7 @@
#include "basictypes.h"
#include "sfmt/SFMT.h"
struct PNGHandle;
class FSerializer;
class FRandom
{
@ -174,8 +174,8 @@ public:
// Static interface
static void StaticClearRandom ();
static DWORD StaticSumSeeds ();
static void StaticReadRNGState (PNGHandle *png);
static void StaticWriteRNGState (FILE *file);
static void StaticReadRNGState (FSerializer &arc);
static void StaticWriteRNGState (FSerializer &file);
static FRandom *StaticFindRNG(const char *name);
#ifndef NDEBUG

View file

@ -46,6 +46,8 @@
#include "doomstat.h"
#include "gi.h"
#include "d_gui.h"
#include "serializer.h"
#include "resourcefiles/resourcefile.h"
@ -86,6 +88,10 @@ protected:
int commentRight;
int commentBottom;
// this needs to be kept in memory so that the texture can access it when it needs to.
FileReader *currentSavePic;
TArray<char> SavePicData;
static int InsertSaveNode (FSaveGameNode *node);
static void ReadSaveStrings ();
@ -213,7 +219,7 @@ void DLoadSaveMenu::ReadSaveStrings ()
LastSaved = LastAccessed = -1;
quickSaveSlot = NULL;
filter = G_BuildSaveName ("*.zds", -1);
filter = G_BuildSaveName ("*." SAVEGAME_EXT, -1);
filefirst = I_FindFirst (filter.GetChars(), &c_file);
if (filefirst != ((void *)(-1)))
{
@ -221,8 +227,70 @@ void DLoadSaveMenu::ReadSaveStrings ()
{
// I_FindName only returns the file's name and not its full path
FString filepath = G_BuildSaveName (I_FindName(&c_file), -1);
FILE *file = fopen (filepath, "rb");
FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, nullptr, true, true);
if (savegame != nullptr)
{
bool oldVer = false;
bool missing = false;
FResourceLump *info = savegame->FindLump("info.json");
if (info == nullptr)
{
// savegame info not found. This is not a savegame so leave it alone.
delete savegame;
continue;
}
void *data = info->CacheLump();
FSerializer arc;
if (arc.OpenReader((const char *)data, info->LumpSize))
{
int savever = 0;
FString engine;
FString iwad;
FString title;
arc("Save Version", savever);
arc("Engine", engine);
arc("Game WAD", iwad);
arc("Title", title);
if (engine.Compare(GAMESIG) != 0 || savever > SAVEVER)
{
// different engine or newer version:
// not our business. Leave it alone.
delete savegame;
continue;
}
if (savever < MINSAVEVER)
{
// old, incompatible savegame. List as not usable.
oldVer = true;
}
else if (iwad.CompareNoCase(Wads.GetWadName(FWadCollection::IWAD_FILENUM)) == 0)
{
missing = !G_CheckSaveGameWads(arc, false);
}
else
{
// different game. Skip this.
delete savegame;
continue;
}
FSaveGameNode *node = new FSaveGameNode;
node->Filename = filepath;
node->bOldVersion = oldVer;
node->bMissingWads = missing;
strncpy(node->Title, title.GetChars(), SAVESTRINGSIZE);
InsertSaveNode(node);
delete savegame;
}
}
else // check for old formats.
{
FILE *file = fopen (filepath, "rb");
if (file != NULL)
{
PNGHandle *png;
@ -241,45 +309,20 @@ void DLoadSaveMenu::ReadSaveStrings ()
title[SAVESTRINGSIZE] = 0;
if (NULL != (png = M_VerifyPNG (file)))
{
char *ver = M_GetPNGText (png, "ZDoom Save Version");
char *engine = M_GetPNGText (png, "Engine");
if (ver != NULL)
{
// An old version
if (!M_GetPNGText(png, "Title", title, SAVESTRINGSIZE))
{
strncpy(title, I_FindName(&c_file), SAVESTRINGSIZE);
}
if (strncmp (ver, SAVESIG, 9) == 0 &&
atoi (ver+9) >= MINSAVEVER &&
engine != NULL)
{
// Was saved with a compatible ZDoom version,
// so check if it's for the current game.
// If it is, add it. Otherwise, ignore it.
char *iwad = M_GetPNGText (png, "Game WAD");
if (iwad != NULL)
{
if (stricmp (iwad, Wads.GetWadName (FWadCollection::IWAD_FILENUM)) == 0)
{
addIt = true;
oldVer = false;
missing = !G_CheckSaveGameWads (png, false);
}
delete[] iwad;
}
}
else
{ // An old version
addIt = true;
}
delete[] ver;
}
if (engine != NULL)
{
delete[] engine;
}
delete png;
}
else
@ -312,13 +355,14 @@ void DLoadSaveMenu::ReadSaveStrings ()
{
FSaveGameNode *node = new FSaveGameNode;
node->Filename = filepath;
node->bOldVersion = oldVer;
node->bMissingWads = missing;
node->bOldVersion = true;
node->bMissingWads = false;
memcpy (node->Title, title, SAVESTRINGSIZE);
InsertSaveNode (node);
}
fclose (file);
}
}
} while (I_FindNext (filefirst, &c_file) == 0);
I_FindClose (filefirst);
}
@ -407,6 +451,7 @@ DLoadSaveMenu::DLoadSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
listboxHeight = listboxRows * rowHeight + 1;
listboxRight = listboxLeft + listboxWidth;
listboxBottom = listboxTop + listboxHeight;
currentSavePic = nullptr;
commentLeft = savepicLeft;
commentTop = savepicTop + savepicHeight + 16;
@ -418,6 +463,8 @@ DLoadSaveMenu::DLoadSaveMenu(DMenu *parent, FListMenuDescriptor *desc)
void DLoadSaveMenu::Destroy()
{
if (currentSavePic != nullptr) delete currentSavePic;
currentSavePic = nullptr;
ClearSaveStuff ();
}
@ -429,17 +476,23 @@ void DLoadSaveMenu::Destroy()
void DLoadSaveMenu::UnloadSaveData ()
{
if (SavePic != NULL)
if (SavePic != nullptr)
{
delete SavePic;
}
if (SaveComment != NULL)
if (SaveComment != nullptr)
{
V_FreeBrokenLines (SaveComment);
}
if (currentSavePic != nullptr)
{
delete currentSavePic;
}
SavePic = NULL;
SaveComment = NULL;
SavePic = nullptr;
SaveComment = nullptr;
currentSavePic = nullptr;
SavePicData.Clear();
}
//=============================================================================
@ -465,8 +518,7 @@ void DLoadSaveMenu::ClearSaveStuff ()
void DLoadSaveMenu::ExtractSaveData (int index)
{
FILE *file;
PNGHandle *png;
FResourceFile *resf;
FSaveGameNode *node;
UnloadSaveData ();
@ -475,66 +527,61 @@ void DLoadSaveMenu::ExtractSaveData (int index)
(node = SaveGames[index]) &&
!node->Filename.IsEmpty() &&
!node->bOldVersion &&
(file = fopen (node->Filename.GetChars(), "rb")) != NULL)
(resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), nullptr, true)) != nullptr)
{
if (NULL != (png = M_VerifyPNG (file)))
FResourceLump *info = resf->FindLump("info.json");
if (info == nullptr)
{
char *time, *pcomment, *comment;
size_t commentlen, totallen, timelen;
// this should not happen because the file has already been verified.
return;
}
void *data = info->CacheLump();
FSerializer arc;
if (arc.OpenReader((const char *)data, info->LumpSize))
{
FString time, pcomment, comment;
// Extract comment
time = M_GetPNGText (png, "Creation Time");
pcomment = M_GetPNGText (png, "Comment");
if (pcomment != NULL)
{
commentlen = strlen (pcomment);
}
else
{
commentlen = 0;
}
if (time != NULL)
{
timelen = strlen (time);
totallen = timelen + commentlen + 3;
}
else
{
timelen = 0;
totallen = commentlen + 1;
}
if (totallen != 0)
{
comment = new char[totallen];
arc("Creation Time", time);
arc("Comment", pcomment);
if (timelen)
{
memcpy (comment, time, timelen);
comment[timelen] = '\n';
comment[timelen+1] = '\n';
timelen += 2;
}
if (commentlen)
{
memcpy (comment + timelen, pcomment, commentlen);
}
comment[timelen+commentlen] = 0;
SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, comment);
delete[] comment;
delete[] time;
delete[] pcomment;
}
comment = time;
if (time.Len() > 0) comment += "\n\n";
comment += pcomment;
SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, comment.GetChars());
// Extract pic
FResourceLump *pic = resf->FindLump("savepic.png");
if (pic != nullptr)
{
FileReader *reader = pic->NewReader();
if (reader != nullptr)
{
// copy to a memory buffer which gets accessed through a memory reader and PNGHandle.
// We cannot use the actual lump as backing for the texture because that requires keeping the
// savegame file open.
SavePicData.Resize(pic->LumpSize);
reader->Read(&SavePicData[0], pic->LumpSize);
reader = new MemoryReader(&SavePicData[0], SavePicData.Size());
PNGHandle *png = M_VerifyPNG(reader);
if (png != nullptr)
{
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
currentSavePic = reader; // must be kept so that the texture can read from it.
delete png;
if (SavePic->GetWidth() == 1 && SavePic->GetHeight() == 1)
{
delete SavePic;
SavePic = NULL;
SavePic = nullptr;
delete currentSavePic;
currentSavePic = nullptr;
SavePicData.Clear();
}
}
fclose (file);
}
}
}
delete resf;
}
}

View file

@ -74,7 +74,7 @@
#include "p_setup.h"
#include "po_man.h"
#include "actorptrselect.h"
#include "farchive.h"
#include "serializer.h"
#include "decallib.h"
#include "p_terrain.h"
#include "version.h"
@ -82,6 +82,7 @@
#include "r_utility.h"
#include "a_morph.h"
#include "i_music.h"
#include "serializer.h"
#include "g_shared/a_pickups.h"
@ -720,47 +721,45 @@ void ACSStringPool::FindFirstFreeEntry(unsigned base)
//
//============================================================================
void ACSStringPool::ReadStrings(PNGHandle *png, DWORD id)
void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
{
Clear();
size_t len = M_FindPNGChunk(png, id);
if (len != 0)
if (file.BeginObject(key))
{
FPNGChunkArchive arc(png->File->GetFile(), id, len);
int32_t i, j, poolsize;
unsigned int h, bucketnum;
char *str = NULL;
arc << poolsize;
int poolsize = 0;
file("poolsize", poolsize);
Pool.Resize(poolsize);
i = 0;
j = arc.ReadCount();
while (j >= 0)
for (auto &p : Pool)
{
// Mark skipped entries as free
for (; i < j; ++i)
{
Pool[i].Next = FREE_ENTRY;
Pool[i].LockCount = 0;
p.Next = FREE_ENTRY;
p.LockCount = 0;
}
arc << str;
h = SuperFastHash(str, strlen(str));
bucketnum = h % NUM_BUCKETS;
Pool[i].Str = str;
Pool[i].Hash = h;
Pool[i].LockCount = arc.ReadCount();
Pool[i].Next = PoolBuckets[bucketnum];
if (file.BeginArray("pool"))
{
int j = file.ArraySize();
for (int i = 0; i < j; i++)
{
if (file.BeginObject(nullptr))
{
unsigned ii = UINT_MAX;
file("index", ii);
if (ii < Pool.Size())
{
file("string", Pool[ii].Str)
("lockcount", Pool[ii].LockCount);
unsigned h = SuperFastHash(Pool[ii].Str, Pool[ii].Str.Len());
unsigned bucketnum = h % NUM_BUCKETS;
Pool[ii].Hash = h;
Pool[ii].Next = PoolBuckets[bucketnum];
PoolBuckets[bucketnum] = i;
i++;
j = arc.ReadCount();
}
if (str != NULL)
{
delete[] str;
file.EndObject();
}
}
}
FindFirstFreeEntry(0);
}
}
@ -768,11 +767,11 @@ void ACSStringPool::ReadStrings(PNGHandle *png, DWORD id)
//
// ACSStringPool :: WriteStrings
//
// Writes strings to a PNG chunk.
// Writes strings to a serializer
//
//============================================================================
void ACSStringPool::WriteStrings(FILE *file, DWORD id) const
void ACSStringPool::WriteStrings(FSerializer &file, const char *key) const
{
int32_t i, poolsize = (int32_t)Pool.Size();
@ -780,20 +779,29 @@ void ACSStringPool::WriteStrings(FILE *file, DWORD id) const
{ // No need to write if we don't have anything.
return;
}
FPNGChunkArchive arc(file, id);
arc << poolsize;
if (file.BeginObject(key))
{
file("poolsize", poolsize);
if (file.BeginArray("pool"))
{
for (i = 0; i < poolsize; ++i)
{
PoolEntry *entry = &Pool[i];
if (entry->Next != FREE_ENTRY)
{
arc.WriteCount(i);
arc.WriteString(entry->Str);
arc.WriteCount(entry->LockCount);
if (file.BeginObject(nullptr))
{
file("index", i)
("string", entry->Str)
("lockcount", entry->LockCount)
.EndObject();
}
}
arc.WriteCount(-1);
}
file.EndArray();
}
file.EndObject();
}
}
//============================================================================
@ -943,7 +951,7 @@ void P_ClearACSVars(bool alsoglobal)
//
//============================================================================
static void WriteVars (FILE *file, SDWORD *vars, size_t count, DWORD id)
static void WriteVars (FSerializer &file, SDWORD *vars, size_t count, const char *key)
{
size_t i, j;
@ -961,43 +969,7 @@ static void WriteVars (FILE *file, SDWORD *vars, size_t count, DWORD id)
if (vars[j] != 0)
break;
}
FPNGChunkArchive arc (file, id);
for (i = 0; i <= j; ++i)
{
DWORD var = vars[i];
arc << var;
}
}
}
//============================================================================
//
//
//
//============================================================================
static void ReadVars (PNGHandle *png, SDWORD *vars, size_t count, DWORD id)
{
size_t len = M_FindPNGChunk (png, id);
size_t used = 0;
if (len != 0)
{
DWORD var;
size_t i;
FPNGChunkArchive arc (png->File->GetFile(), id, len);
used = len / 4;
for (i = 0; i < used; ++i)
{
arc << var;
vars[i] = var;
}
png->File->ResetFilePtr();
}
if (used < count)
{
memset (&vars[used], 0, (count-used)*4);
file.Array(key, vars, int(j+1));
}
}
@ -1007,9 +979,21 @@ static void ReadVars (PNGHandle *png, SDWORD *vars, size_t count, DWORD id)
//
//============================================================================
static void WriteArrayVars (FILE *file, FWorldGlobalArray *vars, unsigned int count, DWORD id)
static void ReadVars (FSerializer &arc, SDWORD *vars, size_t count, const char *key)
{
unsigned int i, j;
memset(&vars[0], 0, count * 4);
arc.Array(key, vars, (int)count);
}
//============================================================================
//
//
//
//============================================================================
static void WriteArrayVars (FSerializer &file, FWorldGlobalArray *vars, unsigned int count, const char *key)
{
unsigned int i;
// Find the first non-empty array.
for (i = 0; i < count; ++i)
@ -1019,28 +1003,31 @@ static void WriteArrayVars (FILE *file, FWorldGlobalArray *vars, unsigned int co
}
if (i < count)
{
// Find last non-empty array. Anything beyond the last stored array
// will be emptied at load time.
for (j = count-1; j > i; --j)
if (file.BeginObject(key))
{
if (vars[j].CountUsed() != 0)
break;
}
FPNGChunkArchive arc (file, id);
arc.WriteCount (i);
arc.WriteCount (j);
for (; i <= j; ++i)
for(;i<count;i++)
{
arc.WriteCount (vars[i].CountUsed());
if (vars[i].CountUsed())
{
FString arraykey;
arraykey.Format("%d", i);
if (file.BeginObject(arraykey))
{
FWorldGlobalArray::ConstIterator it(vars[i]);
const FWorldGlobalArray::Pair *pair;
while (it.NextPair(pair))
{
arc.WriteCount (pair->Key);
arc.WriteCount (pair->Value);
arraykey.Format("%d", pair->Key);
int v = pair->Value;
file(arraykey.GetChars(), v);
}
file.EndObject();
}
}
}
file.EndObject();
}
}
}
@ -1051,37 +1038,32 @@ static void WriteArrayVars (FILE *file, FWorldGlobalArray *vars, unsigned int co
//
//============================================================================
static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count, DWORD id)
static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t count, const char *key)
{
size_t len = M_FindPNGChunk (png, id);
unsigned int i, k;
for (i = 0; i < count; ++i)
for (size_t i = 0; i < count; ++i)
{
vars[i].Clear();
}
if (len != 0)
if (file.BeginObject(key))
{
DWORD max, size;
FPNGChunkArchive arc (png->File->GetFile(), id, len);
i = arc.ReadCount ();
max = arc.ReadCount ();
for (; i <= max; ++i)
const char *arraykey;
while ((arraykey = file.GetKey()))
{
size = arc.ReadCount ();
for (k = 0; k < size; ++k)
int i = (int)strtol(arraykey, nullptr, 10);
if (file.BeginObject(nullptr))
{
SDWORD key, val;
key = arc.ReadCount();
val = arc.ReadCount();
vars[i].Insert (key, val);
while ((arraykey = file.GetKey()))
{
int k = (int)strtol(arraykey, nullptr, 10);
int val;
file(nullptr, val);
vars[i].Insert(k, val);
}
file.EndObject();
}
}
png->File->ResetFilePtr();
file.EndObject();
}
}
@ -1091,13 +1073,13 @@ static void ReadArrayVars (PNGHandle *png, FWorldGlobalArray *vars, size_t count
//
//============================================================================
void P_ReadACSVars(PNGHandle *png)
void P_ReadACSVars(FSerializer &arc)
{
ReadVars (png, ACS_WorldVars, NUM_WORLDVARS, MAKE_ID('w','v','A','r'));
ReadVars (png, ACS_GlobalVars, NUM_GLOBALVARS, MAKE_ID('g','v','A','r'));
ReadArrayVars (png, ACS_WorldArrays, NUM_WORLDVARS, MAKE_ID('w','a','R','r'));
ReadArrayVars (png, ACS_GlobalArrays, NUM_GLOBALVARS, MAKE_ID('g','a','R','r'));
GlobalACSStrings.ReadStrings(png, MAKE_ID('a','s','T','r'));
ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
}
//============================================================================
@ -1106,13 +1088,13 @@ void P_ReadACSVars(PNGHandle *png)
//
//============================================================================
void P_WriteACSVars(FILE *stdfile)
void P_WriteACSVars(FSerializer &arc)
{
WriteVars (stdfile, ACS_WorldVars, NUM_WORLDVARS, MAKE_ID('w','v','A','r'));
WriteVars (stdfile, ACS_GlobalVars, NUM_GLOBALVARS, MAKE_ID('g','v','A','r'));
WriteArrayVars (stdfile, ACS_WorldArrays, NUM_WORLDVARS, MAKE_ID('w','a','R','r'));
WriteArrayVars (stdfile, ACS_GlobalArrays, NUM_GLOBALVARS, MAKE_ID('g','a','R','r'));
GlobalACSStrings.WriteStrings(stdfile, MAKE_ID('a','s','T','r'));
WriteVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars");
WriteVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars");
WriteArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays");
WriteArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.WriteStrings(arc, "acsglobalstrings");
}
//---- Inventory functions --------------------------------------//
@ -1367,11 +1349,12 @@ public:
int tag, int height, int special,
int arg0, int arg1, int arg2, int arg3, int arg4);
void Tick ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
private:
sector_t *Sector;
double WatchD, LastD;
int Special, Arg0, Arg1, Arg2, Arg3, Arg4;
int Special;
int Args[5];
TObjPtr<AActor> Activator;
line_t *Line;
bool LineSide;
@ -1387,11 +1370,16 @@ END_POINTERS
DPlaneWatcher::DPlaneWatcher (AActor *it, line_t *line, int lineSide, bool ceiling,
int tag, int height, int special,
int arg0, int arg1, int arg2, int arg3, int arg4)
: Special (special), Arg0 (arg0), Arg1 (arg1), Arg2 (arg2), Arg3 (arg3), Arg4 (arg4),
: Special (special),
Activator (it), Line (line), LineSide (!!lineSide), bCeiling (ceiling)
{
int secnum;
Args[0] = arg0;
Args[1] = arg1;
Args[2] = arg2;
Args[3] = arg3;
Args[4] = arg4;
secnum = P_FindFirstSectorFromTag (tag);
if (secnum >= 0)
{
@ -1417,13 +1405,19 @@ DPlaneWatcher::DPlaneWatcher (AActor *it, line_t *line, int lineSide, bool ceili
}
}
void DPlaneWatcher::Serialize (FArchive &arc)
void DPlaneWatcher::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("special", Special)
.Args("args", Args, nullptr, Special)
("sector", Sector)
("ceiling", bCeiling)
("watchd", WatchD)
("lastd", LastD)
("activator", Activator)
("line", Line)
("lineside", LineSide);
arc << Special << Arg0 << Arg1 << Arg2 << Arg3 << Arg4
<< Sector << bCeiling << WatchD << LastD << Activator
<< Line << LineSide << bCeiling;
}
void DPlaneWatcher::Tick ()
@ -1448,7 +1442,7 @@ void DPlaneWatcher::Tick ()
if ((LastD < WatchD && newd >= WatchD) ||
(LastD > WatchD && newd <= WatchD))
{
P_ExecuteSpecial(Special, Line, Activator, LineSide, Arg0, Arg1, Arg2, Arg3, Arg4);
P_ExecuteSpecial(Special, Line, Activator, LineSide, Args[0], Args[1], Args[2], Args[3], Args[4]);
Destroy ();
}
@ -1614,64 +1608,72 @@ void FBehavior::UnlockMapVarStrings() const
}
}
void FBehavior::StaticSerializeModuleStates (FArchive &arc)
void FBehavior::StaticSerializeModuleStates (FSerializer &arc)
{
DWORD modnum;
modnum = StaticModules.Size();
arc << modnum;
auto modnum = StaticModules.Size();
if (arc.BeginArray("acsmodules"))
{
if (arc.isReading())
{
int modnum = arc.ArraySize();
if (modnum != StaticModules.Size())
{
I_Error("Level was saved with a different number of ACS modules. (Have %d, save has %d)", StaticModules.Size(), modnum);
}
}
for (modnum = 0; modnum < StaticModules.Size(); ++modnum)
{
FBehavior *module = StaticModules[modnum];
const char *modname = module->ModuleName;
int ModSize = module->GetDataSize();
if (arc.IsStoring())
if (arc.BeginObject(nullptr))
{
arc.WriteString (module->ModuleName);
arc << ModSize;
}
else
arc.StringPtr("modname", modname)
("modsize", ModSize);
if (arc.isReading())
{
char *modname = NULL;
arc << modname;
arc << ModSize;
if (stricmp(modname, module->ModuleName) != 0)
{
delete[] modname;
I_Error("Level was saved with a different set or order of ACS modules. (Have %s, save has %s)", module->ModuleName, modname);
}
else if (ModSize != module->GetDataSize())
{
delete[] modname;
I_Error("ACS module %s has changed from what was saved. (Have %d bytes, save has %d bytes)", module->ModuleName, module->GetDataSize(), ModSize);
}
delete[] modname;
}
module->SerializeVars(arc);
arc.EndObject();
}
}
arc.EndArray();
}
}
void FBehavior::SerializeVars (FArchive &arc)
void FBehavior::SerializeVars (FSerializer &arc)
{
if (arc.BeginArray("variables"))
{
SerializeVarSet(arc, MapVarStore, NUM_MAPVARS);
for (int i = 0; i < NumArrays; ++i)
{
SerializeVarSet(arc, ArrayStore[i].Elements, ArrayStore[i].ArraySize);
}
arc.EndArray();
}
}
void FBehavior::SerializeVarSet (FArchive &arc, SDWORD *vars, int max)
void FBehavior::SerializeVarSet (FSerializer &arc, SDWORD *vars, int max)
{
SDWORD arcval;
SDWORD count;
SDWORD first, last;
if (arc.IsStoring ())
if (arc.BeginObject(nullptr))
{
if (arc.isWriting())
{
// Find first non-zero variable
for (first = 0; first < max; ++first)
@ -1693,52 +1695,30 @@ void FBehavior::SerializeVarSet (FArchive &arc, SDWORD *vars, int max)
if (last < first)
{ // no non-zero variables
arcval = 0;
arc << arcval;
return;
count = 0;
arc("count", count);
}
arcval = last - first + 1;
arc << arcval;
arcval = first;
arc << arcval;
while (first <= last)
else
{
arc << vars[first];
++first;
count = last - first + 1;
arc("count", count);
arc("first", first);
arc.Array("values", &vars[first], count);
}
}
else
{
SDWORD truelast;
memset(vars, 0, max * sizeof(*vars));
arc("count", count);
arc << last;
if (last == 0)
if (count != 0)
{
return;
arc("first", first);
if (first + count > max) count = max - first;
arc.Array("values", &vars[first], count);
}
arc << first;
last += first;
truelast = last;
if (last > max)
{
last = max;
}
while (first < last)
{
arc << vars[first];
++first;
}
while (first < truelast)
{
arc << arcval;
++first;
}
arc.EndObject();
}
}
@ -2869,33 +2849,6 @@ void FBehavior::StaticStopMyScripts (AActor *actor)
}
}
//==========================================================================
//
// P_SerializeACSScriptNumber
//
// Serializes a script number. If it's negative, it's really a name, so
// that will get serialized after it.
//
//==========================================================================
void P_SerializeACSScriptNumber(FArchive &arc, int &scriptnum, bool was2byte)
{
arc << scriptnum;
// If the script number is negative, then it's really a name.
// So read/store the name after it.
if (scriptnum < 0)
{
if (arc.IsStoring())
{
arc.WriteName(FName(ENamedName(-scriptnum)).GetChars());
}
else
{
const char *nam = arc.ReadName();
scriptnum = -FName(nam);
}
}
}
//---- The ACS Interpreter ----//
@ -2928,81 +2881,65 @@ DACSThinker::~DACSThinker ()
ActiveThinker = NULL;
}
void DACSThinker::Serialize (FArchive &arc)
//==========================================================================
//
// helper class for the runningscripts serializer
//
//==========================================================================
struct SavingRunningscript
{
int scriptnum;
int scriptcount = 0;
DLevelScript *lscript;
};
FSerializer &Serialize(FSerializer &arc, const char *key, SavingRunningscript &rs, SavingRunningscript *def)
{
if (arc.BeginObject(key))
{
arc.ScriptNum("num", rs.scriptnum)
("script", rs.lscript)
.EndObject();
}
return arc;
}
void DACSThinker::Serialize(FSerializer &arc)
{
Super::Serialize(arc);
if (arc.IsStoring())
{
DLevelScript *script;
script = Scripts;
while (script)
{
scriptcount++;
arc("scripts", Scripts);
// We want to store this list backwards, so we can't loose the last pointer
if (script->next == NULL)
break;
script = script->next;
}
arc << scriptcount;
while (script)
if (arc.isWriting())
{
arc << script;
script = script->prev;
}
}
else
{
// We are running through this list backwards, so the next entry is the last processed
DLevelScript *next = NULL;
arc << scriptcount;
Scripts = NULL;
LastScript = NULL;
for (int i = 0; i < scriptcount; i++)
{
arc << Scripts;
Scripts->next = next;
Scripts->prev = NULL;
if (next != NULL)
next->prev = Scripts;
next = Scripts;
if (i == 0)
LastScript = Scripts;
}
}
if (arc.IsStoring ())
if (RunningScripts.CountUsed())
{
ScriptMap::Iterator it(RunningScripts);
ScriptMap::Pair *pair;
arc.BeginArray("runningscripts");
while (it.NextPair(pair))
{
assert(pair->Value != NULL);
arc << pair->Value;
scriptnum = pair->Key;
P_SerializeACSScriptNumber(arc, scriptnum, true);
assert(pair->Value != nullptr);
SavingRunningscript srs = { pair->Key, pair->Value };
arc(nullptr, srs);
}
arc.EndArray();
}
DLevelScript *nilptr = NULL;
arc << nilptr;
}
else // Loading
{
DLevelScript *script = NULL;
DLevelScript *script = nullptr;
RunningScripts.Clear();
arc << script;
while (script)
if (arc.BeginArray("runningscripts"))
{
P_SerializeACSScriptNumber(arc, scriptnum, true);
RunningScripts[scriptnum] = script;
arc << script;
auto cnt = arc.ArraySize();
for (int i = 0; i < cnt; i++)
{
SavingRunningscript srs;
arc(nullptr, srs);
RunningScripts[srs.scriptnum] = srs.lscript;
}
arc.EndArray();
}
}
}
@ -3049,58 +2986,51 @@ IMPLEMENT_POINTY_CLASS (DLevelScript)
DECLARE_POINTER(activator)
END_POINTERS
inline FArchive &operator<< (FArchive &arc, DLevelScript::EScriptState &state)
{
BYTE val = (BYTE)state;
arc << val;
state = (DLevelScript::EScriptState)val;
return arc;
}
//==========================================================================
//
// SerializeFFontPtr
//
//==========================================================================
void DLevelScript::Serialize (FArchive &arc)
void DLevelScript::Serialize(FSerializer &arc)
{
DWORD i;
Super::Serialize(arc);
P_SerializeACSScriptNumber(arc, script, false);
uint32_t pcofs;
uint16_t lib;
arc << state
<< statedata
<< activator
<< activationline
<< backSide
<< numlocalvars;
if (arc.IsLoading())
if (arc.isWriting())
{
localvars = new SDWORD[numlocalvars];
}
for (i = 0; i < (DWORD)numlocalvars; i++)
{
arc << localvars[i];
lib = activeBehavior->GetLibraryID() >> LIBRARYID_SHIFT;
pcofs = activeBehavior->PC2Ofs(pc);
}
if (arc.IsStoring ())
arc.ScriptNum("scriptnum", script)
("next", next)
("prev", prev)
.Enum("state", state)
("statedata", statedata)
("activator", activator)
("activationline", activationline)
("backside", backSide)
("localvars", Localvars)
("lib", lib)
("pc", pcofs)
("activefont", activefont)
("hudwidth", hudwidth)
("hudheight", hudheight)
("cliprectleft", ClipRectLeft)
("cliprectop", ClipRectTop)
("cliprectwidth", ClipRectWidth)
("cliprectheight", ClipRectHeight)
("wrapwidth", WrapWidth)
("inmodulescriptnum", InModuleScriptNumber);
if (arc.isReading())
{
WORD lib = activeBehavior->GetLibraryID() >> LIBRARYID_SHIFT;
arc << lib;
i = activeBehavior->PC2Ofs (pc);
arc << i;
}
else
{
WORD lib;
arc << lib << i;
activeBehavior = FBehavior::StaticGetModule(lib);
pc = activeBehavior->Ofs2PC (i);
pc = activeBehavior->Ofs2PC(pcofs);
}
arc << activefont
<< hudwidth << hudheight;
arc << ClipRectLeft << ClipRectTop << ClipRectWidth << ClipRectHeight
<< WrapWidth;
arc << InModuleScriptNumber;
}
DLevelScript::DLevelScript ()
@ -3109,14 +3039,10 @@ DLevelScript::DLevelScript ()
if (DACSThinker::ActiveThinker == NULL)
new DACSThinker;
activefont = SmallFont;
localvars = NULL;
}
DLevelScript::~DLevelScript ()
{
if (localvars != NULL)
delete[] localvars;
localvars = NULL;
}
void DLevelScript::Unlink ()
@ -6141,7 +6067,7 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int &
int DLevelScript::RunScript ()
{
DACSThinker *controller = DACSThinker::ActiveThinker;
SDWORD *locals = localvars;
SDWORD *locals = &Localvars[0];
ACSLocalArrays noarrays;
ACSLocalArrays *localarrays = &noarrays;
ScriptFunction *activeFunction = NULL;
@ -9677,12 +9603,11 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr
script = num;
assert(code->VarCount >= code->ArgCount);
numlocalvars = code->VarCount;
localvars = new SDWORD[code->VarCount];
memset(localvars, 0, code->VarCount * sizeof(SDWORD));
Localvars.Resize(code->VarCount);
memset(&Localvars[0], 0, code->VarCount * sizeof(SDWORD));
for (int i = 0; i < MIN<int>(argcount, code->ArgCount); ++i)
{
localvars[i] = args[i];
Localvars[i] = args[i];
}
pc = module->GetScriptAddress(code);
InModuleScriptNumber = module->GetScriptIndex(code);
@ -9727,15 +9652,13 @@ static void SetScriptState (int script, DLevelScript::EScriptState state)
void P_DoDeferedScripts ()
{
acsdefered_t *def;
const ScriptPtr *scriptdata;
FBehavior *module;
// Handle defered scripts in this step, too
def = level.info->defered;
while (def)
for(int i = level.info->deferred.Size()-1; i>=0; i--)
{
acsdefered_t *next = def->next;
acsdefered_t *def = &level.info->deferred[i];
switch (def->type)
{
case acsdefered_t::defexecute:
@ -9766,39 +9689,35 @@ void P_DoDeferedScripts ()
DPrintf (DMSG_SPAMMY, "Deferred terminate of %s\n", ScriptPresentation(def->script).GetChars());
break;
}
delete def;
def = next;
}
level.info->defered = NULL;
level.info->deferred.Clear();
}
static void addDefered (level_info_t *i, acsdefered_t::EType type, int script, const int *args, int argcount, AActor *who)
{
if (i)
{
acsdefered_t *def = new acsdefered_t;
acsdefered_t &def = i->deferred[i->deferred.Reserve(1)];
int j;
def->next = i->defered;
def->type = type;
def->script = script;
for (j = 0; (size_t)j < countof(def->args) && j < argcount; ++j)
def.type = type;
def.script = script;
for (j = 0; (size_t)j < countof(def.args) && j < argcount; ++j)
{
def->args[j] = args[j];
def.args[j] = args[j];
}
while ((size_t)j < countof(def->args))
while ((size_t)j < countof(def.args))
{
def->args[j++] = 0;
def.args[j++] = 0;
}
if (who != NULL && who->player != NULL)
{
def->playernum = int(who->player - players);
def.playernum = int(who->player - players);
}
else
{
def->playernum = -1;
def.playernum = -1;
}
i->defered = def;
DPrintf (DMSG_SPAMMY, "%s on map %s deferred\n", ScriptPresentation(script).GetChars(), i->MapName.GetChars());
}
}
@ -9876,43 +9795,15 @@ void P_TerminateScript (int script, const char *map)
SetScriptState (script, DLevelScript::SCRIPT_PleaseRemove);
}
FArchive &operator<< (FArchive &arc, acsdefered_t *&defertop)
FSerializer &Serialize(FSerializer &arc, const char *key, acsdefered_t &defer, acsdefered_t *def)
{
BYTE more;
if (arc.IsStoring ())
if (arc.BeginObject(key))
{
acsdefered_t *defer = defertop;
more = 1;
while (defer)
{
BYTE type;
arc << more;
type = (BYTE)defer->type;
arc << type;
P_SerializeACSScriptNumber(arc, defer->script, false);
arc << defer->playernum << defer->args[0] << defer->args[1] << defer->args[2];
defer = defer->next;
}
more = 0;
arc << more;
}
else
{
acsdefered_t **defer = &defertop;
arc << more;
while (more)
{
*defer = new acsdefered_t;
arc << more;
(*defer)->type = (acsdefered_t::EType)more;
P_SerializeACSScriptNumber(arc, (*defer)->script, false);
arc << (*defer)->playernum << (*defer)->args[0] << (*defer)->args[1] << (*defer)->args[2];
defer = &((*defer)->next);
arc << more;
}
*defer = NULL;
arc.Enum("type", defer.type)
.ScriptNum("script", defer.script)
.Array("args", defer.args, 3)
("player", defer.playernum)
.EndObject();
}
return arc;
}

View file

@ -44,6 +44,7 @@
class FFont;
class FileReader;
struct line_t;
enum
@ -94,8 +95,8 @@ public:
void PurgeStrings();
void Clear();
void Dump() const;
void ReadStrings(PNGHandle *png, DWORD id);
void WriteStrings(FILE *file, DWORD id) const;
void ReadStrings(FSerializer &file, const char *key);
void WriteStrings(FSerializer &file, const char *key) const;
private:
int FindString(const char *str, size_t len, unsigned int h, unsigned int bucketnum);
@ -120,10 +121,9 @@ private:
extern ACSStringPool GlobalACSStrings;
void P_CollectACSGlobalStrings();
void P_ReadACSVars(PNGHandle *);
void P_WriteACSVars(FILE*);
void P_ReadACSVars(FSerializer &);
void P_WriteACSVars(FSerializer &);
void P_ClearACSVars(bool);
void P_SerializeACSScriptNumber(FArchive &arc, int &scriptnum, bool was2byte);
struct ACSProfileInfo
{
@ -325,7 +325,7 @@ public:
static void StaticUnloadModules ();
static bool StaticCheckAllGood ();
static FBehavior *StaticGetModule (int lib);
static void StaticSerializeModuleStates (FArchive &arc);
static void StaticSerializeModuleStates (FSerializer &arc);
static void StaticMarkLevelVarStrings();
static void StaticLockLevelVarStrings();
static void StaticUnlockLevelVarStrings();
@ -369,8 +369,8 @@ private:
void UnescapeStringTable(BYTE *chunkstart, BYTE *datastart, bool haspadding);
int FindStringInChunk (DWORD *chunk, const char *varname) const;
void SerializeVars (FArchive &arc);
void SerializeVarSet (FArchive &arc, SDWORD *vars, int max);
void SerializeVars (FSerializer &arc);
void SerializeVarSet (FSerializer &arc, SDWORD *vars, int max);
void MarkMapVarStrings() const;
void LockMapVarStrings() const;
@ -860,7 +860,7 @@ public:
const int *args, int argcount, int flags);
~DLevelScript ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
int RunScript ();
inline void SetState (EScriptState newstate) { state = newstate; }
@ -870,22 +870,21 @@ public:
void MarkLocalVarStrings() const
{
GlobalACSStrings.MarkStringArray(localvars, numlocalvars);
GlobalACSStrings.MarkStringArray(&Localvars[0], Localvars.Size());
}
void LockLocalVarStrings() const
{
GlobalACSStrings.LockStringArray(localvars, numlocalvars);
GlobalACSStrings.LockStringArray(&Localvars[0], Localvars.Size());
}
void UnlockLocalVarStrings() const
{
GlobalACSStrings.UnlockStringArray(localvars, numlocalvars);
GlobalACSStrings.UnlockStringArray(&Localvars[0], Localvars.Size());
}
protected:
DLevelScript *next, *prev;
int script;
SDWORD *localvars;
int numlocalvars;
TArray<int32_t> Localvars;
int *pc;
EScriptState state;
int statedata;
@ -945,7 +944,7 @@ public:
DACSThinker ();
~DACSThinker ();
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
void Tick ();
typedef TMap<int, DLevelScript *> ScriptMap;
@ -966,8 +965,6 @@ private:
// The structure used to control scripts between maps
struct acsdefered_t
{
struct acsdefered_t *next;
enum EType
{
defexecute,
@ -980,6 +977,6 @@ struct acsdefered_t
int playernum;
};
FArchive &operator<< (FArchive &arc, acsdefered_t *&defer);
FSerializer &Serialize(FSerializer &arc, const char *key, acsdefered_t &defer, acsdefered_t *def);
#endif //__P_ACS_H__

Some files were not shown because too many files have changed in this diff Show more