Merge remote-tracking branch 'gzdoom/master' into lightmath

# Conflicts:
#	src/gl/renderer/gl_renderbuffers.cpp
#	src/gl/renderer/gl_renderbuffers.h
#	src/gl/renderer/gl_renderer.h
#	src/gl/scene/gl_scene.cpp
This commit is contained in:
Magnus Norddahl 2016-09-24 08:12:12 +02:00
commit d126e91ded
246 changed files with 22605 additions and 7056 deletions

View file

@ -1115,6 +1115,7 @@ set( FASTMATH_SOURCES
gl/stereo3d/scoped_view_shifter.cpp gl/stereo3d/scoped_view_shifter.cpp
gl/stereo3d/gl_anaglyph.cpp gl/stereo3d/gl_anaglyph.cpp
gl/stereo3d/gl_quadstereo.cpp gl/stereo3d/gl_quadstereo.cpp
gl/stereo3d/gl_sidebyside3d.cpp
gl/dynlights/gl_dynlight.cpp gl/dynlights/gl_dynlight.cpp
gl/dynlights/gl_glow.cpp gl/dynlights/gl_glow.cpp
gl/dynlights/gl_dynlight1.cpp gl/dynlights/gl_dynlight1.cpp
@ -1178,7 +1179,6 @@ set (PCH_SOURCES
dthinker.cpp dthinker.cpp
edata.cpp edata.cpp
f_wipe.cpp f_wipe.cpp
farchive.cpp
files.cpp files.cpp
g_doomedmap.cpp g_doomedmap.cpp
g_game.cpp g_game.cpp
@ -1257,8 +1257,9 @@ set (PCH_SOURCES
p_xlat.cpp p_xlat.cpp
parsecontext.cpp parsecontext.cpp
po_man.cpp po_man.cpp
portal.cpp portal.cpp
r_utility.cpp r_utility.cpp
serializer.cpp
sc_man.cpp sc_man.cpp
st_stuff.cpp st_stuff.cpp
statistics.cpp statistics.cpp
@ -1360,7 +1361,6 @@ set (PCH_SOURCES
thingdef/thingdef_properties.cpp thingdef/thingdef_properties.cpp
thingdef/thingdef_states.cpp thingdef/thingdef_states.cpp
xlat/parse_xlat.cpp xlat/parse_xlat.cpp
fragglescript/t_fspic.cpp
fragglescript/t_func.cpp fragglescript/t_func.cpp
fragglescript/t_load.cpp fragglescript/t_load.cpp
fragglescript/t_oper.cpp fragglescript/t_oper.cpp
@ -1564,6 +1564,7 @@ source_group("Games\\Strife Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DI
source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+") source_group("Intermission" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/intermission/.+")
source_group("Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+") source_group("Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/math/.+")
source_group("Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/menu/.+") 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" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/.+")
source_group("OpenGL Renderer\\Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/data/.+") 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/.+") source_group("OpenGL Renderer\\Dynamic Lights" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/gl/dynlights/.+")

View file

@ -111,6 +111,8 @@ struct FPortalGroupArray;
// Any questions? // Any questions?
// //
// --- mobj.flags --- // --- mobj.flags ---
enum ActorFlag enum ActorFlag
{ {
@ -581,8 +583,9 @@ public:
void Destroy (); void Destroy ();
~AActor (); ~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); static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
inline AActor *GetDefault () const inline AActor *GetDefault () const
@ -986,7 +989,7 @@ public:
double Speed; double Speed;
double FloatSpeed; 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 BYTE frame; // sprite frame to draw
DVector2 Scale; // Scaling values; 1 is normal size DVector2 Scale; // Scaling values; 1 is normal size
FRenderStyle RenderStyle; // Style to draw this actor with FRenderStyle RenderStyle; // Style to draw this actor with
@ -1014,7 +1017,9 @@ public:
SDWORD tics; // state tic counter SDWORD tics; // state tic counter
FState *state; FState *state;
VMFunction *Damage; // For missiles and monster railgun //VMFunction *Damage; // For missiles and monster railgun
int DamageVal;
VMFunction *DamageFunc;
int projectileKickback; int projectileKickback;
ActorFlags flags; ActorFlags flags;
ActorFlags2 flags2; // Heretic flags ActorFlags2 flags2; // Heretic flags
@ -1179,8 +1184,9 @@ public:
private: private:
static AActor *TIDHash[128]; static AActor *TIDHash[128];
static inline int TIDHASH (int key) { return key & 127; } static inline int TIDHASH (int key) { return key & 127; }
public:
static FSharedStringArena mStringPropertyData; static FSharedStringArena mStringPropertyData;
private:
friend class FActorIterator; friend class FActorIterator;
friend bool P_IsTIDUsed(int tid); friend bool P_IsTIDUsed(int tid);
@ -1201,6 +1207,23 @@ public:
FState *GetRaiseState(); FState *GetRaiseState();
void Revive(); void Revive();
void SetDamage(int dmg)
{
DamageVal = dmg;
DamageFunc = nullptr;
}
bool IsZeroDamage() const
{
return DamageVal == 0 && DamageFunc == nullptr;
}
void RestoreDamage()
{
DamageVal = GetDefault()->DamageVal;
DamageFunc = GetDefault()->DamageFunc;
}
FState *FindState (FName label) const FState *FindState (FName label) const
{ {
return GetClass()->FindState(1, &label); return GetClass()->FindState(1, &label);

View file

@ -38,7 +38,7 @@
#include "gi.h" #include "gi.h"
#include "p_setup.h" #include "p_setup.h"
#include "c_bind.h" #include "c_bind.h"
#include "farchive.h" #include "serializer.h"
#include "r_renderer.h" #include "r_renderer.h"
#include "r_sky.h" #include "r_sky.h"
#include "sbar.h" #include "sbar.h"
@ -3106,13 +3106,14 @@ void AM_Drawer ()
// //
//============================================================================= //=============================================================================
void AM_SerializeMarkers(FArchive &arc) void AM_SerializeMarkers(FSerializer &arc)
{ {
arc << markpointnum; if (arc.BeginObject("automarkers"))
for (int i=0; i<AM_NUMMARKPOINTS; i++)
{ {
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__ #define __AMMAP_H__
struct event_t; struct event_t;
class FArchive; class FSerializer;
void AM_StaticInit(); void AM_StaticInit();
@ -45,7 +45,7 @@ void AM_Stop (void);
void AM_NewResolution (); void AM_NewResolution ();
void AM_ToggleMap (); void AM_ToggleMap ();
void AM_LevelInit (); void AM_LevelInit ();
void AM_SerializeMarkers(FArchive &arc); void AM_SerializeMarkers(FSerializer &arc);
#endif #endif

View file

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

View file

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

View file

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

View file

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

View file

@ -69,7 +69,7 @@
#include "i_system.h" #include "i_system.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "p_effect.h" #include "p_effect.h"
#include "farchive.h" #include "serializer.h"
#include "vmbuilder.h" #include "vmbuilder.h"
// [SO] Just the way Randy said to do it :) // [SO] Just the way Randy said to do it :)
@ -915,7 +915,7 @@ static int PatchThing (int thingy)
} }
else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0) else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0)
{ {
info->Damage = CreateDamageFunction(val); info->SetDamage(val);
} }
else if (linelen == 5) else if (linelen == 5)
{ {
@ -3198,8 +3198,8 @@ PClassActor *ADehackedPickup::DetermineType ()
return NULL; return NULL;
} }
void ADehackedPickup::Serialize(FArchive &arc) void ADehackedPickup::Serialize(FSerializer &arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);
arc << droppedbymonster; arc("droppedbymonster", droppedbymonster);
} }

View file

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

View file

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

View file

@ -56,7 +56,7 @@
#include "r_data/r_translate.h" #include "r_data/r_translate.h"
#include "templates.h" #include "templates.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "farchive.h" #include "serializer.h"
static FRandom pr_pickteam ("PickRandomTeam"); static FRandom pr_pickteam ("PickRandomTeam");
@ -70,6 +70,7 @@ CVAR (String, gender, "male", CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (Bool, neverswitchonpickup, false, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Bool, neverswitchonpickup, false, CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (Float, movebob, 0.25f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, movebob, 0.25f, CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (Float, stillbob, 0.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Float, stillbob, 0.f, CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (Float, wbobspeed, 1.f, CVAR_USERINFO | CVAR_ARCHIVE);
CVAR (String, playerclass, "Fighter", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, playerclass, "Fighter", CVAR_USERINFO | CVAR_ARCHIVE);
enum enum
@ -83,6 +84,7 @@ enum
INFO_NeverSwitchOnPickup, INFO_NeverSwitchOnPickup,
INFO_MoveBob, INFO_MoveBob,
INFO_StillBob, INFO_StillBob,
INFO_WBobSpeed,
INFO_PlayerClass, INFO_PlayerClass,
INFO_ColorSet, INFO_ColorSet,
}; };
@ -878,69 +880,75 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update)
*stream += strlen (*((char **)stream)) + 1; *stream += strlen (*((char **)stream)) + 1;
} }
void WriteUserInfo(FArchive &arc, userinfo_t &info) void WriteUserInfo(FSerializer &arc, userinfo_t &info)
{ {
TMapIterator<FName, FBaseCVar *> it(info); if (arc.BeginObject("userinfo"))
TMap<FName, FBaseCVar *>::Pair *pair;
FName name;
UCVarValue val;
int i;
while (it.NextPair(pair))
{ {
name = pair->Key; TMapIterator<FName, FBaseCVar *> it(info);
arc << name; TMap<FName, FBaseCVar *>::Pair *pair;
switch (name.GetIndex()) FString name;
const char *string;
UCVarValue val;
int i;
while (it.NextPair(pair))
{ {
case NAME_Skin: name = pair->Key;
arc.WriteString(skins[info.GetSkin()].name); name.ToLower();
break; switch (pair->Key.GetIndex())
{
case NAME_Skin:
string = skins[info.GetSkin()].name;
break;
case NAME_PlayerClass: case NAME_PlayerClass:
i = info.GetPlayerClassNum(); i = info.GetPlayerClassNum();
arc.WriteString(i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars()); string = (i == -1 ? "Random" : PlayerClasses[i].Type->DisplayName.GetChars());
break; break;
default: default:
val = pair->Value->GetGenericRep(CVAR_String); val = pair->Value->GetGenericRep(CVAR_String);
arc.WriteString(val.String); string = val.String;
break; 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; FName name;
FBaseCVar **cvar; FBaseCVar **cvar;
char *str = NULL;
UCVarValue val; UCVarValue val;
const char *key;
const char *str;
info.Reset(); info.Reset();
skin = NULL; skin = NULL;
for (arc << name; name != NAME_None; arc << name) if (arc.BeginObject("userinfo"))
{ {
cvar = info.CheckKey(name); while ((key = arc.GetKey()))
arc << str;
if (cvar != NULL && *cvar != NULL)
{ {
switch (name) arc.StringPtr(nullptr, str);
name = key;
cvar = info.CheckKey(name);
if (cvar != NULL && *cvar != NULL)
{ {
case NAME_Team: info.TeamChanged(atoi(str)); break; switch (name)
case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known {
case NAME_PlayerClass: info.PlayerClassChanged(str); break; case NAME_Team: info.TeamChanged(atoi(str)); break;
default: case NAME_Skin: skin = str; break; // Caller must call SkinChanged() once current calss is known
val.String = str; case NAME_PlayerClass: info.PlayerClassChanged(str); break;
(*cvar)->SetGenericRep(val, CVAR_String); default:
break; val.String = str;
(*cvar)->SetGenericRep(val, CVAR_String);
break;
}
} }
} }
} arc.EndObject();
if (str != NULL)
{
delete[] str;
} }
} }

View file

@ -102,7 +102,8 @@ class APlayerPawn : public AActor
DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn) DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void PostBeginPlay(); virtual void PostBeginPlay();
virtual void Tick(); virtual void Tick();
@ -337,6 +338,10 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
{ {
return *static_cast<FFloatCVar *>(*CheckKey(NAME_StillBob)); return *static_cast<FFloatCVar *>(*CheckKey(NAME_StillBob));
} }
float GetWBobSpeed() const
{
return *static_cast<FFloatCVar *>(*CheckKey(NAME_WBobSpeed));
}
int GetPlayerClassNum() const int GetPlayerClassNum() const
{ {
return *static_cast<FIntCVar *>(*CheckKey(NAME_PlayerClass)); return *static_cast<FIntCVar *>(*CheckKey(NAME_PlayerClass));
@ -370,8 +375,8 @@ struct userinfo_t : TMap<FName,FBaseCVar *>
int ColorSetChanged(int setnum); int ColorSetChanged(int setnum);
}; };
void ReadUserInfo(FArchive &arc, userinfo_t &info, FString &skin); void ReadUserInfo(FSerializer &arc, userinfo_t &info, FString &skin);
void WriteUserInfo(FArchive &arc, userinfo_t &info); void WriteUserInfo(FSerializer &arc, userinfo_t &info);
// //
// Extended player object info: player_t // Extended player object info: player_t
@ -383,7 +388,7 @@ public:
~player_t(); ~player_t();
player_t &operator= (const player_t &p); 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 FixPointers (const DObject *obj, DObject *replacement);
size_t PropagateMark(); size_t PropagateMark();
@ -541,8 +546,6 @@ public:
// Bookkeeping on players - state. // Bookkeeping on players - state.
extern player_t players[MAXPLAYERS]; extern player_t players[MAXPLAYERS];
FArchive &operator<< (FArchive &arc, player_t *&p);
void P_CheckPlayerSprite(AActor *mo, int &spritenum, DVector2 &scale); void P_CheckPlayerSprite(AActor *mo, int &spritenum, DVector2 &scale);
inline void AActor::SetFriendPlayer(player_t *player) inline void AActor::SetFriendPlayer(player_t *player)

View file

@ -38,7 +38,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "farchive.h" #include "serializer.h"
char *ReadString (BYTE **stream) char *ReadString (BYTE **stream)
@ -287,27 +287,33 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream)
return int(*stream - start); 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]; // This used packed data with the old serializer but that's totally counterproductive when
BYTE *stream = bytes; // having a text format that is human-readable. So this compression has been undone here.
if (arc.IsStoring ()) // The few bytes of file size it saves are not worth the obfuscation.
if (arc.BeginObject(key))
{ {
BYTE len = PackUserCmd (&cmd, NULL, &stream); arc("buttons", cmd.buttons)
arc << len; ("pitch", cmd.pitch)
arc.Write (bytes, len); ("yaw", cmd.yaw)
} ("roll", cmd.roll)
else ("forwardmove", cmd.forwardmove)
{ ("sidemove", cmd.sidemove)
BYTE len; ("upmove", cmd.upmove)
arc << len; .EndObject();
arc.Read (bytes, len);
UnpackUserCmd (&cmd, NULL, &stream);
} }
return arc; return arc;
} }

View file

@ -72,10 +72,6 @@ struct usercmd_t
short upmove; short upmove;
}; };
class FArchive;
FArchive &operator<< (FArchive &arc, usercmd_t &cmd);
// When transmitted, the above message is preceded by a byte // When transmitted, the above message is preceded by a byte
// indicating which fields are actually present in the message. // indicating which fields are actually present in the message.
enum enum

View file

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

View file

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

View file

@ -47,7 +47,13 @@
#include "stats.h" #include "stats.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "dsectoreffect.h" #include "dsectoreffect.h"
#include "farchive.h" #include "serializer.h"
//==========================================================================
//
//
//
//==========================================================================
ClassReg DObject::RegistrationInfo = ClassReg DObject::RegistrationInfo =
{ {
@ -61,6 +67,12 @@ ClassReg DObject::RegistrationInfo =
}; };
_DECLARE_TI(DObject) _DECLARE_TI(DObject)
//==========================================================================
//
//
//
//==========================================================================
CCMD (dumpactors) CCMD (dumpactors)
{ {
const char *const filters[32] = const char *const filters[32] =
@ -95,6 +107,12 @@ CCMD (dumpactors)
} }
} }
//==========================================================================
//
//
//
//==========================================================================
CCMD (dumpclasses) CCMD (dumpclasses)
{ {
// This is by no means speed-optimized. But it's an informational console // 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); Printf ("%d classes shown, %d omitted\n", shown, omitted);
} }
//==========================================================================
//
//
//
//==========================================================================
void DObject::InPlaceConstructor (void *mem) void DObject::InPlaceConstructor (void *mem)
{ {
new ((EInPlace *)mem) DObject; new ((EInPlace *)mem) DObject;
@ -255,6 +279,12 @@ DObject::DObject (PClass *inClass)
GC::Root = this; GC::Root = this;
} }
//==========================================================================
//
//
//
//==========================================================================
DObject::~DObject () DObject::~DObject ()
{ {
if (!PClass::bShutdown) if (!PClass::bShutdown)
@ -304,11 +334,23 @@ DObject::~DObject ()
} }
} }
//==========================================================================
//
//
//
//==========================================================================
void DObject::Destroy () void DObject::Destroy ()
{ {
ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe; ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe;
} }
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::PropagateMark() size_t DObject::PropagateMark()
{ {
const PClass *info = GetClass(); const PClass *info = GetClass();
@ -330,6 +372,12 @@ size_t DObject::PropagateMark()
return 0; return 0;
} }
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld) size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
{ {
const PClass *info = GetClass(); const PClass *info = GetClass();
@ -352,6 +400,12 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
return changed; return changed;
} }
//==========================================================================
//
//
//
//==========================================================================
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
{ {
DObject *probe; DObject *probe;
@ -417,70 +471,41 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
return changed; return changed;
} }
void DObject::SerializeUserVars(FArchive &arc) //==========================================================================
//
//
//
//==========================================================================
void DObject::SerializeUserVars(FSerializer &arc)
{ {
PSymbolTable *symt; if (arc.isWriting())
FName varname;
DWORD count, j;
int *varloc = NULL;
symt = &GetClass()->Symbols;
if (arc.IsStoring())
{ {
// Write all fields that aren't serialized by native code. // Write all fields that aren't serialized by native code.
GetClass()->WriteValue(arc, this); GetClass()->WriteAllFields(arc, this);
}
else if (SaveVersion >= 4535)
{
GetClass()->ReadValue(arc, this);
} }
else else
{ // Old version that only deals with ints {
// Read user variables until 'None' is encountered. GetClass()->ReadAllFields(arc, this);
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;
}
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;
}
} }
} }
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; ObjectFlags |= OF_SerialSuccess;
} }

View file

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

View file

