mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'more-saveg-fixes' into 'master'
Several netsave fixes / improvements See merge request KartKrew/Kart!2475
This commit is contained in:
commit
067a1007da
5 changed files with 633 additions and 47 deletions
|
|
@ -167,6 +167,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
music.cpp
|
||||
music_manager.cpp
|
||||
sanitize.cpp
|
||||
p_deepcopy.cpp
|
||||
)
|
||||
|
||||
if(SRB2_CONFIG_ENABLE_WEBM_MOVIES)
|
||||
|
|
|
|||
229
src/p_deepcopy.cpp
Normal file
229
src/p_deepcopy.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file p_deepcopy.cpp
|
||||
/// \brief Methods for deep copying
|
||||
|
||||
#include "p_deepcopy.h"
|
||||
|
||||
#include "typedef.h"
|
||||
#include "z_zone.h"
|
||||
#include "taglist.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void P_DeepCopy(Type *target, Type *source, void (*callback)(Type *, Type *))
|
||||
|
||||
Make a deep copy of a struct, by using memcpy
|
||||
for an initial shallow copy, and a callback
|
||||
function to handle any memory addresses.
|
||||
|
||||
Input Arguments:-
|
||||
Type: The type of the structs.
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
callback: A callback function, intended to replace
|
||||
pointers after the initial shallow copy.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
template <typename Type>
|
||||
static void P_DeepCopy(Type *target, Type *source, void (*callback)(Type *, Type *))
|
||||
{
|
||||
memcpy(target, source, sizeof(Type));
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
callback(target, source);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void P_DeepCopyArray(Type **target_array, Type **source_array, size_t source_len, void (*callback)(Type *, Type *))
|
||||
|
||||
Make a deep copy of an array of structs, by using
|
||||
memcpy for an initial shallow copy, and a callback
|
||||
function to handle any memory addresses for each
|
||||
individual struct.
|
||||
|
||||
Input Arguments:-
|
||||
Type: The type of the structs.
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
callback: A callback function, intended to replace
|
||||
pointers after the initial shallow copy.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
template <typename Type>
|
||||
static void P_DeepCopyArray(Type **target_array, Type **source_array, size_t source_len, void (*callback)(Type *, Type *))
|
||||
{
|
||||
const size_t source_total = source_len * sizeof(Type);
|
||||
|
||||
*target_array = static_cast<Type *>(Z_Calloc(source_total, PU_LEVEL, nullptr));
|
||||
memcpy(*target_array, *source_array, source_total);
|
||||
|
||||
if (callback != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < source_len; i++)
|
||||
{
|
||||
Type *target = &(*target_array)[i];
|
||||
Type *source = &(*source_array)[i];
|
||||
|
||||
callback(target, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_taglist_tags(taglist_t *target, taglist_t *source)
|
||||
|
||||
Make a deep copy of taglist's tags fields.
|
||||
Used as a helper function for other callbacks,
|
||||
does not work as a full deep copy of taglist_t
|
||||
on its own.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_taglist_tags(taglist_t *target, taglist_t *source)
|
||||
{
|
||||
if (source->count)
|
||||
{
|
||||
target->tags = static_cast<mtag_t *>(
|
||||
memcpy(
|
||||
Z_Malloc(
|
||||
source->count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
nullptr
|
||||
),
|
||||
source->tags,
|
||||
source->count * sizeof(mtag_t)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_sector_callback(sector_t *target, sector_t *source)
|
||||
|
||||
Handles memory addresses after creating a shallow copy
|
||||
of a sector_t, to turn it into a deep copy.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_sector_callback(sector_t *target, sector_t *source)
|
||||
{
|
||||
// (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
copy_taglist_tags(&target->tags, &source->tags);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source)
|
||||
{
|
||||
P_DeepCopy<sector_t>(target, source, copy_sector_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<sector_t>(target_array, source_array, source_len, copy_sector_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void copy_line_callback(line_t *target, line_t *source)
|
||||
|
||||
Handles memory addresses after creating a shallow copy
|
||||
of a line_t, to turn it into a deep copy.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
static void copy_line_callback(line_t *target, line_t *source)
|
||||
{
|
||||
// (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
copy_taglist_tags(&target->tags, &source->tags);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
{
|
||||
P_DeepCopy<line_t>(target, source, copy_line_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<line_t>(target_array, source_array, source_len, copy_line_callback);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySide(line_t *target, line_t *source)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySide(side_t *target, side_t *source)
|
||||
{
|
||||
P_DeepCopy<side_t>(target, source, nullptr); // (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
{
|
||||
P_DeepCopyArray<side_t>(target_array, source_array, source_len, nullptr); // (Not a true deep copy until all of the memory addresses are accounted for.)
|
||||
}
|
||||
131
src/p_deepcopy.h
Normal file
131
src/p_deepcopy.h
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
|
||||
// Copyright (C) 2024 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file p_deepcopy.h
|
||||
/// \brief Methods for deep copying
|
||||
|
||||
#ifndef __P_DEEPCOPY__
|
||||
#define __P_DEEPCOPY__
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source);
|
||||
|
||||
Make a deep copy of a single sector_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySector(sector_t *target, sector_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len);
|
||||
|
||||
Make a deep copy of an array of sector_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySectors(sector_t **target_array, sector_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLine(line_t *target, line_t *source)
|
||||
|
||||
Make a deep copy of a single line_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLine(line_t *target, line_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len)
|
||||
|
||||
Make a deep copy of an array of line_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopyLines(line_t **target_array, line_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySide(line_t *target, line_t *source)
|
||||
|
||||
Make a deep copy of a single side_t.
|
||||
|
||||
Input Arguments:-
|
||||
target: The struct to copy into.
|
||||
source: The struct to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySide(side_t *target, side_t *source);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len)
|
||||
|
||||
Make a deep copy of an array of side_t.
|
||||
|
||||
Input Arguments:-
|
||||
target_array: The start of the array to copy into.
|
||||
This will be allocated by this function, so
|
||||
it should be freed beforehand.
|
||||
source_array: The start of the array to copy from.
|
||||
source_len: The length of the array to copy from.
|
||||
|
||||
Return:-
|
||||
N/A
|
||||
--------------------------------------------------*/
|
||||
|
||||
void P_DeepCopySides(side_t **target_array, side_t **source_array, size_t source_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __P_DEEPCOPY__
|
||||
303
src/p_saveg.cpp
303
src/p_saveg.cpp
|
|
@ -2000,7 +2000,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
|
|||
#define SD_DIFF3 0x80
|
||||
|
||||
// diff3 flags
|
||||
#define SD_TAGLIST 0x01
|
||||
#define SD__UNUSED 0x01
|
||||
#define SD_COLORMAP 0x02
|
||||
#define SD_CRUMBLESTATE 0x04
|
||||
#define SD_FLOORLIGHT 0x08
|
||||
|
|
@ -2050,7 +2050,7 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn
|
|||
|
||||
#define LD_FLAG 0x01
|
||||
#define LD_SPECIAL 0x02
|
||||
#define LD_CLLCOUNT 0x04
|
||||
#define LD_TAG 0x04
|
||||
#define LD_S1TEXOFF 0x08
|
||||
#define LD_S1TOPTEX 0x10
|
||||
#define LD_S1BOTTEX 0x20
|
||||
|
|
@ -2064,7 +2064,7 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn
|
|||
#define LD_S2MIDTEX 0x08
|
||||
#define LD_ARGS 0x10
|
||||
#define LD_STRINGARGS 0x20
|
||||
#define LD_EXECUTORDELAY 0x40
|
||||
#define LD__UNUSED 0x40
|
||||
#define LD_DIFF3 0x80
|
||||
|
||||
// diff3 flags
|
||||
|
|
@ -2476,7 +2476,7 @@ static void UnArchiveSectors(savebuffer_t *save)
|
|||
|
||||
// Add new entries.
|
||||
for (j = 0; j < sectors[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
Taggroup_Add(tags_sectors, sectors[i].tags.tags[j], i);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2553,7 +2553,7 @@ static void UnArchiveSectors(savebuffer_t *save)
|
|||
|
||||
static void ArchiveLines(savebuffer_t *save)
|
||||
{
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
const line_t *li = lines;
|
||||
const line_t *spawnli = spawnlines;
|
||||
const side_t *si;
|
||||
|
|
@ -2570,8 +2570,8 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
if (li->special != spawnli->special)
|
||||
diff |= LD_SPECIAL;
|
||||
|
||||
if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
|
||||
diff |= LD_CLLCOUNT;
|
||||
if (!Tag_Compare(&li->tags, &spawnli->tags))
|
||||
diff |= LD_TAG;
|
||||
|
||||
if (!P_LineArgsEqual(li, spawnli))
|
||||
diff2 |= LD_ARGS;
|
||||
|
|
@ -2579,9 +2579,6 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
if (!P_LineStringArgsEqual(li, spawnli))
|
||||
diff2 |= LD_STRINGARGS;
|
||||
|
||||
if (li->executordelay != spawnli->executordelay)
|
||||
diff2 |= LD_EXECUTORDELAY;
|
||||
|
||||
if (li->activation != spawnli->activation)
|
||||
diff3 |= LD_ACTIVATION;
|
||||
|
||||
|
|
@ -2631,8 +2628,12 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, li->flags);
|
||||
if (diff & LD_SPECIAL)
|
||||
WRITEINT16(save->p, li->special);
|
||||
if (diff & LD_CLLCOUNT)
|
||||
WRITEINT16(save->p, li->callcount);
|
||||
if (diff & LD_TAG)
|
||||
{
|
||||
WRITEUINT32(save->p, li->tags.count);
|
||||
for (j = 0; j < li->tags.count; j++)
|
||||
WRITEINT16(save->p, li->tags.tags[j]);
|
||||
}
|
||||
|
||||
si = &sides[li->sidenum[0]];
|
||||
if (diff & LD_S1TEXOFF)
|
||||
|
|
@ -2678,8 +2679,6 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
WRITECHAR(save->p, li->stringargs[j][k]);
|
||||
}
|
||||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
WRITEINT32(save->p, li->executordelay);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
WRITEUINT32(save->p, li->activation);
|
||||
}
|
||||
|
|
@ -2689,7 +2688,7 @@ static void ArchiveLines(savebuffer_t *save)
|
|||
|
||||
static void UnArchiveLines(savebuffer_t *save)
|
||||
{
|
||||
UINT16 i;
|
||||
UINT16 i, j;
|
||||
line_t *li;
|
||||
side_t *si;
|
||||
UINT8 diff, diff2, diff3;
|
||||
|
|
@ -2720,8 +2719,28 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
li->flags = READUINT32(save->p);
|
||||
if (diff & LD_SPECIAL)
|
||||
li->special = READINT16(save->p);
|
||||
if (diff & LD_CLLCOUNT)
|
||||
li->callcount = READINT16(save->p);
|
||||
if (diff & LD_TAG)
|
||||
{
|
||||
size_t ncount = READUINT32(save->p);
|
||||
|
||||
// Remove entries from global lists.
|
||||
for (j = 0; j < lines[i].tags.count; j++)
|
||||
Taggroup_Remove(tags_lines, lines[i].tags.tags[j], i);
|
||||
|
||||
// Reallocate if size differs.
|
||||
if (ncount != lines[i].tags.count)
|
||||
{
|
||||
lines[i].tags.count = ncount;
|
||||
lines[i].tags.tags = (mtag_t*)Z_Realloc(lines[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL);
|
||||
}
|
||||
|
||||
for (j = 0; j < ncount; j++)
|
||||
lines[i].tags.tags[j] = READINT16(save->p);
|
||||
|
||||
// Add new entries.
|
||||
for (j = 0; j < lines[i].tags.count; j++)
|
||||
Taggroup_Add(tags_lines, lines[i].tags.tags[j], i);
|
||||
}
|
||||
|
||||
si = &sides[li->sidenum[0]];
|
||||
if (diff & LD_S1TEXOFF)
|
||||
|
|
@ -2744,13 +2763,11 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
si->midtexture = READINT32(save->p);
|
||||
if (diff2 & LD_ARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_ARGS; j++)
|
||||
li->args[j] = READINT32(save->p);
|
||||
}
|
||||
if (diff2 & LD_STRINGARGS)
|
||||
{
|
||||
UINT8 j;
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = READINT32(save->p);
|
||||
|
|
@ -2769,8 +2786,6 @@ static void UnArchiveLines(savebuffer_t *save)
|
|||
li->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
if (diff2 & LD_EXECUTORDELAY)
|
||||
li->executordelay = READINT32(save->p);
|
||||
if (diff3 & LD_ACTIVATION)
|
||||
li->activation = READUINT32(save->p);
|
||||
}
|
||||
|
|
@ -3142,9 +3157,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
// not the default but the most probable
|
||||
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0 || mobj->lastmomz != 0)
|
||||
diff |= MD_MOM;
|
||||
if (mobj->radius != mobj->info->radius)
|
||||
if (mobj->radius != FixedMul(mapobjectscale, mobj->info->radius))
|
||||
diff |= MD_RADIUS;
|
||||
if (mobj->height != mobj->info->height)
|
||||
if (mobj->height != FixedMul(mapobjectscale, mobj->info->height))
|
||||
diff |= MD_HEIGHT;
|
||||
if (mobj->flags != mobj->info->flags)
|
||||
diff |= MD_FLAGS;
|
||||
|
|
@ -3188,11 +3203,11 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
diff |= MD_MOVEFACTOR;
|
||||
if (mobj->fuse)
|
||||
diff |= MD_FUSE;
|
||||
if (mobj->watertop)
|
||||
if (mobj->watertop != INT32_MAX)
|
||||
diff |= MD_WATERTOP;
|
||||
if (mobj->waterbottom)
|
||||
diff |= MD_WATERBOTTOM;
|
||||
if (mobj->scale != FRACUNIT)
|
||||
if (mobj->scale != mapobjectscale)
|
||||
diff |= MD_SCALE;
|
||||
if (mobj->destscale != mobj->scale)
|
||||
diff |= MD_DSCALE;
|
||||
|
|
@ -4461,6 +4476,21 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static mobjtype_t g_doomednum_to_mobjtype[UINT16_MAX];
|
||||
|
||||
static void CalculateDoomednumToMobjtype(void)
|
||||
{
|
||||
memset(g_doomednum_to_mobjtype, MT_NULL, sizeof(g_doomednum_to_mobjtype));
|
||||
|
||||
for (size_t i = MT_NULL+1; i < NUMMOBJTYPES; i++)
|
||||
{
|
||||
if (mobjinfo[i].doomednum > 0 && mobjinfo[i].doomednum <= UINT16_MAX)
|
||||
{
|
||||
g_doomednum_to_mobjtype[ mobjinfo[i].doomednum ] = static_cast<mobjtype_t>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
||||
{
|
||||
mobj_t *mobj;
|
||||
|
|
@ -4532,20 +4562,26 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
mobj->type = (mobjtype_t)READUINT32(save->p);
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NUMMOBJTYPES; i++)
|
||||
if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum)
|
||||
break;
|
||||
if (i == NUMMOBJTYPES)
|
||||
mobjtype_t new_type = MT_NULL;
|
||||
if (mobj->spawnpoint)
|
||||
{
|
||||
new_type = g_doomednum_to_mobjtype[mobj->spawnpoint->type];
|
||||
}
|
||||
|
||||
if (new_type <= MT_NULL || new_type >= NUMMOBJTYPES)
|
||||
{
|
||||
if (mobj->spawnpoint)
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type);
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum %d\n", mobj->spawnpoint->type);
|
||||
else
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n");
|
||||
CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum NULL\n");
|
||||
|
||||
I_Error("Netsave corrupted");
|
||||
}
|
||||
mobj->type = (mobjtype_t)i;
|
||||
|
||||
mobj->type = new_type;
|
||||
}
|
||||
mobj->info = &mobjinfo[mobj->type];
|
||||
|
||||
if (diff & MD_POS)
|
||||
{
|
||||
mobj->x = mobj->old_x = READFIXED(save->p);
|
||||
|
|
@ -4574,11 +4610,11 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
if (diff & MD_RADIUS)
|
||||
mobj->radius = READFIXED(save->p);
|
||||
else
|
||||
mobj->radius = mobj->info->radius;
|
||||
mobj->radius = FixedMul(mobj->info->radius, mapobjectscale);
|
||||
if (diff & MD_HEIGHT)
|
||||
mobj->height = READFIXED(save->p);
|
||||
else
|
||||
mobj->height = mobj->info->height;
|
||||
mobj->height = FixedMul(mobj->info->height, mapobjectscale);
|
||||
if (diff & MD_FLAGS)
|
||||
mobj->flags = READUINT32(save->p);
|
||||
else
|
||||
|
|
@ -4656,12 +4692,14 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
|
|||
mobj->fuse = READINT32(save->p);
|
||||
if (diff & MD_WATERTOP)
|
||||
mobj->watertop = READFIXED(save->p);
|
||||
else
|
||||
mobj->watertop = INT32_MAX;
|
||||
if (diff & MD_WATERBOTTOM)
|
||||
mobj->waterbottom = READFIXED(save->p);
|
||||
if (diff & MD_SCALE)
|
||||
mobj->scale = READFIXED(save->p);
|
||||
else
|
||||
mobj->scale = FRACUNIT;
|
||||
mobj->scale = mapobjectscale;
|
||||
if (diff & MD_DSCALE)
|
||||
mobj->destscale = READFIXED(save->p);
|
||||
else
|
||||
|
|
@ -5506,6 +5544,10 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
|
|||
if (READUINT32(save->p) != ARCHIVEBLOCK_THINKERS)
|
||||
I_Error("Bad $$$.sav at archive block Thinkers");
|
||||
|
||||
// Pre-calculate this lookup, because it was wasting
|
||||
// a shit ton of time loading mobj thinkers.
|
||||
CalculateDoomednumToMobjtype();
|
||||
|
||||
// remove all the current thinkers
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
|
|
@ -6794,6 +6836,197 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only reload stuff that can we modify in the save states themselves.
|
||||
// This is still orders of magnitude faster than a full level reload.
|
||||
// Considered memcpy, but it's complicated -- save that for local saves.
|
||||
|
||||
sector_t *ss = sectors;
|
||||
sector_t *spawnss = spawnsectors;
|
||||
for (i = 0; i < numsectors; i++, ss++, spawnss++)
|
||||
{
|
||||
ss->floorheight = spawnss->floorheight;
|
||||
ss->ceilingheight = spawnss->ceilingheight;
|
||||
ss->floorpic = spawnss->floorpic;
|
||||
ss->ceilingpic = spawnss->ceilingpic;
|
||||
ss->lightlevel = spawnss->lightlevel;
|
||||
ss->special = spawnss->special;
|
||||
ss->floor_xoffs = spawnss->floor_xoffs;
|
||||
ss->floor_yoffs = spawnss->floor_yoffs;
|
||||
ss->ceiling_xoffs = spawnss->ceiling_xoffs;
|
||||
ss->ceiling_yoffs = spawnss->ceiling_yoffs;
|
||||
ss->floorpic_angle = spawnss->floorpic_angle;
|
||||
ss->ceilingpic_angle = spawnss->ceilingpic_angle;
|
||||
|
||||
if (Tag_Compare(&ss->tags, &spawnss->tags) == false)
|
||||
{
|
||||
if (spawnss->tags.count)
|
||||
{
|
||||
ss->tags.count = spawnss->tags.count;
|
||||
ss->tags.tags = static_cast<mtag_t *>(
|
||||
memcpy(
|
||||
Z_Realloc(
|
||||
ss->tags.tags,
|
||||
spawnss->tags.count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
nullptr
|
||||
),
|
||||
spawnss->tags.tags,
|
||||
spawnss->tags.count * sizeof(mtag_t)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ss->tags.count = 0;
|
||||
Z_Free(ss->tags.tags);
|
||||
}
|
||||
}
|
||||
|
||||
ss->extra_colormap = ss->spawn_extra_colormap;
|
||||
ss->crumblestate = CRUMBLE_NONE;
|
||||
ss->floorlightlevel = spawnss->floorlightlevel;
|
||||
ss->floorlightabsolute = spawnss->floorlightabsolute;
|
||||
ss->ceilinglightlevel = spawnss->ceilinglightlevel;
|
||||
ss->ceilinglightabsolute = spawnss->ceilinglightabsolute;
|
||||
ss->flags = spawnss->flags;
|
||||
ss->specialflags = spawnss->specialflags;
|
||||
ss->damagetype = spawnss->damagetype;
|
||||
ss->triggertag = spawnss->triggertag;
|
||||
ss->triggerer = spawnss->triggerer;
|
||||
ss->gravity = spawnss->gravity;
|
||||
ss->action = spawnss->action;
|
||||
|
||||
memcpy(ss->args, spawnss->args, NUM_SCRIPT_ARGS * sizeof(*ss->args));
|
||||
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (spawnss->stringargs[j])
|
||||
{
|
||||
len = strlen(spawnss->stringargs[j]);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
Z_Free(ss->stringargs[j]);
|
||||
ss->stringargs[j] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss->stringargs[j] = static_cast<char *>(Z_Realloc(ss->stringargs[j], len + 1, PU_LEVEL, nullptr));
|
||||
M_Memcpy(ss->stringargs[j], spawnss->stringargs[j], len);
|
||||
ss->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
ss->activation = spawnss->activation;
|
||||
ss->botController.trick = spawnss->botController.trick;
|
||||
ss->botController.flags = spawnss->botController.flags;
|
||||
ss->botController.forceAngle = spawnss->botController.forceAngle;
|
||||
|
||||
if (ss->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
for (rover = ss->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
rover->fofflags = rover->spawnflags;
|
||||
rover->alpha = rover->spawnalpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line_t *li = lines;
|
||||
line_t *spawnli = spawnlines;
|
||||
side_t *si = nullptr;
|
||||
side_t *spawnsi = nullptr;
|
||||
for (i = 0; i < numlines; i++, spawnli++, li++)
|
||||
{
|
||||
li->flags = spawnli->flags;
|
||||
li->special = spawnli->special;
|
||||
li->callcount = 0;
|
||||
|
||||
if (Tag_Compare(&li->tags, &spawnli->tags) == false)
|
||||
{
|
||||
if (spawnli->tags.count)
|
||||
{
|
||||
li->tags.count = spawnli->tags.count;
|
||||
li->tags.tags = static_cast<mtag_t *>(
|
||||
memcpy(
|
||||
Z_Realloc(
|
||||
li->tags.tags,
|
||||
spawnli->tags.count * sizeof(mtag_t),
|
||||
PU_LEVEL,
|
||||
nullptr
|
||||
),
|
||||
spawnli->tags.tags,
|
||||
spawnli->tags.count * sizeof(mtag_t)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
li->tags.count = 0;
|
||||
Z_Free(li->tags.tags);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(li->args, spawnli->args, NUM_SCRIPT_ARGS * sizeof(*li->args));
|
||||
|
||||
for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (spawnli->stringargs[j])
|
||||
{
|
||||
len = strlen(spawnli->stringargs[j]);
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
Z_Free(li->stringargs[j]);
|
||||
li->stringargs[j] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
li->stringargs[j] = static_cast<char *>(Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, nullptr));
|
||||
M_Memcpy(li->stringargs[j], spawnli->stringargs[j], len);
|
||||
li->stringargs[j][len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
li->executordelay = spawnli->executordelay;
|
||||
li->activation = spawnli->activation;
|
||||
|
||||
if (li->sidenum[0] != 0xffff)
|
||||
{
|
||||
si = &sides[li->sidenum[0]];
|
||||
spawnsi = &spawnsides[li->sidenum[0]];
|
||||
|
||||
si->textureoffset = spawnsi->textureoffset;
|
||||
si->toptexture = spawnsi->toptexture;
|
||||
si->bottomtexture = spawnsi->bottomtexture;
|
||||
si->midtexture = spawnsi->midtexture;
|
||||
}
|
||||
|
||||
if (li->sidenum[1] != 0xffff)
|
||||
{
|
||||
si = &sides[li->sidenum[1]];
|
||||
spawnsi = &spawnsides[li->sidenum[1]];
|
||||
|
||||
si->textureoffset = spawnsi->textureoffset;
|
||||
si->toptexture = spawnsi->toptexture;
|
||||
si->bottomtexture = spawnsi->bottomtexture;
|
||||
si->midtexture = spawnsi->midtexture;
|
||||
}
|
||||
}
|
||||
|
||||
Taglist_InitGlobalTables();
|
||||
}
|
||||
|
||||
// get the time
|
||||
leveltime = READUINT32(save->p);
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@
|
|||
#include "k_endcam.h"
|
||||
#include "k_credits.h"
|
||||
#include "k_objects.h"
|
||||
#include "p_deepcopy.h"
|
||||
|
||||
// Replay names have time
|
||||
#if !defined (UNDER_CE)
|
||||
|
|
@ -7535,7 +7536,6 @@ static boolean P_LoadMapFromFile(void)
|
|||
TracyCZone(__zone, true);
|
||||
|
||||
virtlump_t *textmap = vres_Find(curmapvirt, "TEXTMAP");
|
||||
size_t i;
|
||||
|
||||
udmf = textmap != NULL;
|
||||
udmf_version = 0;
|
||||
|
|
@ -7563,17 +7563,9 @@ static boolean P_LoadMapFromFile(void)
|
|||
P_WriteTextmap();
|
||||
|
||||
// Copy relevant map data for NetArchive purposes.
|
||||
spawnsectors = static_cast<sector_t*>(Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL));
|
||||
spawnlines = static_cast<line_t*>(Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL));
|
||||
spawnsides = static_cast<side_t*>(Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL));
|
||||
|
||||
memcpy(spawnsectors, sectors, numsectors * sizeof(*sectors));
|
||||
memcpy(spawnlines, lines, numlines * sizeof(*lines));
|
||||
memcpy(spawnsides, sides, numsides * sizeof(*sides));
|
||||
|
||||
for (i = 0; i < numsectors; i++)
|
||||
if (sectors[i].tags.count)
|
||||
spawnsectors[i].tags.tags = static_cast<mtag_t*>(memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t)));
|
||||
P_DeepCopySectors(&spawnsectors, §ors, numsectors);
|
||||
P_DeepCopyLines(&spawnlines, &lines, numlines);
|
||||
P_DeepCopySides(&spawnsides, &sides, numsides);
|
||||
|
||||
P_MakeMapMD5(curmapvirt, &mapmd5);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue