Properly handle stringarg memory during netsaves

- spawnsectors/lines copy over stringargs properly.
- Object thing args/stringargs aren't overwritten if there aren't any script args set.
- StringArgsEqual functions handle NULL properly.
This commit is contained in:
Sally Coolatta 2024-10-25 17:10:05 -04:00
parent 8ff2e13c7d
commit 0dbe217979
4 changed files with 116 additions and 40 deletions

View file

@ -122,6 +122,54 @@ static void copy_taglist_tags(taglist_t *target, taglist_t *source)
}
}
/*--------------------------------------------------
static void copy_stringarg(char **target, const char *source)
Make a deep copy of a string argument.
Input Arguments:-
target: Double pointer to the string to copy to.
source: The string to copy from.
Return:-
N/A
--------------------------------------------------*/
static void copy_stringarg(char **target, const char *source)
{
// stringarg memory is really freaking touchy,
// so I am being careful and being explicit
// on how it is copied over instead of just
// using strcpy or smth
if (*target != nullptr)
{
Z_Free(*target);
}
size_t len = 0;
if (source != nullptr)
{
len = strlen(source);
}
if (len > 0)
{
*target = static_cast<char *>(
memcpy(
Z_Malloc(
len + 1,
PU_LEVEL,
nullptr
),
source,
len
)
);
(*target)[len] = '\0';
}
}
/*--------------------------------------------------
static void copy_sector_callback(sector_t *target, sector_t *source)
@ -140,6 +188,11 @@ 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);
for (size_t i = 0; i < NUM_SCRIPT_STRINGARGS; i++)
{
copy_stringarg(&target->stringargs[i], source->stringargs[i]);
}
}
/*--------------------------------------------------
@ -182,6 +235,11 @@ 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);
for (size_t i = 0; i < NUM_SCRIPT_STRINGARGS; i++)
{
copy_stringarg(&target->stringargs[i], source->stringargs[i]);
}
}
/*--------------------------------------------------

View file

@ -14102,12 +14102,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
return true;
}
void P_CopyMapThingSpecialFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj)
void P_CopyMapThingBehaviorFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj)
{
size_t arg = SIZE_MAX;
mobj->special = mthing->special;
for (arg = 0; arg < NUM_MAPTHING_ARGS; arg++)
{
mobj->thing_args[arg] = mthing->thing_args[arg];
@ -14132,6 +14130,13 @@ void P_CopyMapThingSpecialFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj)
mobj->thing_stringargs[arg] = Z_Realloc(mobj->thing_stringargs[arg], len + 1, PU_LEVEL, NULL);
M_Memcpy(mobj->thing_stringargs[arg], mthing->thing_stringargs[arg], len + 1);
}
}
void P_CopyMapThingSpecialFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj)
{
size_t arg = SIZE_MAX;
mobj->special = mthing->special;
for (arg = 0; arg < NUM_SCRIPT_ARGS; arg++)
{
@ -14179,6 +14184,7 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj->tid = mthing->tid;
P_AddThingTID(mobj);
P_CopyMapThingBehaviorFieldsToMobj(mthing, mobj);
P_CopyMapThingSpecialFieldsToMobj(mthing, mobj);
if (!P_SetupSpawnedMapThing(mthing, mobj))

View file

@ -561,6 +561,7 @@ fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const f
fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y);
mobj_t *P_SpawnMapThing(mapthing_t *mthing);
void P_CopyMapThingBehaviorFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj);
void P_CopyMapThingSpecialFieldsToMobj(const mapthing_t *mthing, mobj_t *mobj);
void P_SpawnHoop(mapthing_t *mthing);
void P_SpawnItemPattern(mapthing_t *mthing);

View file

@ -2038,11 +2038,16 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn
UINT8 i;
for (i = 0; i < NUM_SCRIPT_STRINGARGS; i++)
{
if (!sc->stringargs[i])
return !spawnsc->stringargs[i];
if (strcmp(sc->stringargs[i], spawnsc->stringargs[i]))
return false;
if (sc->stringargs[i] == NULL || spawnsc->stringargs[i] == NULL)
{
if (sc->stringargs[i] != spawnsc->stringargs[i])
return false;
}
else
{
if (strcmp(sc->stringargs[i], spawnsc->stringargs[i]))
return false;
}
}
return true;
@ -2085,11 +2090,16 @@ static boolean P_LineStringArgsEqual(const line_t *li, const line_t *spawnli)
UINT8 i;
for (i = 0; i < NUM_SCRIPT_STRINGARGS; i++)
{
if (!li->stringargs[i])
return !spawnli->stringargs[i];
if (strcmp(li->stringargs[i], spawnli->stringargs[i]))
return false;
if (li->stringargs[i] == NULL || spawnli->stringargs[i] == NULL)
{
if (li->stringargs[i] != spawnli->stringargs[i])
return false;
}
else
{
if (strcmp(li->stringargs[i], spawnli->stringargs[i]))
return false;
}
}
return true;
@ -2844,19 +2854,18 @@ static boolean P_ThingArgsEqual(const mobj_t *mobj, const mapthing_t *mapthing)
if (mobj->thing_args[i] != mapthing->thing_args[i])
return false;
return true;
}
static boolean P_ThingStringArgsEqual(const mobj_t *mobj, const mapthing_t *mapthing)
{
UINT8 i;
for (i = 0; i < NUM_MAPTHING_STRINGARGS; i++)
{
if (!mobj->thing_stringargs[i])
return !mapthing->thing_stringargs[i];
if (strcmp(mobj->thing_stringargs[i], mapthing->thing_stringargs[i]))
return false;
if (mobj->thing_stringargs[i] == NULL || mapthing->thing_stringargs[i] == NULL)
{
if (mobj->thing_stringargs[i] != mapthing->thing_stringargs[i])
return false;
}
else
{
if (strcmp(mobj->thing_stringargs[i], mapthing->thing_stringargs[i]))
return false;
}
}
return true;
@ -2874,11 +2883,16 @@ static boolean P_ThingScriptEqual(const mobj_t *mobj, const mapthing_t *mapthing
for (i = 0; i < NUM_SCRIPT_STRINGARGS; i++)
{
if (!mobj->script_stringargs[i])
return !mapthing->script_stringargs[i];
if (strcmp(mobj->script_stringargs[i], mapthing->script_stringargs[i]))
return false;
if (mobj->script_stringargs[i] == NULL || mapthing->script_stringargs[i] == NULL)
{
if (mobj->script_stringargs[i] != mapthing->script_stringargs[i])
return false;
}
else
{
if (strcmp(mobj->script_stringargs[i], mapthing->script_stringargs[i]))
return false;
}
}
return true;
@ -2916,7 +2930,7 @@ typedef enum
MD_SCALE = 1<<27,
MD_DSCALE = 1<<28,
MD_ARGS = 1<<29,
MD_STRINGARGS = 1<<30,
MD__UNUSED = 1<<30,
MD_MORE = (INT32)(1U<<31)
} mobj_diff_t;
@ -3101,9 +3115,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (!P_ThingArgsEqual(mobj, mobj->spawnpoint))
diff |= MD_ARGS;
if (!P_ThingStringArgsEqual(mobj, mobj->spawnpoint))
diff |= MD_STRINGARGS;
if (!P_ThingScriptEqual(mobj, mobj->spawnpoint))
diff2 |= MD2_SPECIAL;
}
@ -3125,7 +3136,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
{
if (mobj->thing_stringargs[j] != NULL)
{
diff |= MD_STRINGARGS;
diff |= MD_ARGS;
break;
}
}
@ -3417,9 +3428,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
{
for (j = 0; j < NUM_MAPTHING_ARGS; j++)
WRITEINT32(save->p, mobj->thing_args[j]);
}
if (diff & MD_STRINGARGS)
{
for (j = 0; j < NUM_MAPTHING_STRINGARGS; j++)
{
size_t len, k;
@ -4712,9 +4721,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
{
for (j = 0; j < NUM_MAPTHING_ARGS; j++)
mobj->thing_args[j] = READINT32(save->p);
}
if (diff & MD_STRINGARGS)
{
for (j = 0; j < NUM_MAPTHING_STRINGARGS; j++)
{
size_t len = READINT32(save->p);
@ -4733,6 +4740,10 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->thing_stringargs[j][len] = '\0';
}
}
else if (mobj->spawnpoint)
{
P_CopyMapThingBehaviorFieldsToMobj(mobj->spawnpoint, mobj);
}
if (diff2 & MD2_CUSVAL)
mobj->cusval = READINT32(save->p);
if (diff2 & MD2_CVMEM)