@ -39,7 +39,7 @@
#include "dobject.h" #include "dobject.h"
#include "i_system.h" #include "i_system.h"
#include "farchive.h" #include "serializer.h"
#include "actor.h" #include "actor.h"
#include "templates.h" #include "templates.h"
#include "autosegs.h" #include "autosegs.h"
@ -47,6 +47,7 @@
#include "a_pickups.h" #include "a_pickups.h"
#include "a_weaponpiece.h" #include "a_weaponpiece.h"
#include "d_player.h" #include "d_player.h"
#include "doomerrors.h"
#include "fragglescript/t_fs.h" #include "fragglescript/t_fs.h"
// MACROS ------------------------------------------------------------------ // 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"); 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"); assert(0 && "Cannot read value for this type");
SkipValue(ar);
return false; 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 // PType :: SetDefaultValue
@ -805,116 +714,41 @@ PInt::PInt(unsigned int size, bool unsign)
// //
// PInt :: WriteValue // 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; if (Size == 8 && Unsigned)
// 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)
{ {
bval = *(BYTE *)addr; // this is a special case that cannot be represented by an int64_t.
} uint64_t val = *(uint64_t*)addr;
else if (Unsigned) ar(key, val);
{
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);
} }
else 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 NumericValue val;
{
QWORD uval;
SQWORD sval;
};
BYTE tag;
union
{
BYTE val8;
WORD val16;
DWORD val32;
float single;
double dbl;
};
ar << tag; ar(key, val);
switch (tag) if (val.type == NumericValue::NM_invalid) return false; // not found or usable
{ if (val.type == NumericValue::NM_float) val.signedval = (int64_t)val.floatval;
case VAL_Zero: uval = 0; break;
case VAL_One: uval = 1; break; // No need to check the unsigned state here. Downcasting to smaller types will yield the same result for both.
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
}
switch (Size) switch (Size)
{ {
case 1: *(BYTE *)addr = (BYTE)uval; break; case 1:
case 2: *(WORD *)addr = (WORD)uval; break; *(uint8_t*)addr = (uint8_t)val.signedval;
case 4: *(DWORD *)addr = (DWORD)uval; break; break;
case 8: *(QWORD *)addr = uval; 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; 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 (Size == 8)
{ {
// If it can be written as single precision without information ar(key, *(double*)addr);
// 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;
}
} }
else else
{ {
singleprecision = *(float *)addr; ar(key, *(float*)addr);
} }
ar.WriteByte(VAL_Float32);
ar << singleprecision;
} }
//========================================================================== //==========================================================================
@ -1289,60 +1101,26 @@ 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; NumericValue val;
union
{
BYTE val8;
WORD val16;
DWORD val32;
QWORD val64;
fixed_t fix;
float single;
angle_t ang;
};
switch (tag) 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;
if (Size == 8)
{ {
case VAL_Zero: val = 0; break; *(double*)addr = val.floatval;
case VAL_One: val = 1; break; }
case VAL_Int8: ar << val8; val = (SBYTE)val8; break; else
case VAL_UInt8: ar << val8; val = val8; break; {
case VAL_Int16: ar << val16; val = (SWORD)val16; break; *(float*)addr = (float)val.floatval;
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; return true;
} }
bool PFloat::ReadValue(FArchive &ar, void *addr) const
{
BYTE tag;
ar << tag;
double val;
if (ReadValueDbl(ar, &val, tag))
{
if (Size == 4)
{
*(float *)addr = (float)val;
}
else
{
*(double *)addr = val;
}
return true;
}
return false;
}
//========================================================================== //==========================================================================
// //
// PFloat :: SetValue // PFloat :: SetValue
@ -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(key, *(FString*)addr);
ar.WriteString(*(const FString *)addr);
} }
//========================================================================== //==========================================================================
@ -1494,25 +1271,19 @@ 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; const char *cptr;
ar << tag; ar.StringPtr(key, cptr);
if (tag == VAL_String) if (cptr == nullptr)
{ {
ar << *(FString *)addr; return false;
}
else if (tag == VAL_Name)
{
const char *str = ar.ReadName();
*(FString *)addr = str;
} }
else else
{ {
SkipValue(ar, tag); *(FString*)addr = cptr;
return false; return true;
} }
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); const char *cptr = ((const FName*)addr)->GetChars();
ar.WriteName(((const FName *)addr)->GetChars()); ar.StringPtr(key, cptr);
} }
//========================================================================== //==========================================================================
@ -1586,26 +1357,19 @@ 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; const char *cptr;
ar << tag; ar.StringPtr(key, cptr);
if (tag == VAL_Name) if (cptr == nullptr)
{ {
*(FName *)addr = FName(ar.ReadName()); return false;
}
else if (tag == VAL_String)
{
FString str;
ar << str;
*(FName *)addr = FName(str);
} }
else else
{ {
SkipValue(ar, tag); *(FName*)addr = FName(cptr);
return false; return true;
} }
return true;
} }
/* PSound *****************************************************************/ /* 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); const char *cptr = *(const FSoundID *)addr;
ar.WriteName(*(const FSoundID *)addr); ar.StringPtr(key, cptr);
} }
//========================================================================== //==========================================================================
@ -1642,28 +1406,19 @@ 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; const char *cptr;
ar.StringPtr(key, cptr);
ar << tag; if (cptr == nullptr)
if (tag == VAL_Name)
{ {
const char *str = ar.ReadName(); return false;
*(FSoundID *)addr = FSoundID(str);
}
else if (tag == VAL_String)
{
FString str;
ar << str;
*(FSoundID *)addr = FSoundID(str);
} }
else else
{ {
SkipValue(ar, tag); *(FSoundID *)addr = FSoundID(cptr);
return false; return true;
} }
return true;
} }
/* PColor *****************************************************************/ /* 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(key, *(FState **)addr);
ar << *(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; bool res = false;
ar << tag; ::Serialize(ar, key, *(FState **)addr, nullptr, &res);
if (tag == VAL_State) return res;
{
ar << *(FState **)addr;
return true;
}
SkipValue(ar, tag);
return false;
} }
/* PPointer ***************************************************************/ /* 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))) if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{ {
ar.WriteByte(VAL_Object); ar(key, *(DObject **)addr);
ar << *(DObject **)addr;
} }
else 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; if (PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
ar << tag;
if (tag == VAL_Object && PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
{ {
ar << *(DObject **)addr; bool res = false;
return true; ::Serialize(ar, key, *(DObject **)addr, nullptr, &res);
return res;
} }
SkipValue(ar, tag);
return false; return false;
} }
@ -2098,15 +1843,17 @@ 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
{ {
ar.WriteByte(VAL_Array); if (ar.BeginArray(key))
ar.WriteCount(ElementCount);
const BYTE *addrb = (const BYTE *)addr;
for (unsigned i = 0; i < ElementCount; ++i)
{ {
ElementType->WriteValue(ar, addrb); const BYTE *addrb = (const BYTE *)addr;
addrb += ElementSize; for (unsigned i = 0; i < ElementCount; ++i)
{
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
{ {
bool readsomething = false; if (ar.BeginArray(key))
BYTE tag;
ar << tag;
if (tag == VAL_Array)
{ {
unsigned count = ar.ReadCount(); bool readsomething = false;
unsigned i; unsigned count = ar.ArraySize();
unsigned loop = MIN(count, ElementCount);
BYTE *addrb = (BYTE *)addr; 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; addrb += ElementSize;
} }
if (i < ElementCount) if (loop < count)
{ {
DPrintf(DMSG_WARNING, "Array on disk (%u) is bigger than in memory (%u)\n", DPrintf(DMSG_WARNING, "Array on disk (%u) is bigger than in memory (%u)\n",
count, ElementCount); count, ElementCount);
for (; i < ElementCount; ++i)
{
SkipValue(ar);
}
} }
ar.EndArray();
return readsomething; return readsomething;
} }
SkipValue(ar, tag);
return false; 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
{ {
ar.WriteByte(VAL_Struct); if (ar.BeginObject(key))
WriteFields(ar, addr, Fields); {
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; if (ar.BeginObject(key))
ar << tag;
if (tag == VAL_Struct)
{ {
return ReadFields(ar, addr); bool ret = ReadFields(ar, addr);
ar.EndObject();
return ret;
} }
SkipValue(ar, tag); return false;
return true;
} }
//========================================================================== //==========================================================================
@ -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) 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 // Skip fields with native serialization
if (!(field->Flags & VARF_Native)) if (!(field->Flags & VARF_Native))
{ {
ar.WriteName(field->SymbolName); field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset);
field->Type->WriteValue(ar, (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; bool readsomething = false;
const char *label = ar.ReadName(); bool foundsomething = false;
if (label == NULL) const char *label;
{ // If there is nothing to restore, we count it as success. while ((label = ar.GetKey()))
return true;
}
for (; label != NULL; label = ar.ReadName())
{ {
foundsomething = true;
const PSymbol *sym = Symbols.FindSymbol(FName(label, true), true); const PSymbol *sym = Symbols.FindSymbol(FName(label, true), true);
if (sym == NULL) if (sym == NULL)
{ {
DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n", DPrintf(DMSG_ERROR, "Cannot find field %s in %s\n",
label, TypeName.GetChars()); label, TypeName.GetChars());
SkipValue(ar);
} }
else if (!sym->IsKindOf(RUNTIME_CLASS(PField))) else if (!sym->IsKindOf(RUNTIME_CLASS(PField)))
{ {
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n", DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName.GetChars()); label, TypeName.GetChars());
SkipValue(ar);
} }
else 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); (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) 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- // a more-derived class has variables that shadow a less-
// derived class. Whether or not that is a language feature // derived class. Whether or not that is a language feature
// that will actually be allowed remains to be seen. // that will actually be allowed remains to be seen.
ar.UserWriteClass(const_cast<PClass *>(type)); FString key;
PStruct::WriteFields(ar, addr, type->Fields); key.Format("class:%s", type->TypeName.GetChars());
if (ar.BeginObject(key.GetChars()))
{
PStruct::WriteFields(ar, addr, type->Fields);
ar.EndObject();
}
break; 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); 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; if (ar.BeginObject(key))
ar << tag;
if (tag != VAL_Class)
{ {
SkipValue(ar, tag); bool ret = ReadAllFields(ar, addr);
ar.EndObject();
return ret;
}
return true;
}
bool PClass::ReadAllFields(FSerializer &ar, void *addr) const
{
bool readsomething = false;
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; return false;
} }
else while ((key = ar.GetKey()))
{ {
bool readsomething = false; if (strncmp(key, "class:", 6))
PClass *type; {
for (ar.UserReadClass(type); type != NULL; ar.UserReadClass(type)) // 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. // Only read it if the type is related to this one.
const PClass *parent; const PClass *parent;
@ -2800,19 +2571,27 @@ bool PClass::ReadValue(FArchive &ar, void *addr) const
break; break;
} }
} }
if (parent != NULL) if (parent != nullptr)
{ {
readsomething |= type->ReadFields(ar, addr); if (ar.BeginObject(nullptr))
{
readsomething |= type->ReadFields(ar, addr);
ar.EndObject();
}
} }
else else
{ {
DPrintf(DMSG_ERROR, "Unknown superclass %s of class %s\n", DPrintf(DMSG_ERROR, "Unknown superclass %s of class %s\n",
type->TypeName.GetChars(), TypeName.GetChars()); 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 // 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 // without completely breaking savegames, provided that the change isn't between
// totally unrelated types. // 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. // Returns true if the stored value was compatible. False otherwise.
// If the value was incompatible, then the memory at *addr is unchanged. // If the value was incompatible, then the memory at *addr is unchanged.
virtual bool ReadValue(FArchive &ar, void *addr) const; virtual bool ReadValue(FSerializer &ar, const char *key,void *addr) const;
// Skips over a value written with WriteValue
static void SkipValue(FArchive &ar);
static void SkipValue(FArchive &ar, int tag);
// Sets the default value for this type at (base + offset) // Sets the default value for this type at (base + offset)
// If the default value is binary 0, then this function doesn't need // If the default value is binary 0, then this function doesn't need
@ -354,8 +350,8 @@ class PInt : public PBasicType
public: public:
PInt(unsigned int size, bool unsign); PInt(unsigned int size, bool unsign);
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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, int val);
virtual void SetValue(void *addr, double val); virtual void SetValue(void *addr, double val);
@ -383,8 +379,8 @@ class PFloat : public PBasicType
public: public:
PFloat(unsigned int size); PFloat(unsigned int size);
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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, int val);
virtual void SetValue(void *addr, double val); virtual void SetValue(void *addr, double val);
@ -421,8 +417,8 @@ public:
virtual int GetRegType() const; virtual int GetRegType() const;
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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 SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL) const override;
void InitializeValue(void *addr, const void *def) const override; void InitializeValue(void *addr, const void *def) const override;
void DestroyValue(void *addr) const override; void DestroyValue(void *addr) const override;
@ -436,8 +432,8 @@ class PName : public PInt
public: public:
PName(); PName();
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
}; };
class PSound : public PInt class PSound : public PInt
@ -446,8 +442,8 @@ class PSound : public PInt
public: public:
PSound(); PSound();
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
}; };
class PColor : public PInt class PColor : public PInt
@ -465,8 +461,8 @@ class PStatePointer : public PBasicType
public: public:
PStatePointer(); PStatePointer();
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
virtual int GetStoreOp() const; virtual int GetStoreOp() const;
virtual int GetLoadOp() const; virtual int GetLoadOp() const;
@ -489,8 +485,8 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(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; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, void *addr) const override; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
protected: protected:
PPointer(); PPointer();
@ -559,8 +555,8 @@ public:
virtual bool IsMatch(intptr_t id1, intptr_t id2) const; virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(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; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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; void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) const override;
@ -622,12 +618,12 @@ public:
size_t PropagateMark(); size_t PropagateMark();
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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; void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) const override;
static void WriteFields(FArchive &ar, const void *addr, const TArray<PField *> &fields); static void WriteFields(FSerializer &ar, const void *addr, const TArray<PField *> &fields);
bool ReadFields(FArchive &ar, void *addr) const; bool ReadFields(FSerializer &ar, void *addr) const;
protected: protected:
PStruct(); PStruct();
}; };
@ -692,8 +688,10 @@ public:
typedef PClassClass MetaClass; typedef PClassClass MetaClass;
MetaClass *GetClass() const; MetaClass *GetClass() const;
void WriteValue(FArchive &ar, const void *addr) const override; void WriteValue(FSerializer &ar, const char *key,const void *addr) const override;
bool ReadValue(FArchive &ar, 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) {} virtual void DeriveData(PClass *newclass) {}
static void StaticInit(); static void StaticInit();

View file

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

View file

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

View file

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

View file

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

View file

@ -38,7 +38,7 @@
#include "statnums.h" #include "statnums.h"
#include "i_system.h" #include "i_system.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "farchive.h" #include "serializer.h"
#include "d_player.h" #include "d_player.h"
@ -103,102 +103,98 @@ bool FThinkerList::IsEmpty() const
return Sentinel == NULL || Sentinel->NextThinker == NULL; return Sentinel == NULL || Sentinel->NextThinker == NULL;
} }
void DThinker::SaveList(FArchive &arc, DThinker *node) void DThinker::SaveList(FSerializer &arc, DThinker *node)
{ {
if (node != NULL) if (node != NULL)
{ {
while (!(node->ObjectFlags & OF_Sentinel)) while (!(node->ObjectFlags & OF_Sentinel))
{ {
assert(node->NextThinker != NULL && !(node->NextThinker->ObjectFlags & OF_EuthanizeMe)); assert(node->NextThinker != NULL && !(node->NextThinker->ObjectFlags & OF_EuthanizeMe));
arc << node; ::Serialize<DThinker>(arc, nullptr, node, nullptr);
node = node->NextThinker; node = node->NextThinker;
} }
} }
} }
void DThinker::SerializeAll(FArchive &arc, bool hubLoad) //==========================================================================
//
//
//
//==========================================================================
void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad)
{ {
DThinker *thinker; //DThinker *thinker;
BYTE stat; //BYTE stat;
int statcount; //int statcount;
int i; int i;
// Save lists of thinkers, but not by storing the first one and letting if (arc.isWriting())
// 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())
{ {
for (statcount = i = 0; i <= MAX_STATNUM; i++) arc.BeginArray("thinkers");
{
statcount += (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty());
}
arc << statcount;
for (i = 0; i <= MAX_STATNUM; i++) for (i = 0; i <= MAX_STATNUM; i++)
{ {
if (!Thinkers[i].IsEmpty() || !FreshThinkers[i].IsEmpty()) arc.BeginArray(nullptr);
{ SaveList(arc, Thinkers[i].GetHead());
stat = i; SaveList(arc, FreshThinkers[i].GetHead());
arc << stat; arc.EndArray();
SaveList(arc, Thinkers[i].GetHead());
SaveList(arc, FreshThinkers[i].GetHead());
thinker = NULL;
arc << thinker; // Save a final NULL for this list
}
} }
arc.EndArray();
} }
else else
{ {
// Prevent the constructor from inserting thinkers into a list. if (arc.BeginArray("thinkers"))
bSerialOverride = true;
try
{ {
arc << statcount; for (i = 0; i <= MAX_STATNUM; i++)
while (statcount > 0)
{ {
arc << stat << thinker; if (arc.BeginArray(nullptr))
while (thinker != NULL)
{ {
// This may be a player stored in their ancillary list. Remove int size = arc.ArraySize();
// them first before inserting them into the new list. for (int j = 0; j < size; j++)
if (thinker->NextThinker != NULL)
{ {
thinker->Remove(); 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 != nullptr)
{
thinker->Remove();
}
// Thinkers with the OF_JustSpawned flag set go in the FreshThinkers
// list. Anything else goes in the regular Thinkers list.
if (thinker->ObjectFlags & OF_EuthanizeMe)
{
// This thinker was destroyed during the loading process. Do
// not link it into any list.
}
else if (thinker->ObjectFlags & OF_JustSpawned)
{
FreshThinkers[i].AddTail(thinker);
thinker->PostSerialize();
}
else
{
Thinkers[i].AddTail(thinker);
thinker->PostSerialize();
}
}
} }
// Thinkers with the OF_JustSpawned flag set go in the FreshThinkers arc.EndArray();
// list. Anything else goes in the regular Thinkers list.
if (thinker->ObjectFlags & OF_EuthanizeMe)
{
// This thinker was destroyed during the loading process. Do
// not link it in to any list.
}
else if (thinker->ObjectFlags & OF_JustSpawned)
{
FreshThinkers[stat].AddTail(thinker);
}
else
{
Thinkers[stat].AddTail(thinker);
}
arc << thinker;
} }
statcount--;
} }
arc.EndArray();
} }
catch (class CDoomError &)
{
bSerialOverride = false;
DestroyAllThinkers();
throw;
}
bSerialOverride = false;
} }
} }
//==========================================================================
//
//
//
//==========================================================================
DThinker::DThinker (int statnum) throw() DThinker::DThinker (int statnum) throw()
{ {
NextThinker = NULL; NextThinker = NULL;
@ -261,6 +257,10 @@ void DThinker::PostBeginPlay ()
{ {
} }
void DThinker::PostSerialize()
{
}
DThinker *DThinker::FirstThinker (int statnum) DThinker *DThinker::FirstThinker (int statnum)
{ {
DThinker *node; DThinker *node;
@ -332,24 +332,6 @@ void DThinker::DestroyAllThinkers ()
GC::FullGC(); 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) void DThinker::DestroyThinkersInList (FThinkerList &list)
{ {
if (list.Sentinel != NULL) 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 () void DThinker::RunThinkers ()
{ {
int i, count; int i, count;
@ -473,8 +422,12 @@ void DThinker::Tick ()
size_t DThinker::PropagateMark() size_t DThinker::PropagateMark()
{ {
assert(NextThinker != NULL && !(NextThinker->ObjectFlags & OF_EuthanizeMe)); // Do not choke on partially initialized objects (as happens when loading a savegame fails)
assert(PrevThinker != NULL && !(PrevThinker->ObjectFlags & OF_EuthanizeMe)); if (NextThinker != nullptr || PrevThinker != nullptr)
{
assert(NextThinker != nullptr && !(NextThinker->ObjectFlags & OF_EuthanizeMe));
assert(PrevThinker != nullptr && !(PrevThinker->ObjectFlags & OF_EuthanizeMe));
}
GC::Mark(NextThinker); GC::Mark(NextThinker);
GC::Mark(PrevThinker); GC::Mark(PrevThinker);
return Super::PropagateMark(); return Super::PropagateMark();

View file

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

@ -527,7 +527,7 @@ long MemoryReader::Seek (long offset, int origin)
break; break;
} }
FilePos=clamp<long>(offset,0,Length-1); FilePos=clamp<long>(offset,0,Length);
return 0; return 0;
} }
@ -583,7 +583,7 @@ long MemoryArrayReader::Seek (long offset, int origin)
break; break;
} }
FilePos=clamp<long>(offset,0,Length-1); FilePos=clamp<long>(offset,0,Length);
return 0; return 0;
} }
@ -600,3 +600,58 @@ char *MemoryArrayReader::Gets(char *strbuf, int len)
{ {
return GetsFromBuffer((char*)&buf[0], strbuf, 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 #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_palette.h"
#include "v_font.h" #include "v_font.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "farchive.h" #include "serializer.h"
#include "p_setup.h" #include "p_setup.h"
#include "p_spec.h" #include "p_spec.h"
#include "r_utility.h" #include "r_utility.h"
@ -1780,7 +1780,7 @@ class DLightLevel : public DLighting
public: public:
DLightLevel(sector_t * s,int destlevel,int speed); DLightLevel(sector_t * s,int destlevel,int speed);
void Serialize (FArchive &arc); void Serialize(FSerializer &arc);
void Tick (); void Tick ();
void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; } void Destroy() { Super::Destroy(); m_Sector->lightingdata=NULL; }
}; };
@ -1789,11 +1789,11 @@ public:
IMPLEMENT_CLASS (DLightLevel) IMPLEMENT_CLASS (DLightLevel)
void DLightLevel::Serialize (FArchive &arc) void DLightLevel::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << destlevel << speed; arc("destlevel", destlevel)
if (arc.IsLoading()) m_Sector->lightingdata=this; ("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() void FParser::SF_NewHUPic()
{ {
if (CheckArgs(3)) // disabled because it was never used and never tested
{
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]));
}
} }
void FParser::SF_DeleteHUPic() void FParser::SF_DeleteHUPic()
{ {
if (CheckArgs(1)) // disabled because it was never used and never tested
{
if (HU_DeleteFSPic(intvalue(t_argv[0])) == -1)
script_error("deletehupic: Invalid sfpic handle: %i\n", intvalue(t_argv[0]));
}
} }
void FParser::SF_ModifyHUPic() void FParser::SF_ModifyHUPic()
{ {
if (t_argc != 4) // disabled because it was never used and never tested
{
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;
} }
void FParser::SF_SetHUPicDisplay() void FParser::SF_SetHUPicDisplay()
{ {
if (t_argc != 2) // disabled because it was never used and never tested
{
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]));
} }

View file

@ -56,7 +56,7 @@
#include "t_script.h" #include "t_script.h"
#include "i_system.h" #include "i_system.h"
#include "w_wad.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); Super::Serialize(arc);
ar << type << start_index << end_index << loop_index << next; 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 "i_system.h"
#include "doomerrors.h" #include "doomerrors.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h" #include "serializer.h"
//========================================================================== //==========================================================================
// //
@ -162,6 +162,19 @@ DFsScript::DFsScript()
lastiftrue = false; 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); Super::Serialize(arc);
// don't save a reference to the global script // 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; arc("data", data)
for(int i=0; i< SECTIONSLOTS; i++) arc << sections[i]; ("scriptnum", scriptnum)
for(int i=0; i< VARIABLESLOTS; i++) arc << variables[i]; ("len", len)
for(int i=0; i< MAXSCRIPTS; i++) arc << children[i]; ("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); Super::Serialize(arc);
arc("script", script)
arc << script << save_point << wait_type << wait_data << prev << next << trigger; ("save_point", save_point)
for(int i=0; i< VARIABLESLOTS; i++) arc << variables[i]; ("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); 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 GetValue(svalue_t &result);
void SetValue(const svalue_t &newvalue); void SetValue(const svalue_t &newvalue);
void Serialize(FArchive &ar); void Serialize(FSerializer &ar);
}; };
//========================================================================== //==========================================================================
@ -238,7 +238,7 @@ public:
next = NULL; next = NULL;
} }
void Serialize(FArchive &ar); void Serialize(FSerializer &ar);
}; };
@ -336,8 +336,9 @@ public:
// true or false // true or false
DFsScript(); DFsScript();
~DFsScript();
void Destroy(); void Destroy();
void Serialize(FArchive &ar); void Serialize(FSerializer &ar);
DFsVariable *NewVariable(const char *name, int vtype); DFsVariable *NewVariable(const char *name, int vtype);
void NewFunction(const char *name, void (FParser::*handler)()); void NewFunction(const char *name, void (FParser::*handler)());
@ -652,7 +653,7 @@ class DRunningScript : public DObject
public: public:
DRunningScript(AActor *trigger=NULL, DFsScript *owner = NULL, int index = 0) ; DRunningScript(AActor *trigger=NULL, DFsScript *owner = NULL, int index = 0) ;
void Destroy(); void Destroy();
void Serialize(FArchive &arc); void Serialize(FSerializer &arc);
TObjPtr<DFsScript> script; TObjPtr<DFsScript> script;
@ -689,7 +690,7 @@ public:
void Destroy(); void Destroy();
void Serialize(FArchive & arc); void Serialize(FSerializer & arc);
void Tick(); void Tick();
size_t PropagateMark(); size_t PropagateMark();
size_t PointerSubstitution (DObject *old, DObject *notOld); size_t PointerSubstitution (DObject *old, DObject *notOld);

View file

@ -54,7 +54,7 @@
#include "t_script.h" #include "t_script.h"
#include "a_pickups.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); 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

@ -47,7 +47,7 @@ static void BrainishExplosion (const DVector3 &pos)
boom->SetState (state); boom->SetState (state);
} }
boom->effects = 0; boom->effects = 0;
boom->Damage = NULL; // disables collision detection which is not wanted here boom->SetDamage(0); // disables collision detection which is not wanted here
boom->tics -= pr_brainscream() & 7; boom->tics -= pr_brainscream() & 7;
if (boom->tics < 1) if (boom->tics < 1)
boom->tics = 1; boom->tics = 1;
@ -120,7 +120,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
bool isdefault = false; bool isdefault = false;
// shoot a cube at current target // 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) if (targ != NULL)
{ {

View file

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

View file

@ -14,10 +14,10 @@
#include "a_specialspot.h" #include "a_specialspot.h"
#include "templates.h" #include "templates.h"
#include "m_bbox.h" #include "m_bbox.h"
#include "farchive.h"
#include "portal.h" #include "portal.h"
#include "d_player.h" #include "d_player.h"
#include "p_maputl.h" #include "p_maputl.h"
#include "serializer.h"
#include "g_shared/a_pickups.h" #include "g_shared/a_pickups.h"
// Include all the other Doom stuff here to reduce compile time // 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) IMPLEMENT_CLASS (AScriptedMarine)
void AScriptedMarine::Serialize (FArchive &arc) void AScriptedMarine::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
if (arc.IsStoring ()) auto def = (AScriptedMarine*)GetDefault();
{
arc.WriteSprite (SpriteOverride); arc.Sprite("spriteoverride", SpriteOverride, &def->SpriteOverride)
} ("currentweapon", CurrentWeapon, def->CurrentWeapon);
else
{
SpriteOverride = arc.ReadSprite ();
}
arc << CurrentWeapon;
} }
void AScriptedMarine::Activate (AActor *activator) void AScriptedMarine::Activate (AActor *activator)

View file

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

View file

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

View file

@ -148,7 +148,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState(); DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return; 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; if (spot == NULL) return;
prev = actor->Pos(); prev = actor->Pos();

View file

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

View file

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

View file

@ -115,7 +115,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
fire->target = baseFire->target; fire->target = baseFire->target;
fire->Angles.Yaw = baseFire->Angles.Yaw; fire->Angles.Yaw = baseFire->Angles.Yaw;
fire->Vel = baseFire->Vel; fire->Vel = baseFire->Vel;
fire->Damage = NULL; fire->SetDamage(0);
fire->health = (i+1) * 2; fire->health = (i+1) * 2;
P_CheckMissileSpawn (fire, self->radius); P_CheckMissileSpawn (fire, self->radius);
} }
@ -205,7 +205,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichFireGrow)
self->AddZ(9.); self->AddZ(9.);
if (self->health == 0) if (self->health == 0)
{ {
self->Damage = self->GetDefault()->Damage; self->RestoreDamage();
self->SetState (self->FindState("NoGrow")); self->SetState (self->FindState("NoGrow"));
} }
return 0; return 0;

View file

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

View file

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

View file

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

View file

@ -340,7 +340,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap)
{ {
mo->SetState (mo->FindState (NAME_Death)); mo->SetState (mo->FindState (NAME_Death));
mo->Vel.Z = 40; mo->Vel.Z = 40;
mo->Damage = NULL; mo->SetDamage(0);
} }
return 0; return 0;
} }

View file

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

View file

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

View file

@ -43,7 +43,7 @@
#include "m_png.h" #include "m_png.h"
#include "gstrings.h" #include "gstrings.h"
#include "wi_stuff.h" #include "wi_stuff.h"
#include "farchive.h" #include "serializer.h"
//========================================================================== //==========================================================================
@ -54,7 +54,7 @@
struct FHubInfo struct FHubInfo
{ {
int finished_ep; int levelnum;
int maxkills; int maxkills;
int maxitems; int maxitems;
@ -65,7 +65,7 @@ struct FHubInfo
FHubInfo &operator=(const wbstartstruct_t &wbs) FHubInfo &operator=(const wbstartstruct_t &wbs)
{ {
finished_ep = wbs.finished_ep; levelnum = wbs.finished_ep;
maxkills = wbs.maxkills; maxkills = wbs.maxkills;
maxsecret= wbs.maxsecret; maxsecret= wbs.maxsecret;
maxitems = wbs.maxitems; maxitems = wbs.maxitems;
@ -80,54 +80,54 @@ static TArray<FHubInfo> hubdata;
void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs) void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
{ {
unsigned int i,j; unsigned int i, j;
if (cluster->flags & CLUSTER_HUB) if (cluster->flags & CLUSTER_HUB)
{ {
for(i=0;i<hubdata.Size();i++) for (i = 0; i < hubdata.Size(); i++)
{ {
if (hubdata[i].finished_ep==level.levelnum) if (hubdata[i].levelnum == level.levelnum)
{ {
hubdata[i]=*wbs; hubdata[i] = *wbs;
break; break;
} }
} }
if (i==hubdata.Size()) if (i == hubdata.Size())
{ {
hubdata[hubdata.Reserve(1)] = *wbs; hubdata[hubdata.Reserve(1)] = *wbs;
} }
hubdata[i].finished_ep=level.levelnum; hubdata[i].levelnum = level.levelnum;
if (!multiplayer && !deathmatch) if (!multiplayer && !deathmatch)
{ {
// The player counters don't work in hubs // The player counters don't work in hubs
hubdata[i].plyr[0].skills=level.killed_monsters; hubdata[i].plyr[0].skills = level.killed_monsters;
hubdata[i].plyr[0].sitems=level.found_items; hubdata[i].plyr[0].sitems = level.found_items;
hubdata[i].plyr[0].ssecret=level.found_secrets; hubdata[i].plyr[0].ssecret = level.found_secrets;
} }
if (mode!=FINISH_SameHub) if (mode != FINISH_SameHub)
{ {
wbs->maxkills=wbs->maxitems=wbs->maxsecret=0; wbs->maxkills = wbs->maxitems = wbs->maxsecret = 0;
for(i=0;i<MAXPLAYERS;i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
wbs->plyr[i].sitems=wbs->plyr[i].skills=wbs->plyr[i].ssecret=0; wbs->plyr[i].sitems = wbs->plyr[i].skills = wbs->plyr[i].ssecret = 0;
} }
for(i=0;i<hubdata.Size();i++) for (i = 0; i < hubdata.Size(); i++)
{ {
wbs->maxkills += hubdata[i].maxkills; wbs->maxkills += hubdata[i].maxkills;
wbs->maxitems += hubdata[i].maxitems; wbs->maxitems += hubdata[i].maxitems;
wbs->maxsecret += hubdata[i].maxsecret; wbs->maxsecret += hubdata[i].maxsecret;
for(j=0;j<MAXPLAYERS;j++) for (j = 0; j < MAXPLAYERS; j++)
{ {
wbs->plyr[j].sitems += hubdata[i].plyr[j].sitems; wbs->plyr[j].sitems += hubdata[i].plyr[j].sitems;
wbs->plyr[j].skills += hubdata[i].plyr[j].skills; wbs->plyr[j].skills += hubdata[i].plyr[j].skills;
wbs->plyr[j].ssecret += hubdata[i].plyr[j].ssecret; wbs->plyr[j].ssecret += hubdata[i].plyr[j].ssecret;
} }
} }
if (cluster->ClusterName.IsNotEmpty()) if (cluster->ClusterName.IsNotEmpty())
{ {
if (cluster->flags & CLUSTER_LOOKUPNAME) if (cluster->flags & CLUSTER_LOOKUPNAME)
{ {
@ -140,7 +140,7 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
} }
} }
} }
if (mode!=FINISH_SameHub) hubdata.Clear(); if (mode != FINISH_SameHub) hubdata.Clear();
} }
//========================================================================== //==========================================================================
@ -148,39 +148,41 @@ void G_LeavingHub(int mode, cluster_info_t * cluster, wbstartstruct_t * wbs)
// Serialize intermission info for hubs // 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(); if (arc.BeginObject(key))
arc << i;
if (i>0)
{ {
if (arc.IsStoring()) arc.Write(&hubdata[0], i * sizeof(FHubInfo)); arc("in", h.in)
else ("kills", h.skills)
{ ("items", h.sitems)
hubdata.Resize(i); ("secrets", h.ssecret)
arc.Read(&hubdata[0], i * sizeof(FHubInfo)); ("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); if (arc.BeginObject(key))
G_SerializeHub(arc); {
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; arc("hubinfo", hubdata);
if ((chunklen = M_FindPNGChunk (png, HUBS_ID)) != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), HUBS_ID, chunklen);
G_SerializeHub(arc);
}
} }
void G_ClearHubInfo() void G_ClearHubInfo()

View file

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

View file

@ -81,10 +81,10 @@
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "a_strifeglobal.h" #include "a_strifeglobal.h"
#include "r_data/colormaps.h" #include "r_data/colormaps.h"
#include "farchive.h"
#include "r_renderer.h" #include "r_renderer.h"
#include "r_utility.h" #include "r_utility.h"
#include "p_spec.h" #include "p_spec.h"
#include "serializer.h"
#include "gi.h" #include "gi.h"
@ -93,7 +93,7 @@
void STAT_StartNewGame(const char *lev); void STAT_StartNewGame(const char *lev);
void STAT_ChangeLevel(const char *newl); void STAT_ChangeLevel(const char *newl);
EXTERN_CVAR(Bool, save_formatted)
EXTERN_CVAR (Float, sv_gravity) EXTERN_CVAR (Float, sv_gravity)
EXTERN_CVAR (Float, sv_aircontrol) EXTERN_CVAR (Float, sv_aircontrol)
EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, disableautosave)
@ -822,7 +822,7 @@ void G_DoCompleted (void)
} }
else else
{ // Make sure we don't have a snapshot lying around from before. { // Make sure we don't have a snapshot lying around from before.
level.info->ClearSnapshot(); level.info->Snapshot.Clean();
} }
} }
else else
@ -1291,6 +1291,9 @@ void G_FinishTravel ()
if (level.FromSnapshot) if (level.FromSnapshot)
{ {
FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true); FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true);
// [Nash] run REOPEN scripts upon map re-entry
FBehavior::StaticStartTypedScripts(SCRIPT_Reopen, NULL, false);
} }
} }
@ -1474,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 // Archives the current level
@ -1611,19 +1485,18 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
void G_SnapshotLevel () void G_SnapshotLevel ()
{ {
if (level.info->snapshot) level.info->Snapshot.Clean();
delete level.info->snapshot;
if (level.info->isValid()) if (level.info->isValid())
{ {
level.info->snapshotVer = SAVEVER; FSerializer arc;
level.info->snapshot = new FCompressedMemFile;
level.info->snapshot->Open ();
FArchive arc (*level.info->snapshot); if (arc.OpenWriter(save_formatted))
{
SaveVersion = SAVEVER; SaveVersion = SAVEVER;
G_SerializeLevel (arc, false); G_SerializeLevel(arc, false);
level.info->Snapshot = arc.GetCompressedOutput();
}
} }
} }
@ -1636,18 +1509,15 @@ void G_SnapshotLevel ()
void G_UnSnapshotLevel (bool hubLoad) void G_UnSnapshotLevel (bool hubLoad)
{ {
if (level.info->snapshot == NULL) if (level.info->Snapshot.mBuffer == nullptr)
return; return;
if (level.info->isValid()) if (level.info->isValid())
{ {
SaveVersion = level.info->snapshotVer; FSerializer arc;
level.info->snapshot->Reopen (); if (!arc.OpenReader(&level.info->Snapshot)) return;
FArchive arc (*level.info->snapshot);
if (hubLoad)
arc.SetHubTravel ();
G_SerializeLevel (arc, hubLoad); G_SerializeLevel (arc, hubLoad);
arc.Close ();
level.FromSnapshot = true; level.FromSnapshot = true;
TThinkerIterator<APlayerPawn> it; TThinkerIterator<APlayerPawn> it;
@ -1677,7 +1547,7 @@ void G_UnSnapshotLevel (bool hubLoad)
} }
} }
// No reason to keep the snapshot around once the level's been entered. // No reason to keep the snapshot around once the level's been entered.
level.info->ClearSnapshot(); level.info->Snapshot.Clean();
if (hubLoad) if (hubLoad)
{ {
// Unlock ACS global strings that were locked when the snapshot was made. // Unlock ACS global strings that were locked when the snapshot was made.
@ -1690,10 +1560,28 @@ void G_UnSnapshotLevel (bool hubLoad)
// //
//========================================================================== //==========================================================================
static void writeSnapShot (FArchive &arc, level_info_t *i) void G_WriteSnapshots(TArray<FString> &filenames, TArray<FCompressedBuffer> &buffers)
{ {
arc << i->snapshotVer << i->MapName; unsigned int i;
i->snapshot->Serialize (arc); FString filename;
for (i = 0; i < wadlevelinfos.Size(); i++)
{
if (wadlevelinfos[i].Snapshot.mCompressedSize > 0)
{
filename.Format("%s.map.json", wadlevelinfos[i].MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(wadlevelinfos[i].Snapshot);
}
}
if (TheDefaultLevelInfo.Snapshot.mCompressedSize > 0)
{
filename.Format("%s.mapd.json", TheDefaultLevelInfo.MapName.GetChars());
filename.ToLower();
filenames.Push(filename);
buffers.Push(TheDefaultLevelInfo.Snapshot);
}
} }
//========================================================================== //==========================================================================
@ -1701,70 +1589,39 @@ static void writeSnapShot (FArchive &arc, level_info_t *i)
// //
//========================================================================== //==========================================================================
void G_WriteSnapshots (FILE *file) void G_WriteVisited(FSerializer &arc)
{ {
unsigned int i; if (arc.BeginArray("visited"))
for (i = 0; i < wadlevelinfos.Size(); i++)
{ {
if (wadlevelinfos[i].snapshot) // Write out which levels have been visited
for (auto & wi : wadlevelinfos)
{ {
FPNGChunkArchive arc (file, SNAP_ID); if (wi.flags & LEVEL_VISITED)
writeSnapShot (arc, (level_info_t *)&wadlevelinfos[i]);
}
}
if (TheDefaultLevelInfo.snapshot != NULL)
{
FPNGChunkArchive arc (file, DSNP_ID);
writeSnapShot(arc, &TheDefaultLevelInfo);
}
FPNGChunkArchive *arc = NULL;
// Write out which levels have been visited
for (i = 0; i < wadlevelinfos.Size(); ++i)
{
if (wadlevelinfos[i].flags & LEVEL_VISITED)
{
if (arc == NULL)
{ {
arc = new FPNGChunkArchive (file, VIST_ID); arc.AddString(nullptr, wi.MapName);
} }
(*arc) << wadlevelinfos[i].MapName;
} }
} arc.EndArray();
if (arc != NULL)
{
FString empty = "";
(*arc) << empty;
delete arc;
} }
// Store player classes to be used when spawning a random class // Store player classes to be used when spawning a random class
if (multiplayer) if (multiplayer)
{ {
FPNGChunkArchive arc2 (file, RCLS_ID); arc.Array("randomclasses", SinglePlayerClass, MAXPLAYERS);
for (i = 0; i < MAXPLAYERS; ++i)
{
SBYTE cnum = SinglePlayerClass[i];
arc2 << cnum;
}
} }
// Store player classes that are currently in use if (arc.BeginObject("playerclasses"))
FPNGChunkArchive arc3 (file, PCLS_ID);
for (i = 0; i < MAXPLAYERS; ++i)
{ {
BYTE pnum; for (int i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i])
{ {
pnum = i; if (playeringame[i])
arc3 << pnum; {
arc3.UserWriteClass (players[i].cls); FString key;
key.Format("%d", i);
arc(key, players[i].cls);
}
} }
pnum = 255; arc.EndObject();
arc3 << pnum;
} }
} }
@ -1773,95 +1630,89 @@ void G_WriteSnapshots (FILE *file)
// //
//========================================================================== //==========================================================================
void G_ReadSnapshots (PNGHandle *png) void G_ReadSnapshots(FResourceFile *resf)
{ {
DWORD chunkLen;
FString MapName; FString MapName;
level_info_t *i; level_info_t *i;
G_ClearSnapshots (); G_ClearSnapshots();
chunkLen = (DWORD)M_FindPNGChunk (png, SNAP_ID); for (unsigned j = 0; j < resf->LumpCount(); j++)
while (chunkLen != 0)
{ {
FPNGChunkArchive arc (png->File->GetFile(), SNAP_ID, chunkLen); FResourceLump * resl = resf->GetLump(j);
DWORD snapver; if (resl != nullptr)
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)
{
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)
{
FPNGChunkArchive arc (png->File->GetFile(), VIST_ID, chunkLen);
while (arc << MapName, MapName.Len() > 0)
{ {
i = FindLevelInfo(MapName); auto ptr = strstr(resl->FullName, ".map.json");
i->flags |= LEVEL_VISITED; if (ptr != nullptr)
{
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
i = FindLevelInfo(mapname);
if (i != nullptr)
{
i->Snapshot = resl->GetRawData();
}
}
else
{
auto ptr = strstr(resl->FullName, ".mapd.json");
if (ptr != nullptr)
{
ptrdiff_t maplen = ptr - resl->FullName.GetChars();
FString mapname(resl->FullName.GetChars(), (size_t)maplen);
TheDefaultLevelInfo.Snapshot = resl->GetRawData();
}
}
} }
} }
chunkLen = (DWORD)M_FindPNGChunk (png, RCLS_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), PCLS_ID, chunkLen);
SBYTE cnum;
for (DWORD j = 0; j < chunkLen; ++j)
{
arc << cnum;
SinglePlayerClass[j] = cnum;
}
}
chunkLen = (DWORD)M_FindPNGChunk (png, PCLS_ID);
if (chunkLen != 0)
{
FPNGChunkArchive arc (png->File->GetFile(), RCLS_ID, chunkLen);
BYTE pnum;
arc << pnum;
while (pnum != 255)
{
arc.UserReadClass (players[pnum].cls);
arc << pnum;
}
}
png->File->ResetFilePtr();
} }
//==========================================================================
//
//
//==========================================================================
void G_ReadVisited(FSerializer &arc)
{
if (arc.BeginArray("visited"))
{
for (int s = arc.ArraySize(); s > 0; s--)
{
FString str;
arc(nullptr, str);
auto i = FindLevelInfo(str);
if (i != nullptr) i->flags |= LEVEL_VISITED;
}
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) CCMD(listsnapshots)
{ {
for (unsigned i = 0; i < wadlevelinfos.Size(); ++i) for (unsigned i = 0; i < wadlevelinfos.Size(); ++i)
{ {
FCompressedMemFile *snapshot = wadlevelinfos[i].snapshot; FCompressedBuffer *snapshot = &wadlevelinfos[i].Snapshot;
if (snapshot != NULL) if (snapshot->mBuffer != nullptr)
{ {
unsigned int comp, uncomp; Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), snapshot->mCompressedSize, snapshot->mSize);
snapshot->GetSizes(comp, uncomp);
Printf("%s (%u -> %u bytes)\n", wadlevelinfos[i].MapName.GetChars(), comp, uncomp);
} }
} }
} }
@ -1871,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;
}
//========================================================================== // only write this stuff if needed
// for (auto &wi : wadlevelinfos)
//
//==========================================================================
void P_WriteACSDefereds (FILE *file)
{
FPNGChunkArchive *arc = NULL;
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++)
{ {
if (wadlevelinfos[i].defered) if (wi.deferred.Size() > 0)
{ {
if (arc == NULL) found = true;
break;
}
}
if (found && arc.BeginObject("deferred"))
{
for (auto &wi : wadlevelinfos)
{
if (wi.deferred.Size() > 0)
{ {
arc = new FPNGChunkArchive (file, ACSD_ID); if (wi.deferred.Size() > 0)
{
arc(wi.MapName, wi.deferred);
}
} }
writeDefereds (*arc, (level_info_t *)&wadlevelinfos[i]);
} }
} arc.EndObject();
if (arc != NULL)
{
// Signal end of defereds
FString empty = "";
(*arc) << empty;
delete arc;
} }
} }
@ -1911,28 +1756,27 @@ void P_WriteACSDefereds (FILE *file)
// //
//========================================================================== //==========================================================================
void P_ReadACSDefereds (PNGHandle *png) void P_ReadACSDefereds (FSerializer &arc)
{ {
FString MapName; FString MapName;
size_t chunklen;
P_RemoveDefereds (); 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) 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();
} }
@ -1944,9 +1788,9 @@ void P_ReadACSDefereds (PNGHandle *png)
void FLevelLocals::Tick () void FLevelLocals::Tick ()
{ {
// Reset carry sectors // 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());
} }
} }
@ -1961,10 +1805,10 @@ void FLevelLocals::AddScroller (int secnum)
{ {
return; return;
} }
if (Scrolls == NULL) if (Scrolls.Size() == 0)
{ {
Scrolls = new FSectorScrollValues[numsectors]; Scrolls.Resize(numsectors);
memset (Scrolls, 0, sizeof(*Scrolls)*numsectors); memset (&Scrolls[0], 0, sizeof(Scrolls[0])*numsectors);
} }
} }

View file

@ -38,7 +38,9 @@
#include "doomdef.h" #include "doomdef.h"
#include "sc_man.h" #include "sc_man.h"
#include "s_sound.h" #include "s_sound.h"
#include "p_acs.h"
#include "textures/textures.h" #include "textures/textures.h"
#include "resourcefiles/file_zip.h"
struct level_info_t; struct level_info_t;
struct cluster_info_t; struct cluster_info_t;
@ -223,8 +225,6 @@ enum ELevelFlags : unsigned int
}; };
struct acsdefered_t;
struct FSpecialAction struct FSpecialAction
{ {
FName Type; // this is initialized before the actors... 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! int Args[5]; // must allow 16 bit tags for 666 & 667!
}; };
class FCompressedMemFile;
class DScroller; class DScroller;
class FScanner; class FScanner;
@ -295,9 +294,8 @@ struct level_info_t
FString LevelName; FString LevelName;
SBYTE WallVertLight, WallHorizLight; SBYTE WallVertLight, WallHorizLight;
int musicorder; int musicorder;
FCompressedMemFile *snapshot; FCompressedBuffer Snapshot;
DWORD snapshotVer; TArray<acsdefered_t> deferred;
struct acsdefered_t *defered;
float skyspeed1; float skyspeed1;
float skyspeed2; float skyspeed2;
DWORD fadeto; DWORD fadeto;
@ -346,14 +344,16 @@ struct level_info_t
} }
~level_info_t() ~level_info_t()
{ {
ClearSnapshot(); Snapshot.Clean();
ClearDefered(); ClearDefered();
} }
void Reset(); void Reset();
bool isValid(); bool isValid();
FString LookupLevelName (); FString LookupLevelName ();
void ClearSnapshot(); void ClearDefered()
void ClearDefered(); {
deferred.Clear();
}
level_info_t *CheckLevelRedirect (); level_info_t *CheckLevelRedirect ();
template<class T> 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 struct FLevelLocals
{ {
void Tick (); void Tick ();
void AddScroller (int secnum); 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 time; // time in the hub
int maptime; // time in the map int maptime; // time in the map
int totaltime; // time in the game int totaltime; // time in the game
@ -436,7 +431,7 @@ struct FLevelLocals
int airsupply; int airsupply;
int DefaultEnvironment; // Default sound environment. 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 WallVertLight; // Light diffs for vert/horiz walls
SBYTE WallHorizLight; SBYTE WallHorizLight;
@ -537,9 +532,10 @@ void G_ClearSnapshots (void);
void P_RemoveDefereds (); void P_RemoveDefereds ();
void G_SnapshotLevel (void); void G_SnapshotLevel (void);
void G_UnSnapshotLevel (bool keepPlayers); void G_UnSnapshotLevel (bool keepPlayers);
struct PNGHandle; void G_ReadSnapshots (FResourceFile *);
void G_ReadSnapshots (PNGHandle *png); void G_WriteSnapshots (TArray<FString> &, TArray<FCompressedBuffer> &);
void G_WriteSnapshots (FILE *file); void G_WriteVisited(FSerializer &arc);
void G_ReadVisited(FSerializer &arc);
void G_ClearHubInfo(); void G_ClearHubInfo();
enum ESkillProperty enum ESkillProperty

View file

@ -45,7 +45,6 @@
#include "i_system.h" #include "i_system.h"
#include "gi.h" #include "gi.h"
#include "gstrings.h" #include "gstrings.h"
#include "farchive.h"
#include "p_acs.h" #include "p_acs.h"
#include "doomstat.h" #include "doomstat.h"
#include "d_player.h" #include "d_player.h"
@ -196,7 +195,7 @@ void G_ClearSnapshots (void)
{ {
for (unsigned int i = 0; i < wadlevelinfos.Size(); i++) 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 // 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. // 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; WallVertLight = +8;
F1Pic = ""; F1Pic = "";
musicorder = 0; musicorder = 0;
snapshot = NULL; Snapshot = { 0,0,0,0,0,nullptr };
snapshotVer = 0; deferred.Clear();
defered = 0;
skyspeed1 = skyspeed2 = 0.f; skyspeed1 = skyspeed2 = 0.f;
fadeto = 0; fadeto = 0;
outsidefog = 0xff000000; 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 "thingdef/thingdef.h"
#include "g_level.h" #include "g_level.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h"
#include "a_pickups.h" #include "a_pickups.h"
#include "d_player.h" #include "d_player.h"
#include "serializer.h"
#define MAULATORTICS (25*35) #define MAULATORTICS (25*35)
@ -79,10 +79,10 @@ void AMinotaurFriend::BeginPlay ()
StartTime = -1; StartTime = -1;
} }
void AMinotaurFriend::Serialize (FArchive &arc) void AMinotaurFriend::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << StartTime; arc("starttime", StartTime);
} }
void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags) void AMinotaurFriend::Die (AActor *source, AActor *inflictor, int dmgflags)

View file

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

View file

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

View file

@ -6,7 +6,7 @@
#include "templates.h" #include "templates.h"
#include "g_level.h" #include "g_level.h"
#include "d_player.h" #include "d_player.h"
#include "farchive.h" #include "serializer.h"
IMPLEMENT_CLASS (AArmor) IMPLEMENT_CLASS (AArmor)
@ -21,10 +21,17 @@ IMPLEMENT_CLASS (AHexenArmor)
// //
//=========================================================================== //===========================================================================
void ABasicArmor::Serialize (FArchive &arc) void ABasicArmor::Serialize(FSerializer &arc)
{ {
Super::Serialize (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); 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); Super::Serialize (arc);
arc << SavePercent << SaveAmount << MaxSaveAmount << BonusCount << BonusMax auto def = (ABasicArmorBonus *)GetDefault();
<< MaxAbsorb << MaxFullAbsorb; 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); Super::Serialize (arc);
arc << Slots[0] << Slots[1] << Slots[2] << Slots[3] auto def = (AHexenArmor *)GetDefault();
<< Slots[4] arc.Array("slots", Slots, def->Slots, 5, true)
<< SlotsIncrement[0] << SlotsIncrement[1] << SlotsIncrement[2] .Array("slotsincrement", SlotsIncrement, def->SlotsIncrement, 4);
<< SlotsIncrement[3];
} }
//=========================================================================== //===========================================================================

View file

@ -19,7 +19,7 @@
#include "g_level.h" #include "g_level.h"
#include "doomstat.h" #include "doomstat.h"
#include "v_palette.h" #include "v_palette.h"
#include "farchive.h" #include "serializer.h"
#include "r_utility.h" #include "r_utility.h"
#include "r_data/colormaps.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); Super::Serialize (arc);
arc << PowerupType; auto def = (APowerupGiver*)GetDefault();
arc << EffectTics << BlendColor << Mode; arc("poweruptype", PowerupType, def->PowerupType)
arc << Strength; ("effecttics", EffectTics, def->EffectTics)
("blendcolor", BlendColor, def->BlendColor)
("mode", Mode, def->Mode)
("strength", Strength, def->Strength);
} }
// Powerup ------------------------------------------------------------------- // Powerup -------------------------------------------------------------------
@ -136,11 +139,14 @@ void APowerup::Tick ()
// //
//=========================================================================== //===========================================================================
void APowerup::Serialize (FArchive &arc) void APowerup::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << EffectTics << BlendColor << Mode; auto def = (APowerup*)GetDefault();
arc << Strength; 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); 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); 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); Super::Serialize (arc);
arc << SpeedFlags; arc("speedflags", SpeedFlags);
} }
//=========================================================================== //===========================================================================
@ -1668,7 +1675,7 @@ void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bo
newdam = damage * 4; newdam = damage * 4;
} }
if (Owner != NULL && newdam > damage) S_Sound(Owner, 5, ActiveSound, 1.0f, ATTN_NONE); if (Owner != NULL && newdam > damage) S_Sound(Owner, 5, ActiveSound, 1.0f, ATTN_NONE);
newdamage = newdam; newdamage = damage = newdam;
} }
if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive); if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive);
} }
@ -1743,7 +1750,7 @@ void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage
newdam = damage / 4; newdam = damage / 4;
} }
if (Owner != NULL && newdam < damage) S_Sound(Owner, CHAN_AUTO, ActiveSound, 1.0f, ATTN_NONE); if (Owner != NULL && newdam < damage) S_Sound(Owner, CHAN_AUTO, ActiveSound, 1.0f, ATTN_NONE);
newdamage = newdam; newdamage = damage = newdam;
} }
if (Inventory != NULL) if (Inventory != NULL)
{ {
@ -1899,11 +1906,14 @@ IMPLEMENT_CLASS(APowerMorph)
// //
//=========================================================================== //===========================================================================
void APowerMorph::Serialize (FArchive &arc) void APowerMorph::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << PlayerClass << MorphStyle << MorphFlash << UnMorphFlash; arc("playerclass", PlayerClass)
arc << Player; ("morphstyle", MorphStyle)
("morphflash", MorphFlash)
("unmorphflash", UnMorphFlash)
("player", Player);
} }
//=========================================================================== //===========================================================================

View file

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

View file

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

View file

@ -44,8 +44,9 @@
#include "d_net.h" #include "d_net.h"
#include "colormatcher.h" #include "colormatcher.h"
#include "v_palette.h" #include "v_palette.h"
#include "farchive.h" #include "serializer.h"
#include "doomdata.h" #include "doomdata.h"
#include "r_state.h"
static double DecalWidth, DecalLeft, DecalRight; static double DecalWidth, DecalLeft, DecalRight;
static double SpreadZ; static double SpreadZ;
@ -58,7 +59,8 @@ static int ImpactCount;
CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE)
IMPLEMENT_POINTY_CLASS (DBaseDecal) IMPLEMENT_POINTY_CLASS (DBaseDecal)
DECLARE_POINTER(WallNext) DECLARE_POINTER(WallPrev)
DECLARE_POINTER(WallNext)
END_POINTERS END_POINTERS
IMPLEMENT_CLASS (DImpactDecal) IMPLEMENT_CLASS (DImpactDecal)
@ -75,7 +77,7 @@ DBaseDecal::DBaseDecal ()
DBaseDecal::DBaseDecal (double z) DBaseDecal::DBaseDecal (double z)
: DThinker(STAT_DECAL), : DThinker(STAT_DECAL),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(1.), ScaleY(1.), Alpha(1.), 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; RenderStyle = STYLE_None;
PicNum.SetInvalid(); PicNum.SetInvalid();
@ -83,8 +85,8 @@ DBaseDecal::DBaseDecal (double z)
DBaseDecal::DBaseDecal (int statnum, double z) DBaseDecal::DBaseDecal (int statnum, double z)
: DThinker(statnum), : DThinker(statnum),
WallNext(0), WallPrev(0), LeftDistance(0), Z(z), ScaleX(1.), ScaleY(1.), Alpha(1.), WallNext(nullptr), WallPrev(nullptr), 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; RenderStyle = STYLE_None;
PicNum.SetInvalid(); PicNum.SetInvalid();
@ -92,17 +94,17 @@ DBaseDecal::DBaseDecal (int statnum, double z)
DBaseDecal::DBaseDecal (const AActor *basis) DBaseDecal::DBaseDecal (const AActor *basis)
: DThinker(STAT_DECAL), : 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), 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) DBaseDecal::DBaseDecal (const DBaseDecal *basis)
: DThinker(STAT_DECAL), : 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), 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 () void DBaseDecal::Remove ()
{ {
DBaseDecal **prev = WallPrev; if (WallPrev == nullptr)
DBaseDecal *next = WallNext; {
if (prev && (*prev = next)) if (Side != nullptr) Side->AttachedDecals = WallNext;
next->WallPrev = prev; }
WallPrev = NULL; else WallPrev->WallNext = WallNext;
WallNext = NULL;
if (WallNext != nullptr) WallNext->WallPrev = WallPrev;
WallPrev = nullptr;
WallNext = nullptr;
} }
void DBaseDecal::Serialize (FArchive &arc) void DBaseDecal::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << LeftDistance arc("wallprev", WallPrev)
<< Z ("wallnext", WallNext)
<< ScaleX << ScaleY ("leftdistance", LeftDistance)
<< Alpha ("z", Z)
<< AlphaColor ("scalex", ScaleX)
<< Translation ("scaley", ScaleY)
<< PicNum ("alpha", Alpha)
<< RenderFlags ("alphacolor", AlphaColor)
<< RenderStyle ("translation", Translation)
<< Sector; ("picnum", PicNum)
} ("renderflags", RenderFlags)
("renderstyle", RenderStyle)
void DBaseDecal::SerializeChain (FArchive &arc, DBaseDecal **first) ("side", Side)
{ ("sector", Sector);
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;
}
}
} }
void DBaseDecal::GetXY (side_t *wall, double &ox, double &oy) const 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. // Returns the texture the decal stuck to.
FTextureID DBaseDecal::StickToWall (side_t *wall, double x, double y, F3DFloor *ffloor) 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 Side = wall;
DBaseDecal *next, **prev; WallPrev = wall->AttachedDecals;
prev = &wall->AttachedDecals; while (WallPrev != nullptr && WallPrev->WallNext != nullptr)
while (*prev != NULL)
{ {
next = *prev; WallPrev = WallPrev->WallNext;
prev = &next->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; sector_t *front, *back;
line_t *line; line_t *line;
FTextureID tex; 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 () DImpactDecal::DImpactDecal ()
: DBaseDecal (STAT_AUTODECAL, 0.) : DBaseDecal (STAT_AUTODECAL, 0.)
{ {

View file

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

View file

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

View file

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

View file

@ -11,9 +11,10 @@
#include "a_morph.h" #include "a_morph.h"
#include "doomstat.h" #include "doomstat.h"
#include "g_level.h" #include "g_level.h"
#include "farchive.h" #include "serializer.h"
#include "p_enemy.h" #include "p_enemy.h"
#include "d_player.h" #include "d_player.h"
#include "r_data/sprites.h"
static FRandom pr_morphmonst ("MorphMonster"); static FRandom pr_morphmonst ("MorphMonster");
@ -634,10 +635,16 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage, FName damaget
return -1; return -1;
} }
void AMorphProjectile::Serialize (FArchive &arc) void AMorphProjectile::Serialize(FSerializer &arc)
{ {
Super::Serialize (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) DECLARE_POINTER (UnmorphedMe)
END_POINTERS END_POINTERS
void AMorphedMonster::Serialize (FArchive &arc) void AMorphedMonster::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << UnmorphedMe << UnmorphTime << MorphStyle << MorphExitFlash << FlagsSave; arc("unmorphedme", UnmorphedMe)
("unmorphtime", UnmorphTime)
("morphstyle", MorphStyle)
("morphexitflash", MorphExitFlash)
("flagsave", FlagsSave);
} }
void AMorphedMonster::Destroy () void AMorphedMonster::Destroy ()

View file

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

View file

@ -18,9 +18,9 @@
#include "g_level.h" #include "g_level.h"
#include "g_game.h" #include "g_game.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h"
#include "d_player.h" #include "d_player.h"
#include "p_spec.h" #include "p_spec.h"
#include "serializer.h"
static FRandom pr_restore ("RestorePos"); 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); 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); 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); Super::Serialize(arc);
arc << autousemode; auto def = (AHealthPickup*)GetDefault();
arc("autousemode", autousemode, def->autousemode);
} }
// Backpack ----------------------------------------------------------------- // Backpack -----------------------------------------------------------------
@ -1823,10 +1837,11 @@ void AHealthPickup::Serialize (FArchive &arc)
// //
//=========================================================================== //===========================================================================
void ABackpackItem::Serialize (FArchive &arc) void ABackpackItem::Serialize(FSerializer &arc)
{ {
Super::Serialize (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 HAS_OBJECT_POINTERS
public: public:
virtual void Touch (AActor *toucher); virtual void Touch (AActor *toucher);
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void MarkPrecacheSounds() const; virtual void MarkPrecacheSounds() const;
virtual void BeginPlay (); virtual void BeginPlay ();
@ -185,7 +186,7 @@ public:
int RespawnTics; // Tics from pickup time to respawn time int RespawnTics; // Tics from pickup time to respawn time
FTextureID Icon; // Icon to show on status bar or HUD FTextureID Icon; // Icon to show on status bar or HUD
int DropTime; // Countdown after dropping int DropTime; // Countdown after dropping
const PClass *SpawnPointClass; // For respawning like Heretic's mace PClassActor *SpawnPointClass; // For respawning like Heretic's mace
DWORD ItemFlags; DWORD ItemFlags;
PClassActor *PickupFlash; // actor to spawn as pickup flash PClassActor *PickupFlash; // actor to spawn as pickup flash
@ -254,7 +255,8 @@ class AAmmo : public AInventory
{ {
DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo) DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo)
public: public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
AInventory *CreateCopy (AActor *other); AInventory *CreateCopy (AActor *other);
bool HandlePickup (AInventory *item); bool HandlePickup (AInventory *item);
PClassActor *GetParentAmmo () const; PClassActor *GetParentAmmo () const;
@ -311,7 +313,8 @@ public:
bool bAltFire; // Set when this weapon's alternate fire is used. bool bAltFire; // Set when this weapon's alternate fire is used.
virtual void MarkPrecacheSounds() const; virtual void MarkPrecacheSounds() const;
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual bool ShouldStay (); virtual bool ShouldStay ();
virtual void AttachToOwner (AActor *other); virtual void AttachToOwner (AActor *other);
virtual bool HandlePickup (AInventory *item); virtual bool HandlePickup (AInventory *item);
@ -395,7 +398,8 @@ class AWeaponGiver : public AWeapon
public: public:
bool TryPickup(AActor *&toucher); bool TryPickup(AActor *&toucher);
void Serialize(FArchive &arc);
void Serialize(FSerializer &arc);
double DropAmmoFactor; double DropAmmoFactor;
}; };
@ -431,7 +435,8 @@ class AHealthPickup : public AInventory
public: public:
int autousemode; int autousemode;
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateCopy (AActor *other);
virtual AInventory *CreateTossable (); virtual AInventory *CreateTossable ();
virtual bool HandlePickup (AInventory *item); virtual bool HandlePickup (AInventory *item);
@ -451,7 +456,8 @@ class ABasicArmor : public AArmor
{ {
DECLARE_CLASS (ABasicArmor, AArmor) DECLARE_CLASS (ABasicArmor, AArmor)
public: public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual void Tick (); virtual void Tick ();
virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateCopy (AActor *other);
virtual bool HandlePickup (AInventory *item); virtual bool HandlePickup (AInventory *item);
@ -471,7 +477,8 @@ class ABasicArmorPickup : public AArmor
{ {
DECLARE_CLASS (ABasicArmorPickup, AArmor) DECLARE_CLASS (ABasicArmorPickup, AArmor)
public: public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup); virtual bool Use (bool pickup);
@ -486,7 +493,8 @@ class ABasicArmorBonus : public AArmor
{ {
DECLARE_CLASS (ABasicArmorBonus, AArmor) DECLARE_CLASS (ABasicArmorBonus, AArmor)
public: public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateCopy (AActor *other);
virtual bool Use (bool pickup); virtual bool Use (bool pickup);
@ -505,7 +513,8 @@ class AHexenArmor : public AArmor
{ {
DECLARE_CLASS (AHexenArmor, AArmor) DECLARE_CLASS (AHexenArmor, AArmor)
public: public:
virtual void Serialize (FArchive &arc);
virtual void Serialize(FSerializer &arc);
virtual AInventory *CreateCopy (AActor *other); virtual AInventory *CreateCopy (AActor *other);
virtual AInventory *CreateTossable (); virtual AInventory *CreateTossable ();
virtual bool HandlePickup (AInventory *item); virtual bool HandlePickup (AInventory *item);
@ -533,7 +542,7 @@ class APuzzleItem : public AInventory
{ {
DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem) DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem)
public: public:
void Serialize (FArchive &arc);
bool ShouldStay (); bool ShouldStay ();
bool Use (bool pickup); bool Use (bool pickup);
bool HandlePickup (AInventory *item); bool HandlePickup (AInventory *item);
@ -555,7 +564,8 @@ class ABackpackItem : public AInventory
{ {
DECLARE_CLASS (ABackpackItem, AInventory) DECLARE_CLASS (ABackpackItem, AInventory)
public: public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool HandlePickup (AInventory *item); bool HandlePickup (AInventory *item);
AInventory *CreateCopy (AActor *other); AInventory *CreateCopy (AActor *other);
AInventory *CreateTossable (); AInventory *CreateTossable ();

View file

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

View file

@ -8,7 +8,7 @@
#include "s_sound.h" #include "s_sound.h"
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "statnums.h" #include "statnums.h"
#include "farchive.h" #include "serializer.h"
#include "d_player.h" #include "d_player.h"
#include "r_utility.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); Super::Serialize (arc);
arc << m_Spot << m_Intensity << m_Countdown arc("spot", m_Spot)
<< m_TremorRadius << m_DamageRadius ("intensity", m_Intensity)
<< m_QuakeSFX << m_Flags << m_CountdownStart ("countdown", m_Countdown)
<< m_WaveSpeed ("tremorradius", m_TremorRadius)
<< m_Falloff << m_Highpoint << m_MiniCount ("damageradius", m_DamageRadius)
<< m_RollIntensity << m_RollWave; ("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

@ -49,23 +49,27 @@ bool ASectorAction::IsActivatedByUse() const
void ASectorAction::Destroy () void ASectorAction::Destroy ()
{ {
// Remove ourself from this sector's list of actions if (Sector != nullptr)
AActor *probe = Sector->SecActTarget;
union
{ {
AActor **act; // Remove ourself from this sector's list of actions
ASectorAction **secact; AActor *probe = Sector->SecActTarget;
} prev; union
prev.secact = &Sector->SecActTarget; {
AActor **act;
ASectorAction **secact;
} prev;
prev.secact = &Sector->SecActTarget;
while (probe && probe != this) while (probe && probe != this)
{ {
prev.act = &probe->tracer; prev.act = &probe->tracer;
probe = probe->tracer; probe = probe->tracer;
} }
if (probe != NULL) if (probe != nullptr)
{ {
*prev.act = probe->tracer; *prev.act = probe->tracer;
}
Sector = nullptr;
} }
Super::Destroy (); Super::Destroy ();

View file

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

View file

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

View file

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

View file

@ -39,7 +39,7 @@
#include "i_system.h" #include "i_system.h"
#include "thingdef/thingdef.h" #include "thingdef/thingdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h" #include "serializer.h"
#include "a_pickups.h" #include "a_pickups.h"
static FRandom pr_spot ("SpecialSpot"); static FRandom pr_spot ("SpecialSpot");
@ -58,7 +58,7 @@ TObjPtr<DSpotState> DSpotState::SpotState;
struct FSpotList struct FSpotList
{ {
const PClass *Type; PClassActor *Type;
TArray<ASpecialSpot*> Spots; TArray<ASpecialSpot*> Spots;
unsigned Index; unsigned Index;
int SkipCount; int SkipCount;
@ -68,7 +68,7 @@ struct FSpotList
{ {
} }
FSpotList(const PClass *type) FSpotList(PClassActor *type)
{ {
Type = type; Type = type;
Index = 0; Index = 0;
@ -82,17 +82,6 @@ struct FSpotList
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void Serialize(FArchive &arc)
{
arc << Type << Spots << Index << SkipCount << numcalls;
}
//----------------------------------------------------------------------------
//
//
//
//----------------------------------------------------------------------------
bool Add(ASpecialSpot *newspot) bool Add(ASpecialSpot *newspot)
{ {
for(unsigned i = 0; i < Spots.Size(); i++) 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 () DSpotState::DSpotState ()
: DThinker (STAT_INFO) : DThinker (STAT_INFO)
{ {
@ -215,10 +224,6 @@ DSpotState::DSpotState ()
void DSpotState::Destroy () void DSpotState::Destroy ()
{ {
for(unsigned i = 0; i < SpotLists.Size(); i++)
{
delete SpotLists[i];
}
SpotLists.Clear(); SpotLists.Clear();
SpotLists.ShrinkToFit(); 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++) 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); Super::Serialize(arc);
if (arc.IsStoring()) arc("spots", SpotLists);
{
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);
}
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -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); FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetNextInList(skipcounter); 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); FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetSpotWithMinMaxDistance(x, y, mindist, maxdist); 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); FSpotList *list = FindSpotList(type);
if (list != NULL) return list->GetRandomSpot(onlyonce); if (list != NULL) return list->GetRandomSpot(onlyonce);

View file

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

View file

@ -1,7 +1,7 @@
#include "a_pickups.h" #include "a_pickups.h"
#include "a_weaponpiece.h" #include "a_weaponpiece.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h" #include "serializer.h"
IMPLEMENT_CLASS(PClassWeaponPiece) IMPLEMENT_CLASS(PClassWeaponPiece)
IMPLEMENT_CLASS (AWeaponHolder) 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); Super::Serialize(arc);
arc << PieceMask << PieceWeapon; arc("piecemask", PieceMask)
("pieceweapon", PieceWeapon);
} }
@ -29,10 +30,13 @@ IMPLEMENT_POINTY_CLASS (AWeaponPiece)
END_POINTERS END_POINTERS
void AWeaponPiece::Serialize (FArchive &arc) void AWeaponPiece::Serialize(FSerializer &arc)
{ {
Super::Serialize (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: protected:
bool PrivateShouldStay (); bool PrivateShouldStay ();
public: public:
void Serialize (FArchive &arc);
void Serialize(FSerializer &arc);
bool TryPickup (AActor *&toucher); bool TryPickup (AActor *&toucher);
bool TryPickupRestricted (AActor *&toucher); bool TryPickupRestricted (AActor *&toucher);
bool ShouldStay (); bool ShouldStay ();
@ -23,7 +24,7 @@ public:
virtual void PlayPickupSound (AActor *toucher); virtual void PlayPickupSound (AActor *toucher);
int PieceValue; int PieceValue;
PClassWeapon *WeaponClass; PClassActor *WeaponClass;
TObjPtr<AWeapon> FullWeapon; TObjPtr<AWeapon> FullWeapon;
}; };
@ -35,7 +36,8 @@ class AWeaponHolder : public AInventory
public: public:
int PieceMask; 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 "doomstat.h"
#include "g_level.h" #include "g_level.h"
#include "d_net.h" #include "d_net.h"
#include "farchive.h" #include "serializer.h"
#define BONUSADD 6 #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); Super::Serialize (arc);
arc << WeaponFlags auto def = (AWeapon*)GetDefault();
<< AmmoType1 << AmmoType2 arc("weaponflags", WeaponFlags, def->WeaponFlags)
<< AmmoGive1 << AmmoGive2 ("ammogive1", AmmoGive1, def->AmmoGive1)
<< MinAmmo1 << MinAmmo2 ("ammogive2", AmmoGive2, def->AmmoGive2)
<< AmmoUse1 << AmmoUse2 ("minammo1", MinAmmo1, def->MinAmmo1)
<< Kickback ("minammo2", MinAmmo2, def->MinAmmo2)
<< YAdjust ("ammouse1", AmmoUse1, def->AmmoUse1)
<< UpSound << ReadySound ("ammouse2", AmmoUse2, def->AmmoUse2)
<< SisterWeaponType ("kickback", Kickback, Kickback)
<< ProjectileType << AltProjectileType ("yadjust", YAdjust, def->YAdjust)
<< SelectionOrder ("upsound", UpSound, def->UpSound)
<< MoveCombatDist ("readysound", ReadySound, def->ReadySound)
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon ("selectionorder", SelectionOrder, def->SelectionOrder)
<< bAltFire ("ammo1", Ammo1)
<< ReloadCounter ("ammo2", Ammo2)
<< BobStyle << BobSpeed << BobRangeX << BobRangeY ("sisterweapon", SisterWeapon)
<< FOVScale ("givenasmorphweapon", GivenAsMorphWeapon, def->GivenAsMorphWeapon)
<< Crosshair ("altfire", bAltFire, def->bAltFire)
<< MinSelAmmo1 << MinSelAmmo2; ("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)
*/
} }
//=========================================================================== //===========================================================================
@ -222,6 +239,10 @@ bool AWeapon::HandlePickup (AInventory *item)
{ {
item->ItemFlags |= IF_PICKUPGOOD; item->ItemFlags |= IF_PICKUPGOOD;
} }
if (MaxAmount > 1) //[SP] If amount<maxamount do another pickup test of the weapon itself!
{
return Super::HandlePickup (item);
}
return true; return true;
} }
if (Inventory != NULL) if (Inventory != NULL)
@ -737,10 +758,11 @@ FState *AWeapon::GetStateForButtonName (FName button)
IMPLEMENT_CLASS(AWeaponGiver) IMPLEMENT_CLASS(AWeaponGiver)
void AWeaponGiver::Serialize(FArchive &arc) void AWeaponGiver::Serialize(FSerializer &arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);
arc << DropAmmoFactor; auto def = (AWeaponGiver *)GetDefault();
arc("dropammofactor", DropAmmoFactor, def->DropAmmoFactor);
} }
bool AWeaponGiver::TryPickup(AActor *&toucher) bool AWeaponGiver::TryPickup(AActor *&toucher)

View file

@ -39,7 +39,7 @@
#include "v_video.h" #include "v_video.h"
#include "cmdlib.h" #include "cmdlib.h"
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h" #include "serializer.h"
EXTERN_CVAR(Int, con_scaletext) EXTERN_CVAR(Int, con_scaletext)
int active_con_scaletext(); int active_con_scaletext();
@ -56,14 +56,6 @@ IMPLEMENT_CLASS (DHUDMessageTypeOnFadeOut)
* Basic HUD message. Appears and disappears without any special effects * * 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 // DHUDMessage Constructor
@ -180,20 +172,34 @@ DHUDMessage::~DHUDMessage ()
// //
//============================================================================ //============================================================================
void DHUDMessage::Serialize(FArchive &arc) void DHUDMessage::Serialize(FSerializer &arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);
arc << Left << Top << CenterX << HoldTics arc("left", Left)
<< Tics << State << TextColor ("top", Top)
<< SBarID << SourceText << Font << Next ("centerx", CenterX)
<< HUDWidth << HUDHeight ("holdtics", HoldTics)
<< NoWrap ("tics", Tics)
<< ClipX << ClipY << ClipWidth << ClipHeight ("state", State)
<< WrapWidth .Enum("textcolor", TextColor)
<< HandleAspect ("sbarid", SBarID)
<< VisibilityFlags ("sourcetext", SourceText)
<< Style << Alpha; ("font", Font)
if (arc.IsLoading()) ("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; Lines = NULL;
ResetText(SourceText); 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); 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); 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); 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); EColorRange textColor, float holdTime);
virtual ~DHUDMessage (); virtual ~DHUDMessage ();
virtual void Serialize (FArchive &arc); virtual void Serialize(FSerializer &arc);
void Draw (int bottom, int visibility); void Draw (int bottom, int visibility);
virtual void ResetText (const char *text); 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, DHUDMessageFadeOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime, float fadeOutTime); 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 void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick (); virtual bool Tick ();
@ -176,7 +176,7 @@ public:
DHUDMessageFadeInOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight, DHUDMessageFadeInOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float holdTime, float fadeInTime, float fadeOutTime); 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 void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick (); virtual bool Tick ();
@ -195,7 +195,7 @@ public:
DHUDMessageTypeOnFadeOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight, DHUDMessageTypeOnFadeOut (FFont *font, const char *text, float x, float y, int hudwidth, int hudheight,
EColorRange textColor, float typeTime, float holdTime, float fadeOutTime); 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 void DoDraw (int linenum, int x, int y, bool clean, int hudheight);
virtual bool Tick (); virtual bool Tick ();
virtual void ScreenSizeChanged (); virtual void ScreenSizeChanged ();
@ -355,7 +355,8 @@ public:
static void AddBlend (float r, float g, float b, float a, float v_blend[4]); 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 Tick ();
virtual void Draw (EHudState state); virtual void Draw (EHudState state);

View file

@ -51,8 +51,9 @@
#include "colormatcher.h" #include "colormatcher.h"
#include "v_palette.h" #include "v_palette.h"
#include "d_player.h" #include "d_player.h"
#include "farchive.h" #include "serializer.h"
#include "gstrings.h" #include "gstrings.h"
#include "r_utility.h"
#include "../version.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.Array("hudmessages", Messages, 3, true);
{
arc << Messages[i];
}
} }
void DBaseStatusBar::ScreenSizeChanged () void DBaseStatusBar::ScreenSizeChanged ()

View file

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

View file

@ -18,7 +18,7 @@
#include "templates.h" #include "templates.h"
#include "d_event.h" #include "d_event.h"
#include "v_font.h" #include "v_font.h"
#include "farchive.h" #include "serializer.h"
#include "p_spec.h" #include "p_spec.h"
#include "portal.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); Super::Serialize (arc);
arc << NumPieces << DownPieces; arc("numpieces", NumPieces)
("downpieces", DownPieces);
} }
//============================================================================ //============================================================================

View file

@ -69,6 +69,7 @@
#include "r_utility.h" #include "r_utility.h"
#include "portal.h" #include "portal.h"
#include "doomstat.h" #include "doomstat.h"
#include "serializer.h"
#include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderer.h"
@ -154,24 +155,31 @@ static FRandom randLight;
// //
// //
//========================================================================== //==========================================================================
void ADynamicLight::Serialize(FArchive &arc) void ADynamicLight::Serialize(FSerializer &arc)
{ {
Super::Serialize (arc); Super::Serialize (arc);
arc << lightflags << lighttype; auto def = static_cast<ADynamicLight*>(GetDefault());
arc << m_tickCount << m_currentRadius; arc("lightflags", lightflags, def->lightflags)
arc << m_Radius[0] << m_Radius[1]; ("lighttype", lighttype, def->lighttype)
("tickcount", m_tickCount, def->m_tickCount)
("currentradius", m_currentRadius, def->m_currentRadius)
.Array("radius", m_Radius, def->m_Radius, 2);
if (lighttype == PulseLight) arc << m_lastUpdate << m_cycler; if (lighttype == PulseLight)
if (arc.IsLoading()) arc("lastupdate", m_lastUpdate, def->m_lastUpdate)
{ ("cycler", m_cycler, def->m_cycler);
// The default constructor which is used for creating objects before deserialization will not set this variable.
// It needs to be true for all placed lights.
visibletoplayer = true;
LinkLight();
}
} }
void ADynamicLight::PostSerialize()
{
Super::PostSerialize();
// The default constructor which is used for creating objects before deserialization will not set this variable.
// It needs to be true for all placed lights.
visibletoplayer = true;
LinkLight();
}
//========================================================================== //==========================================================================
// //
// [TS] // [TS]

View file

@ -32,7 +32,7 @@ EXTERN_CVAR(Bool, gl_lights)
EXTERN_CVAR(Bool, gl_attachedlights) EXTERN_CVAR(Bool, gl_attachedlights)
class ADynamicLight; class ADynamicLight;
class FArchive; class FSerializer;
@ -93,7 +93,8 @@ class ADynamicLight : public AActor
DECLARE_CLASS (ADynamicLight, AActor) DECLARE_CLASS (ADynamicLight, AActor)
public: public:
virtual void Tick(); virtual void Tick();
void Serialize(FArchive &arc); void Serialize(FSerializer &arc);
void PostSerialize();
BYTE GetRed() const { return args[LIGHT_RED]; } BYTE GetRed() const { return args[LIGHT_RED]; }
BYTE GetGreen() const { return args[LIGHT_GREEN]; } BYTE GetGreen() const { return args[LIGHT_GREEN]; }
BYTE GetBlue() const { return args[LIGHT_BLUE]; } BYTE GetBlue() const { return args[LIGHT_BLUE]; }

View file

@ -275,8 +275,8 @@ void FVoxelModel::AddFace(int x1, int y1, int z1, int x2, int y2, int z2, int x3
mIndices.Push(indx[1]); mIndices.Push(indx[1]);
mIndices.Push(indx[3]); mIndices.Push(indx[3]);
mIndices.Push(indx[1]); mIndices.Push(indx[1]);
mIndices.Push(indx[3]);
mIndices.Push(indx[2]); mIndices.Push(indx[2]);
mIndices.Push(indx[3]);
} }
//=========================================================================== //===========================================================================

View file

@ -160,6 +160,7 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
ptr->Set(x, y + h, 0, u1, v2, color); ptr++; ptr->Set(x, y + h, 0, u1, v2, color); ptr++;
ptr->Set(x + w, y, 0, u2, v1, color); ptr++; ptr->Set(x + w, y, 0, u2, v1, color); ptr++;
ptr->Set(x + w, y + h, 0, u2, v2, color); ptr++; ptr->Set(x + w, y + h, 0, u2, v2, color); ptr++;
dg.mVertCount = 8;
} }
AddData(&dg); AddData(&dg);
} }

View file

@ -322,6 +322,78 @@ void FGLRenderer::UpdateCameraExposure()
FGLDebug::PopGroup(); FGLDebug::PopGroup();
} }
//-----------------------------------------------------------------------------
//
// Extracts light average from the scene and updates the camera exposure texture
//
//-----------------------------------------------------------------------------
void FGLRenderer::UpdateCameraExposure()
{
if (!gl_bloom && gl_tonemap == 0)
return;
FGLDebug::PushGroup("UpdateCameraExposure");
FGLPostProcessState savedState;
savedState.SaveTextureBinding1();
// Extract light level from scene texture:
const auto &level0 = mBuffers->ExposureLevels[0];
glBindFramebuffer(GL_FRAMEBUFFER, level0.Framebuffer);
glViewport(0, 0, level0.Width, level0.Height);
mBuffers->BindCurrentTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mExposureExtractShader->Bind();
mExposureExtractShader->SceneTexture.Set(0);
mExposureExtractShader->Scale.Set(mSceneViewport.width / (float)mScreenViewport.width, mSceneViewport.height / (float)mScreenViewport.height);
mExposureExtractShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
RenderScreenQuad();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Find the average value:
for (int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++)
{
const auto &level = mBuffers->ExposureLevels[i];
const auto &next = mBuffers->ExposureLevels[i + 1];
glBindFramebuffer(GL_FRAMEBUFFER, next.Framebuffer);
glViewport(0, 0, next.Width, next.Height);
glBindTexture(GL_TEXTURE_2D, level.Texture);
mExposureAverageShader->Bind();
mExposureAverageShader->ExposureTexture.Set(0);
RenderScreenQuad();
}
// Combine average value with current camera exposure:
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->ExposureFB);
glViewport(0, 0, 1, 1);
if (!mBuffers->FirstExposureFrame)
{
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
mBuffers->FirstExposureFrame = false;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureLevels.Last().Texture);
mExposureCombineShader->Bind();
mExposureCombineShader->ExposureTexture.Set(0);
mExposureCombineShader->ExposureBase.Set(gl_exposure_base);
mExposureCombineShader->ExposureMin.Set(gl_exposure_min);
mExposureCombineShader->ExposureScale.Set(gl_exposure_scale);
mExposureCombineShader->ExposureSpeed.Set(gl_exposure_speed);
RenderScreenQuad();
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
FGLDebug::PopGroup();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Adds bloom contribution to scene texture // Adds bloom contribution to scene texture

View file

@ -58,6 +58,7 @@
#include "gl/shaders/gl_colormapshader.h" #include "gl/shaders/gl_colormapshader.h"
#include "gl/shaders/gl_lensshader.h" #include "gl/shaders/gl_lensshader.h"
#include "gl/shaders/gl_presentshader.h" #include "gl/shaders/gl_presentshader.h"
#include "gl/stereo3d/gl_stereo3d.h"
#include "gl/textures/gl_texture.h" #include "gl/textures/gl_texture.h"
#include "gl/textures/gl_translate.h" #include "gl/textures/gl_translate.h"
#include "gl/textures/gl_material.h" #include "gl/textures/gl_material.h"
@ -286,6 +287,8 @@ void FGLRenderer::SetOutputViewport(GL_IRECT *bounds)
mSceneViewport.top += mOutputLetterbox.top; mSceneViewport.top += mOutputLetterbox.top;
} }
} }
s3d::Stereo3DMode::getCurrentMode().AdjustViewports();
} }
//=========================================================================== //===========================================================================

View file

@ -177,7 +177,7 @@ public:
void RenderScreenQuad(); void RenderScreenQuad();
void SetFixedColormap (player_t *player); void SetFixedColormap (player_t *player);
void WriteSavePic (player_t *player, FILE *file, int width, int height); void WriteSavePic (player_t *player, FileWriter *file, int width, int height);
void EndDrawScene(sector_t * viewsector); void EndDrawScene(sector_t * viewsector);
void PostProcessScene(); void PostProcessScene();
void AmbientOccludeScene(); void AmbientOccludeScene();

View file

@ -497,6 +497,10 @@ void GLDrawList::SortWallIntoWall(SortNode * head,SortNode * sort)
// //
// //
//========================================================================== //==========================================================================
EXTERN_CVAR(Int, gl_billboard_mode)
EXTERN_CVAR(Bool, gl_billboard_faces_camera)
EXTERN_CVAR(Bool, gl_billboard_particles)
void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort) void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort)
{ {
GLWall * wh=&walls[drawitems[head->itemindex].index]; GLWall * wh=&walls[drawitems[head->itemindex].index];
@ -527,6 +531,27 @@ void GLDrawList::SortSpriteIntoWall(SortNode * head,SortNode * sort)
} }
else else
{ {
const bool drawWithXYBillboard = ((ss->particle && gl_billboard_particles) || (!(ss->actor && ss->actor->renderflags & RF_FORCEYBILLBOARD)
&& (gl_billboard_mode == 1 || (ss->actor && ss->actor->renderflags & RF_FORCEXYBILLBOARD))));
const bool drawBillboardFacingCamera = gl_billboard_faces_camera;
// [Nash] has +ROLLSPRITE
const bool rotated = (ss->actor != nullptr && ss->actor->renderflags & RF_ROLLSPRITE | RF_WALLSPRITE | RF_FLATSPRITE);
// cannot sort them at the moment. This requires more complex splitting.
if (drawWithXYBillboard || drawBillboardFacingCamera || rotated)
{
float v1 = wh->PointOnSide(ss->x, ss->y);
if (v1 < 0)
{
head->AddToLeft(sort);
}
else
{
head->AddToRight(sort);
}
return;
}
double r=ss->CalcIntersectionVertex(wh); double r=ss->CalcIntersectionVertex(wh);
float ix=(float)(ss->x1 + r * (ss->x2-ss->x1)); float ix=(float)(ss->x1 + r * (ss->x2-ss->x1));

View file

@ -43,6 +43,7 @@
#include "a_hexenglobal.h" #include "a_hexenglobal.h"
#include "p_local.h" #include "p_local.h"
#include "gl/gl_functions.h" #include "gl/gl_functions.h"
#include "serializer.h"
#include "gl/dynlights/gl_lightbuffer.h" #include "gl/dynlights/gl_lightbuffer.h"
#include "gl/system/gl_interface.h" #include "gl/system/gl_interface.h"
@ -649,6 +650,7 @@ void FGLRenderer::DrawBlend(sector_t * viewsector)
V_AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); V_AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend);
} }
gl_RenderState.SetTextureMode(TM_MODULATE);
gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (blend[3]>0.0f) if (blend[3]>0.0f)
{ {
@ -687,6 +689,7 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector)
framebuffer->Begin2D(false); framebuffer->Begin2D(false);
Reset3DViewport(); Reset3DViewport();
// [BB] Only draw the sprites if we didn't render a HUD model before. // [BB] Only draw the sprites if we didn't render a HUD model before.
if ( renderHUDModel == false ) if ( renderHUDModel == false )
{ {
@ -828,7 +831,6 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
{ {
const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix); const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix);
eye->SetUp(); eye->SetUp();
// TODO: stereo specific viewport - needed when implementing side-by-side modes etc.
SetOutputViewport(bounds); SetOutputViewport(bounds);
Set3DViewport(mainview); Set3DViewport(mainview);
mDrawingScene2D = true; mDrawingScene2D = true;
@ -848,7 +850,7 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo
clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1); clipper.SafeAddClipRangeRealAngles(ViewAngle.BAMs() + a1, ViewAngle.BAMs() - a1);
ProcessScene(toscreen); ProcessScene(toscreen);
if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures. if (mainview && toscreen) EndDrawScene(lviewsector); // do not call this for camera textures.
if (mainview && FGLRenderBuffers::IsEnabled()) if (mainview && FGLRenderBuffers::IsEnabled())
{ {
PostProcessScene(); PostProcessScene();
@ -942,7 +944,7 @@ void FGLRenderer::RenderView (player_t* player)
// //
//=========================================================================== //===========================================================================
void FGLRenderer::WriteSavePic (player_t *player, FILE *file, int width, int height) void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{ {
GL_IRECT bounds; GL_IRECT bounds;
@ -988,25 +990,25 @@ void FGLRenderer::WriteSavePic (player_t *player, FILE *file, int width, int hei
struct FGLInterface : public FRenderer struct FGLInterface : public FRenderer
{ {
bool UsesColormap() const; bool UsesColormap() const override;
void PrecacheTexture(FTexture *tex, int cache); void PrecacheTexture(FTexture *tex, int cache);
void PrecacheSprite(FTexture *tex, SpriteHits &hits); void PrecacheSprite(FTexture *tex, SpriteHits &hits);
void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist); void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist) override;
void RenderView(player_t *player); void RenderView(player_t *player) override;
void WriteSavePic (player_t *player, FILE *file, int width, int height); void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override;
void StateChanged(AActor *actor); void StateChanged(AActor *actor) override;
void StartSerialize(FArchive &arc); void StartSerialize(FSerializer &arc) override;
void EndSerialize(FArchive &arc); void EndSerialize(FSerializer &arc) override;
void RenderTextureView (FCanvasTexture *self, AActor *viewpoint, int fov); void RenderTextureView (FCanvasTexture *self, AActor *viewpoint, int fov) override;
sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back); sector_t *FakeFlat(sector_t *sec, sector_t *tempsec, int *floorlightlevel, int *ceilinglightlevel, bool back) override;
void SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog); void SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog) override;
void PreprocessLevel(); void PreprocessLevel() override;
void CleanLevelData(); void CleanLevelData() override;
bool RequireGLNodes(); bool RequireGLNodes() override;
int GetMaxViewPitch(bool down); int GetMaxViewPitch(bool down) override;
void ClearBuffer(int color); void ClearBuffer(int color) override;
void Init(); void Init() override;
}; };
//=========================================================================== //===========================================================================
@ -1216,20 +1218,22 @@ void FGLInterface::StateChanged(AActor *actor)
// //
//=========================================================================== //===========================================================================
void FGLInterface::StartSerialize(FArchive &arc) void FGLInterface::StartSerialize(FSerializer &arc)
{ {
gl_DeleteAllAttachedLights(); gl_DeleteAllAttachedLights();
if (arc.BeginObject("glinfo"))
{
arc("fogdensity", fogdensity)
("outsidefogdensity", outsidefogdensity)
("skyfog", skyfog)
.EndObject();
}
} }
void gl_SerializeGlobals(FArchive &arc) void FGLInterface::EndSerialize(FSerializer &arc)
{
arc << fogdensity << outsidefogdensity << skyfog;
}
void FGLInterface::EndSerialize(FArchive &arc)
{ {
gl_RecreateAllAttachedLights(); gl_RecreateAllAttachedLights();
if (arc.IsLoading()) gl_InitPortals(); if (arc.isReading()) gl_InitPortals();
} }
//=========================================================================== //===========================================================================
@ -1265,7 +1269,7 @@ void FGLInterface::ClearBuffer(int color)
// //
//=========================================================================== //===========================================================================
void FGLInterface::WriteSavePic (player_t *player, FILE *file, int width, int height) void FGLInterface::WriteSavePic (player_t *player, FileWriter *file, int width, int height)
{ {
GLRenderer->WriteSavePic(player, file, width, height); GLRenderer->WriteSavePic(player, file, width, height);
} }

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