From 42532d6bc716407c8a4f1b63b5c2964801d7c204 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 3 Oct 2025 19:44:47 -0400 Subject: [PATCH 01/24] Refactor NetSync for players This is based on stuff from SRB2Classic adjust for Blan. This uses a bunch of new functions but later I plan to switch to a _Generic for these. --- src/p_saveg.c | 1051 ++++++++++++++++++++----------------------------- src/p_saveg.h | 1 + 2 files changed, 426 insertions(+), 626 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index f0ec19a4e..d4d0dbab5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -48,6 +48,137 @@ savedata_t savedata; +UINT8 P_SyncUINT8(savebuffer_t *save, UINT8 v) +{ + if (save->write) + { + WRITEUINT8(save->p,v); + return v; + } + else + return READUINT8(save->p); +} + +SINT8 P_SyncSINT8(savebuffer_t *save, SINT8 v) +{ + if (save->write) + { + WRITESINT8(save->p,v); + return v; + } + else + return READSINT8(save->p); +} + +UINT16 P_SyncUINT16(savebuffer_t *save, UINT16 v) +{ + if (save->write) + { + WRITEUINT16(save->p, v); + return v; + } + else + return READUINT16(save->p); +} + +INT16 P_SyncINT16(savebuffer_t *save, INT16 v) +{ + if (save->write) + { + WRITEINT16(save->p, v); + return v; + } + else + return READINT16(save->p); +} + +UINT32 P_SyncUINT32(savebuffer_t *save, UINT32 v) +{ + if (save->write) + { + WRITEUINT32(save->p, v); + return v; + } + else + return READUINT32(save->p); +} + +INT32 P_SyncINT32(savebuffer_t *save, INT32 v) +{ + if (save->write) + { + WRITEINT32(save->p, v); + return v; + } + else + return READINT32(save->p); +} + +char P_SyncChar(savebuffer_t *save, char v) +{ + if (save->write) + { + WRITECHAR(save->p, v); + return v; + } + else + return READCHAR(save->p); +} + +fixed_t P_SyncFixed(savebuffer_t *save, fixed_t v) +{ + if (save->write) + { + WRITEFIXED(save->p, v); + return v; + } + else + return READFIXED(save->p); +} + +angle_t P_SyncAngle(savebuffer_t *save, angle_t v) +{ + if (save->write) + { + WRITEANGLE(save->p, v); + return v; + } + else + return READANGLE(save->p); +} + +void P_SyncStringN(savebuffer_t *save, char *s, size_t n) +{ + if (save->write) + WRITESTRINGN(save->p, s, n); + else + READSTRINGN(save->p, s, n); +} + +void P_SyncStringL(savebuffer_t *save, char *s, size_t n) +{ + if (save->write) + WRITESTRINGL(save->p, s, n); + else + READSTRINGL(save->p, s, n); +} + +void P_SyncString(savebuffer_t *save, char *s) +{ + if (save->write) + WRITESTRING(save->p, s); + else + READSTRING(save->p, s); +} + +void P_SyncMem(savebuffer_t *save, void *s, size_t n) +{ + if (save->write) + WRITEMEM(save->p, s, n); + else + READMEM(save->p, s, n); +} + // Block UINT32s to attempt to ensure that the correct data is // being sent and received #define ARCHIVEBLOCK_MISC 0x7FEEDEED @@ -92,25 +223,25 @@ static inline void P_UnArchivePlayer(savebuffer_t *save) savedata.score = READUINT32(save->p); } -static void P_NetArchivePlayers(savebuffer_t *save) +static void P_NetSyncPlayers(savebuffer_t *save) { TracyCZone(__zone, true); INT32 i, j; UINT16 flags; -// size_t q; - WRITEUINT32(save->p, ARCHIVEBLOCK_PLAYERS); + if (P_SyncUINT32(save, ARCHIVEBLOCK_PLAYERS) != ARCHIVEBLOCK_PLAYERS) + I_Error("Bad $$$.sav at archive block Players"); for (i = 0; i < MAXPLAYERS; i++) { - WRITESINT8(save->p, (SINT8)adminplayers[i]); + adminplayers[i] = (INT32)P_SyncSINT8(save, adminplayers[i]); for (j = 0; j < PWRLV_NUMTYPES; j++) { - WRITEINT16(save->p, clientpowerlevels[i][j]); + clientpowerlevels[i][j] = P_SyncINT16(save, clientpowerlevels[i][j]); } - WRITEINT16(save->p, clientPowerAdd[i]); + clientPowerAdd[i] = P_SyncINT16(save, clientPowerAdd[i]); if (!playeringame[i]) continue; @@ -119,711 +250,375 @@ static void P_NetArchivePlayers(savebuffer_t *save) // no longer send ticcmds - WRITESTRINGN(save->p, player_names[i], MAXPLAYERNAME); + P_SyncStringN(save, player_names[i], MAXPLAYERNAME); - WRITEUINT8(save->p, playerconsole[i]); - WRITEINT32(save->p, splitscreen_invitations[i]); + playerconsole[i] = P_SyncUINT8(save, playerconsole[i]); + splitscreen_invitations[i] = P_SyncINT32(save, splitscreen_invitations[i]); - WRITEANGLE(save->p, players[i].angleturn); - WRITEANGLE(save->p, players[i].aiming); - WRITEANGLE(save->p, players[i].drawangle); - WRITEANGLE(save->p, players[i].viewrollangle); - WRITEANGLE(save->p, players[i].tilt); - WRITEANGLE(save->p, players[i].awayviewaiming); - WRITEINT32(save->p, players[i].awayviewtics); + players[i].angleturn = P_SyncAngle(save, players[i].angleturn); + players[i].aiming = P_SyncAngle(save, players[i].aiming); + players[i].drawangle = P_SyncAngle(save, players[i].drawangle); + players[i].viewrollangle = P_SyncAngle(save, players[i].viewrollangle); + players[i].tilt = P_SyncAngle(save, players[i].tilt); + players[i].awayviewaiming = P_SyncAngle(save, players[i].awayviewaiming); + players[i].awayviewtics = P_SyncINT32(save, players[i].awayviewtics); - WRITEUINT8(save->p, players[i].playerstate); - WRITEUINT32(save->p, players[i].pflags); - WRITEUINT8(save->p, players[i].panim); - WRITEUINT8(save->p, players[i].spectator); - WRITEUINT32(save->p, players[i].spectatewait); + players[i].playerstate = P_SyncUINT8(save, players[i].playerstate); + players[i].pflags = P_SyncUINT32(save, players[i].pflags); + players[i].panim = P_SyncUINT8(save, players[i].panim); + players[i].spectator = P_SyncUINT8(save, players[i].spectator); + players[i].spectatewait = P_SyncUINT32(save, players[i].spectatewait); - WRITEUINT16(save->p, players[i].flashpal); - WRITEUINT16(save->p, players[i].flashcount); + players[i].flashpal = P_SyncUINT16(save, players[i].flashpal); + players[i].flashcount = P_SyncUINT16(save, players[i].flashcount); - WRITEUINT8(save->p, players[i].skincolor); - WRITEINT32(save->p, players[i].skin); - WRITEUINT32(save->p, players[i].availabilities); - WRITEUINT32(save->p, players[i].score); - WRITESINT8(save->p, players[i].lives); - WRITESINT8(save->p, players[i].xtralife); - WRITEFIXED(save->p, players[i].speed); - WRITEFIXED(save->p, players[i].lastspeed); - WRITEINT32(save->p, players[i].deadtimer); - WRITEUINT32(save->p, players[i].exiting); + players[i].skincolor = P_SyncUINT8(save, players[i].skincolor); + players[i].skin = P_SyncINT32(save, players[i].skin); + players[i].availabilities = P_SyncUINT32(save, players[i].availabilities); + players[i].score = P_SyncUINT32(save, players[i].score); + players[i].lives = P_SyncSINT8(save, players[i].lives); + players[i].xtralife = P_SyncSINT8(save, players[i].xtralife); + players[i].speed = P_SyncFixed(save, players[i].speed); + players[i].lastspeed = P_SyncFixed(save, players[i].lastspeed); + players[i].deadtimer = P_SyncINT32(save, players[i].deadtimer); + players[i].exiting = P_SyncUINT32(save, players[i].exiting); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - WRITEFIXED(save->p, players[i].cmomx); // Conveyor momx - WRITEFIXED(save->p, players[i].cmomy); // Conveyor momy - WRITEFIXED(save->p, players[i].rmomx); // "Real" momx (momx - cmomx) - WRITEFIXED(save->p, players[i].rmomy); // "Real" momy (momy - cmomy) + players[i].cmomx = P_SyncFixed(save, players[i].cmomx); // Conveyor momx + players[i].cmomy = P_SyncFixed(save, players[i].cmomy); // Conveyor momy + players[i].rmomx = P_SyncFixed(save, players[i].rmomx); // "Real" momx (momx - cmomx) + players[i].rmomy = P_SyncFixed(save, players[i].rmomy); // "Real" momy (momy - cmomy) - WRITEINT16(save->p, players[i].totalring); - WRITEUINT32(save->p, players[i].realtime); + players[i].totalring = P_SyncINT16(save, players[i].totalring); + players[i].realtime = P_SyncUINT32(save, players[i].realtime); for (j = 0; j < LAP__MAX; j++) { - WRITEUINT32(save->p, players[i].laptime[j]); + players[i].laptime[j] = P_SyncUINT32(save, players[i].laptime[j]); } - WRITEUINT8(save->p, players[i].laps); - WRITEUINT8(save->p, players[i].latestlap); - - WRITEUINT32(save->p, players[i].starposttime); - WRITEINT16(save->p, players[i].starpostx); - WRITEINT16(save->p, players[i].starposty); - WRITEINT16(save->p, players[i].starpostz); - WRITEINT32(save->p, players[i].starpostnum); - WRITEANGLE(save->p, players[i].starpostangle); - WRITEUINT8(save->p, (UINT8)players[i].starpostflip); - WRITEINT32(save->p, players[i].prevcheck); - WRITEINT32(save->p, players[i].nextcheck); + players[i].laps = P_SyncUINT8(save, players[i].laps); + players[i].latestlap = P_SyncUINT8(save, players[i].latestlap); - WRITEUINT8(save->p, players[i].ctfteam); + players[i].starposttime = P_SyncUINT32(save, players[i].starposttime); + players[i].starpostx = P_SyncINT16(save, players[i].starpostx); + players[i].starposty = P_SyncINT16(save, players[i].starposty); + players[i].starpostz = P_SyncINT16(save, players[i].starpostz); + players[i].starpostnum = P_SyncINT32(save, players[i].starpostnum); + players[i].starpostangle = P_SyncAngle(save, players[i].starpostangle); + players[i].starpostflip = P_SyncUINT8(save, (UINT8)players[i].starpostflip); + players[i].prevcheck = P_SyncINT32(save, players[i].prevcheck); + players[i].nextcheck = P_SyncINT32(save, players[i].nextcheck); - WRITEUINT8(save->p, players[i].checkskip); + players[i].ctfteam = P_SyncUINT8(save, players[i].ctfteam); - WRITEINT16(save->p, players[i].lastsidehit); - WRITEINT16(save->p, players[i].lastlinehit); + players[i].checkskip = P_SyncUINT8(save, players[i].checkskip); - WRITEINT32(save->p, players[i].onconveyor); + players[i].lastsidehit = P_SyncINT16(save, players[i].lastsidehit); + players[i].lastlinehit = P_SyncINT16(save, players[i].lastlinehit); - WRITEUINT32(save->p, players[i].jointime); - WRITEUINT32(save->p, players[i].spectatorreentry); + players[i].onconveyor = P_SyncINT32(save, players[i].onconveyor); - WRITEUINT32(save->p, players[i].grieftime); - WRITEUINT8(save->p, players[i].griefstrikes); + players[i].jointime = P_SyncUINT32(save, players[i].jointime); + players[i].spectatorreentry = P_SyncUINT32(save, players[i].spectatorreentry); - WRITEUINT8(save->p, players[i].splitscreenindex); + players[i].grieftime = P_SyncUINT32(save, players[i].grieftime); + players[i].griefstrikes = P_SyncUINT8(save, players[i].griefstrikes); - if (players[i].awayviewmobj) - flags |= AWAYVIEW; + players[i].splitscreenindex = P_SyncUINT8(save, players[i].splitscreenindex); - if (players[i].followmobj) - flags |= FOLLOWITEM; + if (save->write) + { + if (players[i].awayviewmobj) + flags |= AWAYVIEW; - if (players[i].follower) - flags |= FOLLOWER; + if (players[i].followmobj) + flags |= FOLLOWITEM; - WRITEUINT16(save->p, flags); + if (players[i].follower) + flags |= FOLLOWER; - if (flags & AWAYVIEW) - WRITEUINT32(save->p, players[i].awayviewmobj->mobjnum); + WRITEUINT16(save->p, flags); - if (flags & FOLLOWITEM) - WRITEUINT32(save->p, players[i].followmobj->mobjnum); + if (flags & AWAYVIEW) + WRITEUINT32(save->p, players[i].awayviewmobj->mobjnum); - WRITEUINT32(save->p, (UINT32)players[i].followitem); + if (flags & FOLLOWITEM) + WRITEUINT32(save->p, players[i].followmobj->mobjnum); + } + else + { + flags = READUINT16(save->p); - WRITEUINT32(save->p, players[i].charflags); + if (flags & AWAYVIEW) + players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save->p); + + if (flags & FOLLOWITEM) + players[i].followmobj = (mobj_t *)(size_t)READUINT32(save->p); + } + + players[i].followitem = P_SyncUINT32(save, (UINT32)players[i].followitem); + + players[i].charflags = P_SyncUINT32(save, players[i].charflags); // SRB2kart - WRITEUINT8(save->p, players[i].kartspeed); - WRITEUINT8(save->p, players[i].kartweight); - + players[i].kartspeed = P_SyncUINT8(save, players[i].kartspeed); + players[i].kartweight = P_SyncUINT8(save, players[i].kartweight); + for (j = 0; j < MAXPREDICTTICS; j++) { - WRITEINT16(save->p, players[i].lturn_max[j]); - WRITEINT16(save->p, players[i].rturn_max[j]); + players[i].lturn_max[j] = P_SyncINT16(save, players[i].lturn_max[j]); + players[i].rturn_max[j] = P_SyncINT16(save, players[i].rturn_max[j]); } - WRITEUINT8(save->p, players[i].followerskin); - WRITEUINT8(save->p, players[i].followerready); // booleans are really just numbers eh?? - WRITEUINT16(save->p, players[i].followercolor); - if (flags & FOLLOWER) - WRITEUINT32(save->p, players[i].follower->mobjnum); + players[i].followerskin = P_SyncUINT8(save, players[i].followerskin); + players[i].followerready = P_SyncUINT8(save, players[i].followerready); // booleans are really just numbers eh?? + players[i].followercolor = P_SyncUINT16(save, players[i].followercolor); + + if (save->write) + { + if (flags & FOLLOWER) + WRITEUINT32(save->p, players[i].follower->mobjnum); + } + else + { + if (flags & FOLLOWER) + players[i].follower->mobjnum = READUINT32(save->p); + } for (j = 0; j < NUMPOWERS; j++) - WRITEUINT16(save->p, players[i].powers[j]); + players[i].powers[j] = P_SyncUINT16(save, players[i].powers[j]); for (j = 0; j < NUMKARTSTUFF; j++) - WRITEINT32(save->p, players[i].kartstuff[j]); + players[i].kartstuff[j] = P_SyncINT32(save, players[i].kartstuff[j]); - WRITEUINT16(save->p, players[i].nocontrol); - WRITEUINT8(save->p, players[i].carry); - WRITEUINT16(save->p, players[i].dye); + players[i].nocontrol = P_SyncUINT16(save, players[i].nocontrol); + players[i].carry = P_SyncUINT8(save, players[i].carry); + players[i].dye = P_SyncUINT16(save, players[i].dye); - WRITEUINT8(save->p, players[i].position); - WRITEUINT8(save->p, players[i].oldposition); - WRITEUINT8(save->p, players[i].positiondelay); - WRITEUINT32(save->p, players[i].distancetofinish); - WRITEUINT32(save->p, players[i].distancetofinishprev); - WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint)); - WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); - WRITEUINT16(save->p, players[i].bigwaypointgap); - WRITEUINT32(save->p, players[i].airtime); - WRITEUINT8(save->p, players[i].startboost); + players[i].position = P_SyncUINT8(save, players[i].position); + players[i].oldposition = P_SyncUINT8(save, players[i].oldposition); + players[i].positiondelay = P_SyncUINT8(save, players[i].positiondelay); + players[i].distancetofinish = P_SyncUINT32(save, players[i].distancetofinish); + players[i].distancetofinishprev = P_SyncUINT32(save, players[i].distancetofinishprev); + if (save->write) + { + WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint)); + WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); + } + else + { + players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); + players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); + } + players[i].bigwaypointgap = P_SyncUINT16(save, players[i].bigwaypointgap); + players[i].airtime = P_SyncUINT32(save, players[i].airtime); + players[i].startboost = P_SyncUINT8(save, players[i].startboost); - WRITEUINT8(save->p, players[i].dropdash); - WRITEUINT8(save->p, players[i].respawn); + players[i].dropdash = P_SyncUINT8(save, players[i].dropdash); + players[i].respawn = P_SyncUINT8(save, players[i].respawn); - WRITEUINT16(save->p, players[i].flashing); - WRITEUINT16(save->p, players[i].spinouttimer); - WRITEINT32(save->p, players[i].spinoutrot); - WRITEUINT8(save->p, players[i].spinouttype); - WRITEUINT16(save->p, players[i].flipovertimer); - WRITEANGLE(save->p, players[i].flipoverangle); - WRITEINT16(save->p, players[i].squishedtimer); - WRITEUINT8(save->p, players[i].instashield); - WRITEUINT8(save->p, players[i].wipeoutslow); - WRITEUINT8(save->p, players[i].justbumped); - WRITEUINT8(save->p, players[i].noclip); + players[i].flashing = P_SyncUINT16(save, players[i].flashing); + players[i].spinouttimer = P_SyncUINT16(save, players[i].spinouttimer); + players[i].spinoutrot = P_SyncINT32(save, players[i].spinoutrot); + players[i].spinouttype = P_SyncUINT8(save, players[i].spinouttype); + players[i].flipovertimer = P_SyncUINT16(save, players[i].flipovertimer); + players[i].flipoverangle = P_SyncAngle(save, players[i].flipoverangle); + players[i].squishedtimer = P_SyncINT16(save, players[i].squishedtimer); + players[i].instashield = P_SyncUINT8(save, players[i].instashield); + players[i].wipeoutslow = P_SyncUINT8(save, players[i].wipeoutslow); + players[i].justbumped = P_SyncUINT8(save, players[i].justbumped); + players[i].noclip = P_SyncUINT8(save, players[i].noclip); - WRITESINT8(save->p, players[i].drift); - WRITESINT8(save->p, players[i].driftlock); - WRITEFIXED(save->p, players[i].driftcharge); - WRITEUINT8(save->p, players[i].driftboost); + players[i].drift = P_SyncSINT8(save, players[i].drift); + players[i].driftlock = P_SyncSINT8(save, players[i].driftlock); + players[i].driftcharge = P_SyncFixed(save, players[i].driftcharge); + players[i].driftboost = P_SyncUINT8(save, players[i].driftboost); - WRITESINT8(save->p, players[i].aizdriftstrat); - WRITEINT32(save->p, players[i].aizdrifttilt); - WRITEINT32(save->p, players[i].aizdriftturn); - WRITEFIXED(save->p, players[i].slipdashcharge); - WRITESINT8(save->p, players[i].slipdashdir); + players[i].aizdriftstrat = P_SyncSINT8(save, players[i].aizdriftstrat); + players[i].aizdrifttilt = P_SyncINT32(save, players[i].aizdrifttilt); + players[i].aizdriftturn = P_SyncINT32(save, players[i].aizdriftturn); + players[i].slipdashcharge = P_SyncFixed(save, players[i].slipdashcharge); + players[i].slipdashdir = P_SyncSINT8(save, players[i].slipdashdir); - WRITEFIXED(save->p, players[i].offroad); - WRITEFIXED(save->p, players[i].tiregrease); - WRITEUINT8(save->p, players[i].pogospring); - WRITEUINT8(save->p, players[i].brakestop); - WRITEUINT8(save->p, players[i].waterskip); - - WRITEUINT8(save->p, players[i].dashpadcooldown); + players[i].offroad = P_SyncFixed(save, players[i].offroad); + players[i].tiregrease = P_SyncFixed(save, players[i].tiregrease); + players[i].pogospring = P_SyncUINT8(save, players[i].pogospring); + players[i].brakestop = P_SyncUINT8(save, players[i].brakestop); + players[i].waterskip = P_SyncUINT8(save, players[i].waterskip); - WRITEFIXED(save->p, players[i].boostpower); - WRITEFIXED(save->p, players[i].speedboost); - WRITEFIXED(save->p, players[i].prevspeedboost); - WRITEFIXED(save->p, players[i].accelboost); - WRITEANGLE(save->p, players[i].boostangle); - WRITEUINT8(save->p, players[i].numsneakers); - WRITEUINT8(save->p, players[i].numboosts); + players[i].dashpadcooldown = P_SyncUINT8(save, players[i].dashpadcooldown); - WRITEFIXED(save->p, players[i].draftpower); - WRITEUINT16(save->p, players[i].draftleeway); - WRITESINT8(save->p, players[i].lastdraft); + players[i].boostpower = P_SyncFixed(save, players[i].boostpower); + players[i].speedboost = P_SyncFixed(save, players[i].speedboost); + players[i].prevspeedboost = P_SyncFixed(save, players[i].prevspeedboost); + players[i].accelboost = P_SyncFixed(save, players[i].accelboost); + players[i].boostangle = P_SyncAngle(save, players[i].boostangle); + players[i].numsneakers = P_SyncUINT8(save, players[i].numsneakers); + players[i].numboosts = P_SyncUINT8(save, players[i].numboosts); + + players[i].draftpower = P_SyncFixed(save, players[i].draftpower); + players[i].draftleeway = P_SyncUINT16(save, players[i].draftleeway); + players[i].lastdraft = P_SyncSINT8(save, players[i].lastdraft); // boostinfo_t - WRITEFIXED(save->p, players[i].boostinfo.stackspeedboost); - WRITEFIXED(save->p, players[i].boostinfo.nonstackspeedboost); - WRITEFIXED(save->p, players[i].boostinfo.accelboost); - WRITEUINT8(save->p, players[i].boostinfo.grade); + players[i].boostinfo.stackspeedboost = P_SyncFixed(save, players[i].boostinfo.stackspeedboost); + players[i].boostinfo.nonstackspeedboost = P_SyncFixed(save, players[i].boostinfo.nonstackspeedboost); + players[i].boostinfo.accelboost = P_SyncFixed(save, players[i].boostinfo.accelboost); + players[i].boostinfo.grade = P_SyncUINT8(save, players[i].boostinfo.grade); - WRITEUINT8(save->p, players[i].tripwireState); - WRITEUINT8(save->p, players[i].tripwirePass); - WRITEUINT16(save->p, players[i].tripwireLeniency); - WRITEUINT8(save->p, players[i].tripwireReboundDelay); + players[i].tripwireState = P_SyncUINT8(save, players[i].tripwireState); + players[i].tripwirePass = P_SyncUINT8(save, players[i].tripwirePass); + players[i].tripwireLeniency = P_SyncUINT16(save, players[i].tripwireLeniency); + players[i].tripwireReboundDelay = P_SyncUINT8(save, players[i].tripwireReboundDelay); - WRITEUINT16(save->p, players[i].itemroulette); - WRITEUINT16(save->p, players[i].previtemroulette); - WRITEUINT16(save->p, players[i].itemblink); - WRITEUINT16(save->p, players[i].itemblinkmode); - WRITEUINT8(save->p, players[i].roulettetype); + players[i].itemroulette = P_SyncUINT16(save, players[i].itemroulette); + players[i].previtemroulette = P_SyncUINT16(save, players[i].previtemroulette); + players[i].itemblink = P_SyncUINT16(save, players[i].itemblink); + players[i].itemblinkmode = P_SyncUINT16(save, players[i].itemblinkmode); + players[i].roulettetype = P_SyncUINT8(save, players[i].roulettetype); - WRITESINT8(save->p, players[i].itemtype); - WRITEUINT8(save->p, players[i].itemamount); - WRITESINT8(save->p, players[i].throwdir); + players[i].itemtype = P_SyncSINT8(save, players[i].itemtype); + players[i].itemamount = P_SyncUINT8(save, players[i].itemamount); + players[i].throwdir = P_SyncSINT8(save, players[i].throwdir); - WRITEUINT8(save->p, players[i].sadtimer); + players[i].sadtimer = P_SyncUINT8(save, players[i].sadtimer); - WRITESINT8(save->p, players[i].rings); - WRITESINT8(save->p, players[i].ringmin); - WRITESINT8(save->p, players[i].ringmax); - WRITEUINT8(save->p, players[i].pickuprings); - WRITEUINT8(save->p, players[i].ringdelay); - WRITEUINT8(save->p, players[i].ringlock); - WRITEUINT16(save->p, players[i].ringboost); - WRITEUINT16(save->p, players[i].ringtime); - WRITEUINT16(save->p, players[i].superring); - WRITEUINT8(save->p, players[i].nextringaward); - WRITEUINT8(save->p, players[i].ringvolume); - WRITEUINT8(save->p, players[i].ringtransparency); + players[i].rings = P_SyncSINT8(save, players[i].rings); + players[i].ringmin = P_SyncSINT8(save, players[i].ringmin); + players[i].ringmax = P_SyncSINT8(save, players[i].ringmax); + players[i].pickuprings = P_SyncUINT8(save, players[i].pickuprings); + players[i].ringdelay = P_SyncUINT8(save, players[i].ringdelay); + players[i].ringlock = P_SyncUINT8(save, players[i].ringlock); + players[i].ringboost = P_SyncUINT16(save, players[i].ringboost); + players[i].ringtime = P_SyncUINT16(save, players[i].ringtime); + players[i].superring = P_SyncUINT16(save, players[i].superring); + players[i].nextringaward = P_SyncUINT8(save, players[i].nextringaward); + players[i].ringvolume = P_SyncUINT8(save, players[i].ringvolume); + players[i].ringtransparency = P_SyncUINT8(save, players[i].ringtransparency); - WRITEUINT8(save->p, players[i].airdroptime); - WRITEUINT8(save->p, players[i].ringdrop); + players[i].airdroptime = P_SyncUINT8(save, players[i].airdroptime); + players[i].ringdrop = P_SyncUINT8(save, players[i].ringdrop); - WRITEUINT8(save->p, players[i].curshield); + players[i].curshield = P_SyncUINT8(save, players[i].curshield); - WRITEUINT8(save->p, players[i].bubblecool); - WRITEUINT8(save->p, players[i].bubbleblowup); - WRITEUINT8(save->p, players[i].bubblehealth); - WRITEUINT16(save->p, players[i].bubbleboost); + players[i].bubblecool = P_SyncUINT8(save, players[i].bubblecool); + players[i].bubbleblowup = P_SyncUINT8(save, players[i].bubbleblowup); + players[i].bubblehealth = P_SyncUINT8(save, players[i].bubblehealth); + players[i].bubbleboost = P_SyncUINT16(save, players[i].bubbleboost); - WRITEUINT16(save->p, players[i].flamedash); - WRITEINT32(save->p, players[i].flametimer); - WRITEUINT8(save->p, players[i].flamestore); + players[i].flamedash = P_SyncUINT16(save, players[i].flamedash); + players[i].flametimer = P_SyncINT32(save, players[i].flametimer); + players[i].flamestore = P_SyncUINT8(save, players[i].flamestore); - WRITEUINT16(save->p, players[i].hyudorotimer); - WRITESINT8(save->p, players[i].stealingtimer); + players[i].hyudorotimer = P_SyncUINT16(save, players[i].hyudorotimer); + players[i].stealingtimer = P_SyncSINT8(save, players[i].stealingtimer); - WRITEUINT16(save->p, players[i].sneakertimer); - WRITEUINT16(save->p, players[i].realsneakertimer); - WRITEUINT8(save->p, players[i].floorboost); - WRITEUINT16(save->p, players[i].chaintimer); - - WRITEUINT8(save->p, players[i].boostcharge); + players[i].sneakertimer = P_SyncUINT16(save, players[i].sneakertimer); + players[i].realsneakertimer = P_SyncUINT16(save, players[i].realsneakertimer); + players[i].floorboost = P_SyncUINT8(save, players[i].floorboost); + players[i].chaintimer = P_SyncUINT16(save, players[i].chaintimer); - WRITEFIXED(save->p, players[i].slopeboost); - WRITEFIXED(save->p, players[i].prevslopeboost); - WRITEFIXED(save->p, players[i].slopeaccel); + players[i].boostcharge = P_SyncUINT8(save, players[i].boostcharge); - WRITEINT16(save->p, players[i].growshrinktimer); - WRITEINT16(save->p, players[i].growcancel); + players[i].slopeboost = P_SyncFixed(save, players[i].slopeboost); + players[i].prevslopeboost = P_SyncFixed(save, players[i].prevslopeboost); + players[i].slopeaccel = P_SyncFixed(save, players[i].slopeaccel); - WRITEUINT16(save->p, players[i].rocketsneakertimer); + players[i].growshrinktimer = P_SyncINT16(save, players[i].growshrinktimer); + players[i].growcancel = P_SyncINT16(save, players[i].growcancel); - WRITEUINT16(save->p, players[i].invincibilitytimer); - WRITEUINT16(save->p, players[i].maxinvincibilitytime); - WRITEUINT16(save->p, players[i].invincibilitybottleneck); - WRITEINT16(save->p, players[i].invincibilitycancel); + players[i].rocketsneakertimer = P_SyncUINT16(save, players[i].rocketsneakertimer); - WRITEUINT8(save->p, players[i].eggmanexplode); - WRITESINT8(save->p, players[i].eggmanblame); + players[i].invincibilitytimer = P_SyncUINT16(save, players[i].invincibilitytimer); + players[i].maxinvincibilitytime = P_SyncUINT16(save, players[i].maxinvincibilitytime); + players[i].invincibilitybottleneck = P_SyncUINT16(save, players[i].invincibilitybottleneck); + players[i].invincibilitycancel = P_SyncINT16(save, players[i].invincibilitycancel); - WRITEUINT16(save->p, players[i].bananadrag); + players[i].eggmanexplode = P_SyncUINT8(save, players[i].eggmanexplode); + players[i].eggmanblame = P_SyncSINT8(save, players[i].eggmanblame); - WRITESINT8(save->p, players[i].lastjawztarget); - WRITEUINT8(save->p, players[i].jawztargetdelay); + players[i].bananadrag = P_SyncUINT16(save, players[i].bananadrag); - WRITEUINT8(save->p, players[i].confirmVictim); - WRITEUINT8(save->p, players[i].confirmVictimDelay); + players[i].lastjawztarget = P_SyncSINT8(save, players[i].lastjawztarget); + players[i].jawztargetdelay = P_SyncUINT8(save, players[i].jawztargetdelay); - WRITEINT32(save->p, players[i].interpoints); - WRITEUINT32(save->p, players[i].roundscore); - WRITEUINT8(save->p, players[i].emeralds); - WRITEUINT8(save->p, players[i].bumper); - WRITEINT16(save->p, players[i].karmadelay); - WRITEINT16(save->p, players[i].karmamode); - WRITEINT16(save->p, players[i].karmapoints); - WRITEINT16(save->p, players[i].wanted); + players[i].confirmVictim = P_SyncUINT8(save, players[i].confirmVictim); + players[i].confirmVictimDelay = P_SyncUINT8(save, players[i].confirmVictimDelay); - WRITESINT8(save->p, players[i].glanceDir); + players[i].interpoints = P_SyncINT32(save, players[i].interpoints); + players[i].roundscore = P_SyncUINT32(save, players[i].roundscore); + players[i].emeralds = P_SyncUINT8(save, players[i].emeralds); + players[i].bumper = P_SyncUINT8(save, players[i].bumper); + players[i].karmadelay = P_SyncINT16(save, players[i].karmadelay); + players[i].karmamode = P_SyncINT16(save, players[i].karmamode); + players[i].karmapoints = P_SyncINT16(save, players[i].karmapoints); + players[i].wanted = P_SyncINT16(save, players[i].wanted); - WRITEUINT16(save->p, players[i].breathTimer); + players[i].glanceDir = P_SyncSINT8(save, players[i].glanceDir); - WRITEUINT8(save->p, players[i].lastsafelap); - WRITEUINT8(save->p, players[i].lastsafestarpost); + players[i].breathTimer = P_SyncUINT16(save, players[i].breathTimer); - WRITEUINT8(save->p, players[i].typing_timer); - WRITEUINT8(save->p, players[i].typing_duration); + players[i].lastsafelap = P_SyncUINT8(save, players[i].lastsafelap); + players[i].lastsafestarpost = P_SyncUINT8(save, players[i].lastsafestarpost); - WRITEUINT8(save->p, players[i].kickstartaccel); + players[i].typing_timer = P_SyncUINT8(save, players[i].typing_timer); + players[i].typing_duration = P_SyncUINT8(save, players[i].typing_duration); - WRITEUINT8(save->p, players[i].itemflags); + players[i].kickstartaccel = P_SyncUINT8(save, players[i].kickstartaccel); + + players[i].itemflags = P_SyncUINT8(save, players[i].itemflags); // botvars_t - WRITEUINT8(save->p, players[i].bot); - WRITEUINT8(save->p, players[i].botvars.style); - WRITEUINT8(save->p, players[i].botvars.difficulty); - WRITEUINT8(save->p, players[i].botvars.diffincrease); - WRITEUINT8(save->p, players[i].botvars.rival); - WRITEFIXED(save->p, players[i].botvars.rubberband); - WRITEUINT16(save->p, players[i].botvars.controller); - - WRITEFIXED(save->p, players[i].outrun); - WRITEUINT8(save->p, players[i].outruntime); - - // sonicloopsvars_t - WRITEFIXED(save->p, players[i].loop.radius); - WRITEFIXED(save->p, players[i].loop.revolution); - WRITEFIXED(save->p, players[i].loop.min_revolution); - WRITEFIXED(save->p, players[i].loop.max_revolution); - WRITEANGLE(save->p, players[i].loop.yaw); - WRITEFIXED(save->p, players[i].loop.origin.x); - WRITEFIXED(save->p, players[i].loop.origin.y); - WRITEFIXED(save->p, players[i].loop.origin.z); - WRITEFIXED(save->p, players[i].loop.origin_shift.x); - WRITEFIXED(save->p, players[i].loop.origin_shift.y); - WRITEFIXED(save->p, players[i].loop.shift.x); - WRITEFIXED(save->p, players[i].loop.shift.y); - WRITEUINT8(save->p, players[i].loop.flip); - - // sonicloopcamvars_t - WRITEUINT32(save->p, players[i].loop.camera.enter_tic); - WRITEUINT32(save->p, players[i].loop.camera.exit_tic); - WRITEUINT32(save->p, players[i].loop.camera.zoom_in_speed); - WRITEUINT32(save->p, players[i].loop.camera.zoom_out_speed); - WRITEFIXED(save->p, players[i].loop.camera.dist); - WRITEANGLE(save->p, players[i].loop.camera.pan); - WRITEFIXED(save->p, players[i].loop.camera.pan_speed); - WRITEUINT32(save->p, players[i].loop.camera.pan_accel); - WRITEUINT32(save->p, players[i].loop.camera.pan_back); - - // Restored NiGHTS stuff - WRITEUINT32(save->p, players[i].bumpertime); - WRITEINT32(save->p, players[i].linkcount); - WRITEUINT32(save->p, players[i].linktimer); - WRITEINT32(save->p, players[i].maxlink); - - // Fix janky landing particle - WRITEUINT8(save->p, players[i].prevonground); - - // Wall Transfer bonus - WRITEUINT8(save->p, players[i].walltransfered); - WRITEUINT8(save->p, players[i].walltransferboost); - - } - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchivePlayers(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - INT32 i, j; - UINT16 flags; - - if (READUINT32(save->p) != ARCHIVEBLOCK_PLAYERS) - I_Error("Bad $$$.sav at archive block Players"); - - for (i = 0; i < MAXPLAYERS; i++) - { - adminplayers[i] = (INT32)READSINT8(save->p); - - for (j = 0; j < PWRLV_NUMTYPES; j++) - { - clientpowerlevels[i][j] = READINT16(save->p); - } - clientPowerAdd[i] = READINT16(save->p); - - // Do NOT memset player struct to 0 - // other areas may initialize data elsewhere - //memset(&players[i], 0, sizeof (player_t)); - if (!playeringame[i]) - continue; - - // NOTE: sending tics should (hopefully) no longer be necessary - - READSTRINGN(save->p, player_names[i], MAXPLAYERNAME); - - playerconsole[i] = READUINT8(save->p); - splitscreen_invitations[i] = READINT32(save->p); - - players[i].angleturn = READANGLE(save->p); - players[i].aiming = READANGLE(save->p); - players[i].drawangle = players[i].old_drawangle = READANGLE(save->p); - players[i].viewrollangle = READANGLE(save->p); - players[i].tilt = READANGLE(save->p); - players[i].awayviewaiming = READANGLE(save->p); - players[i].awayviewtics = READINT32(save->p); - - players[i].playerstate = READUINT8(save->p); - players[i].pflags = READUINT32(save->p); - players[i].panim = READUINT8(save->p); - players[i].spectator = READUINT8(save->p); - players[i].spectatewait = READUINT32(save->p); - - players[i].flashpal = READUINT16(save->p); - players[i].flashcount = READUINT16(save->p); - - players[i].skincolor = READUINT8(save->p); - players[i].skin = READINT32(save->p); - players[i].availabilities = READUINT32(save->p); - players[i].score = READUINT32(save->p); - players[i].lives = READSINT8(save->p); - players[i].xtralife = READSINT8(save->p); // Ring Extra Life counter - players[i].speed = READFIXED(save->p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].lastspeed = READFIXED(save->p); - players[i].deadtimer = READINT32(save->p); // End game if game over lasts too long - players[i].exiting = READUINT32(save->p); // Exitlevel timer - - //////////////////////////// - // Conveyor Belt Movement // - //////////////////////////// - players[i].cmomx = READFIXED(save->p); // Conveyor momx - players[i].cmomy = READFIXED(save->p); // Conveyor momy - players[i].rmomx = READFIXED(save->p); // "Real" momx (momx - cmomx) - players[i].rmomy = READFIXED(save->p); // "Real" momy (momy - cmomy) - - players[i].totalring = READINT16(save->p); // Total number of rings obtained for GP - players[i].realtime = READUINT32(save->p); // integer replacement for leveltime - for (j = 0; j < LAP__MAX; j++) - { - players[i].laptime[j] = READUINT32(save->p); - } - players[i].laps = READUINT8(save->p); // Number of laps (optional) - players[i].latestlap = READUINT8(save->p); - - players[i].starposttime = READUINT32(save->p); - players[i].starpostx = READINT16(save->p); - players[i].starposty = READINT16(save->p); - players[i].starpostz = READINT16(save->p); - players[i].starpostnum = READINT32(save->p); - players[i].starpostangle = READANGLE(save->p); - players[i].starpostflip = (boolean)READUINT8(save->p); - players[i].prevcheck = READINT32(save->p); - players[i].nextcheck = READINT32(save->p); - - players[i].ctfteam = READUINT8(save->p); // 1 == Red, 2 == Blue - - players[i].checkskip = READUINT8(save->p); - - players[i].lastsidehit = READINT16(save->p); - players[i].lastlinehit = READINT16(save->p); - - players[i].onconveyor = READINT32(save->p); - - players[i].jointime = READUINT32(save->p); - players[i].spectatorreentry = READUINT32(save->p); - - players[i].grieftime = READUINT32(save->p); - players[i].griefstrikes = READUINT8(save->p); - - players[i].splitscreenindex = READUINT8(save->p); - - flags = READUINT16(save->p); - - if (flags & AWAYVIEW) - players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save->p); - - if (flags & FOLLOWITEM) - players[i].followmobj = (mobj_t *)(size_t)READUINT32(save->p); - - players[i].followitem = (mobjtype_t)READUINT32(save->p); - - //SetPlayerSkinByNum(i, players[i].skin); - players[i].charflags = READUINT32(save->p); - - // SRB2kart - players[i].kartspeed = READUINT8(save->p); - players[i].kartweight = READUINT8(save->p); - - for (j = 0; j < MAXPREDICTTICS; j++) - { - players[i].lturn_max[j] = READINT16(save->p); - players[i].rturn_max[j] = READINT16(save->p); - } - - players[i].followerskin = READUINT8(save->p); - players[i].followerready = READUINT8(save->p); - players[i].followercolor = READUINT16(save->p); - if (flags & FOLLOWER) - players[i].follower = (mobj_t *)(size_t)READUINT32(save->p); - - for (j = 0; j < NUMPOWERS; j++) - players[i].powers[j] = READUINT16(save->p); - for (j = 0; j < NUMKARTSTUFF; j++) - players[i].kartstuff[j] = READINT32(save->p); - - players[i].nocontrol = READUINT16(save->p); - players[i].carry = READUINT8(save->p); - players[i].dye = READUINT16(save->p); - - players[i].position = READUINT8(save->p); - players[i].oldposition = READUINT8(save->p); - players[i].positiondelay = READUINT8(save->p); - players[i].distancetofinish = READUINT32(save->p); - players[i].distancetofinishprev = READUINT32(save->p); - players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); - - players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); - players[i].bigwaypointgap = READUINT16(save->p); - players[i].airtime = READUINT32(save->p); - players[i].startboost = READUINT8(save->p); - - players[i].dropdash = READUINT8(save->p); - players[i].respawn = READUINT8(save->p); - - players[i].flashing = READUINT16(save->p); - players[i].spinouttimer = READUINT16(save->p); - players[i].spinoutrot = READINT32(save->p); - players[i].spinouttype = READUINT8(save->p); - players[i].flipoverangle = READUINT16(save->p); - players[i].flipovertimer = READANGLE(save->p); - players[i].squishedtimer = READINT16(save->p); - players[i].instashield = READUINT8(save->p); - players[i].wipeoutslow = READUINT8(save->p); - players[i].justbumped = READUINT8(save->p); - players[i].noclip = READUINT8(save->p); - - players[i].drift = READSINT8(save->p); - players[i].driftlock = READSINT8(save->p); - players[i].driftcharge = READFIXED(save->p); - players[i].driftboost = READUINT8(save->p); - - players[i].aizdriftstrat = READSINT8(save->p); - players[i].aizdrifttilt = READINT32(save->p); - players[i].aizdriftturn = READINT32(save->p); - players[i].slipdashcharge = READFIXED(save->p); - players[i].slipdashdir = READSINT8(save->p); - - players[i].offroad = READFIXED(save->p); - players[i].tiregrease = READFIXED(save->p); - players[i].pogospring = READUINT8(save->p); - players[i].brakestop = READUINT8(save->p); - players[i].waterskip = READUINT8(save->p); - - players[i].dashpadcooldown = READUINT8(save->p); - - players[i].boostpower = READFIXED(save->p); - players[i].speedboost = READFIXED(save->p); - players[i].prevspeedboost = READFIXED(save->p); - players[i].accelboost = READFIXED(save->p); - players[i].boostangle = READANGLE(save->p); - players[i].numsneakers = READUINT8(save->p); - players[i].numboosts = READUINT8(save->p); - - players[i].draftpower = READFIXED(save->p); - players[i].draftleeway = READUINT16(save->p); - players[i].lastdraft = READSINT8(save->p); - - // boostinfo_t - players[i].boostinfo.stackspeedboost = READFIXED(save->p); - players[i].boostinfo.nonstackspeedboost = READFIXED(save->p); - players[i].boostinfo.accelboost = READFIXED(save->p); - players[i].boostinfo.grade = READUINT8(save->p); - - players[i].tripwireState = READUINT8(save->p); - players[i].tripwirePass = READUINT8(save->p); - players[i].tripwireLeniency = READUINT16(save->p); - players[i].tripwireReboundDelay = READUINT8(save->p); - - players[i].itemroulette = READUINT16(save->p); - players[i].previtemroulette = READUINT16(save->p); - players[i].itemblink = READUINT16(save->p); - players[i].itemblinkmode = READUINT16(save->p); - players[i].roulettetype = READUINT8(save->p); - - players[i].itemtype = READSINT8(save->p); - players[i].itemamount = READUINT8(save->p); - players[i].throwdir = READSINT8(save->p); - - players[i].sadtimer = READUINT8(save->p); - - players[i].rings = READSINT8(save->p); - players[i].ringmin = READSINT8(save->p); - players[i].ringmax = READSINT8(save->p); - players[i].pickuprings = READUINT8(save->p); - players[i].ringdelay = READUINT8(save->p); - players[i].ringlock = READUINT8(save->p); - players[i].ringboost = READUINT16(save->p); - players[i].ringtime = READUINT16(save->p);; - players[i].superring = READUINT16(save->p); - players[i].nextringaward = READUINT8(save->p); - players[i].ringvolume = READUINT8(save->p); - players[i].ringtransparency = READUINT8(save->p); - - players[i].airdroptime = READUINT8(save->p); - players[i].ringdrop = READUINT8(save->p); - - players[i].curshield = READUINT8(save->p); - - players[i].bubblecool = READUINT8(save->p); - players[i].bubbleblowup = READUINT8(save->p); - players[i].bubblehealth = READUINT8(save->p); - players[i].bubbleboost = READUINT16(save->p); - - players[i].flamedash = READUINT16(save->p); - players[i].flametimer = READINT32(save->p); - players[i].flamestore = READUINT8(save->p); - - players[i].hyudorotimer = READUINT16(save->p); - players[i].stealingtimer = READSINT8(save->p); - - players[i].sneakertimer = READUINT16(save->p); - players[i].realsneakertimer = READUINT16(save->p); - players[i].floorboost = READUINT8(save->p); - players[i].chaintimer = READUINT16(save->p); - - players[i].boostcharge = READUINT8(save->p); - - players[i].slopeboost = READFIXED(save->p); - players[i].prevslopeboost = READFIXED(save->p); - players[i].slopeaccel = READFIXED(save->p); - - players[i].growshrinktimer = READINT16(save->p); - players[i].growcancel = READINT16(save->p); - - players[i].rocketsneakertimer = READUINT16(save->p); - - players[i].invincibilitytimer = READUINT16(save->p); - players[i].maxinvincibilitytime = READUINT16(save->p); - players[i].invincibilitybottleneck = READUINT16(save->p); - players[i].invincibilitycancel = READINT16(save->p); - - players[i].eggmanexplode = READUINT8(save->p); - players[i].eggmanblame = READSINT8(save->p); - - players[i].bananadrag = READUINT16(save->p); - - players[i].lastjawztarget = READSINT8(save->p); - players[i].jawztargetdelay = READUINT8(save->p); - - players[i].confirmVictim = READUINT8(save->p); - players[i].confirmVictimDelay = READUINT8(save->p); - - players[i].interpoints = READINT32(save->p); - players[i].roundscore = READUINT32(save->p); - players[i].emeralds = READUINT8(save->p); - players[i].bumper = READUINT8(save->p); - players[i].karmadelay = READINT16(save->p); - players[i].karmamode = READINT16(save->p); - players[i].karmapoints = READINT16(save->p); - players[i].wanted = READINT16(save->p); - - players[i].glanceDir = READSINT8(save->p); - - players[i].breathTimer = READUINT16(save->p); - - players[i].lastsafelap = READUINT8(save->p); - players[i].lastsafestarpost = READUINT8(save->p); - - players[i].typing_timer = READUINT8(save->p); - players[i].typing_duration = READUINT8(save->p); - - players[i].kickstartaccel = READUINT8(save->p); - - players[i].itemflags = READUINT8(save->p); - - // botvars_t - players[i].bot = READUINT8(save->p); - players[i].botvars.style = READUINT8(save->p); - players[i].botvars.difficulty = READUINT8(save->p); - players[i].botvars.diffincrease = READUINT8(save->p); - players[i].botvars.rival = (boolean)READUINT8(save->p); - players[i].botvars.rubberband = READFIXED(save->p); - players[i].botvars.controller = READUINT16(save->p); - - players[i].outrun = READFIXED(save->p); - players[i].outruntime = READUINT8(save->p); + players[i].bot = P_SyncUINT8(save, players[i].bot); + players[i].botvars.style = P_SyncUINT8(save, players[i].botvars.style); + players[i].botvars.difficulty = P_SyncUINT8(save, players[i].botvars.difficulty); + players[i].botvars.diffincrease = P_SyncUINT8(save, players[i].botvars.diffincrease); + players[i].botvars.rival = P_SyncUINT8(save, players[i].botvars.rival); + players[i].botvars.rubberband = P_SyncFixed(save, players[i].botvars.rubberband); + players[i].botvars.controller = P_SyncUINT16(save, players[i].botvars.controller); + + players[i].outrun = P_SyncFixed(save, players[i].outrun); + players[i].outruntime = P_SyncUINT8(save, players[i].outruntime); // sonicloopsvars_t - players[i].loop.radius = READFIXED(save->p); - players[i].loop.revolution = READFIXED(save->p); - players[i].loop.min_revolution = READFIXED(save->p); - players[i].loop.max_revolution = READFIXED(save->p); - players[i].loop.yaw = READANGLE(save->p); - players[i].loop.origin.x = READFIXED(save->p); - players[i].loop.origin.y = READFIXED(save->p); - players[i].loop.origin.z = READFIXED(save->p); - players[i].loop.origin_shift.x = READFIXED(save->p); - players[i].loop.origin_shift.y = READFIXED(save->p); - players[i].loop.shift.x = READFIXED(save->p); - players[i].loop.shift.y = READFIXED(save->p); - players[i].loop.flip = READUINT8(save->p); + players[i].loop.radius = P_SyncFixed(save, players[i].loop.radius); + players[i].loop.revolution = P_SyncFixed(save, players[i].loop.revolution); + players[i].loop.min_revolution = P_SyncFixed(save, players[i].loop.min_revolution); + players[i].loop.max_revolution = P_SyncFixed(save, players[i].loop.max_revolution); + players[i].loop.yaw = P_SyncAngle(save, players[i].loop.yaw); + players[i].loop.origin.x = P_SyncFixed(save, players[i].loop.origin.x); + players[i].loop.origin.y = P_SyncFixed(save, players[i].loop.origin.y); + players[i].loop.origin.z = P_SyncFixed(save, players[i].loop.origin.z); + players[i].loop.origin_shift.x = P_SyncFixed(save, players[i].loop.origin_shift.x); + players[i].loop.origin_shift.y = P_SyncFixed(save, players[i].loop.origin_shift.y); + players[i].loop.shift.x = P_SyncFixed(save, players[i].loop.shift.x); + players[i].loop.shift.y = P_SyncFixed(save, players[i].loop.shift.y); + players[i].loop.flip = P_SyncUINT8(save, players[i].loop.flip); // sonicloopcamvars_t - players[i].loop.camera.enter_tic = READUINT32(save->p); - players[i].loop.camera.exit_tic = READUINT32(save->p); - players[i].loop.camera.zoom_in_speed = READUINT32(save->p); - players[i].loop.camera.zoom_out_speed = READUINT32(save->p); - players[i].loop.camera.dist = READFIXED(save->p); - players[i].loop.camera.pan = READANGLE(save->p); - players[i].loop.camera.pan_speed = READFIXED(save->p); - players[i].loop.camera.pan_accel = READUINT32(save->p); - players[i].loop.camera.pan_back = READUINT32(save->p); - + players[i].loop.camera.enter_tic = P_SyncUINT32(save, players[i].loop.camera.enter_tic); + players[i].loop.camera.exit_tic = P_SyncUINT32(save, players[i].loop.camera.exit_tic); + players[i].loop.camera.zoom_in_speed = P_SyncUINT32(save, players[i].loop.camera.zoom_in_speed); + players[i].loop.camera.zoom_out_speed = P_SyncUINT32(save, players[i].loop.camera.zoom_out_speed); + players[i].loop.camera.dist = P_SyncFixed(save, players[i].loop.camera.dist); + players[i].loop.camera.pan = P_SyncAngle(save, players[i].loop.camera.pan); + players[i].loop.camera.pan_speed = P_SyncFixed(save, players[i].loop.camera.pan_speed); + players[i].loop.camera.pan_accel = P_SyncUINT32(save, players[i].loop.camera.pan_accel); + players[i].loop.camera.pan_back = P_SyncUINT32(save, players[i].loop.camera.pan_back); // Restored NiGHTS stuff - players[i].bumpertime = READUINT32(save->p); - players[i].linkcount = READINT32(save->p); - players[i].linktimer = READUINT32(save->p); - players[i].maxlink = READINT32(save->p); + players[i].bumpertime = P_SyncUINT32(save, players[i].bumpertime); + players[i].linkcount = P_SyncINT32(save, players[i].linkcount); + players[i].linktimer = P_SyncUINT32(save, players[i].linktimer); + players[i].maxlink = P_SyncINT32(save, players[i].maxlink); // Fix janky landing particle - players[i].prevonground = (boolean)READUINT8(save->p); + players[i].prevonground = P_SyncUINT8(save, players[i].prevonground); // Wall Transfer bonus - players[i].walltransfered = (boolean)READUINT8(save->p); - players[i].walltransferboost = READUINT8(save->p); + players[i].walltransfered = P_SyncUINT8(save, players[i].walltransfered); + players[i].walltransferboost = P_SyncUINT8(save, players[i].walltransferboost); - //players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point } TracyCZoneEnd(__zone); } @@ -5944,6 +5739,8 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) mobj_t *mobj; UINT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise + save->write = true; + CV_SaveNetVars(&save->p); P_NetArchiveMisc(save, resending); @@ -5964,7 +5761,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) } } - P_NetArchivePlayers(save); + P_NetSyncPlayers(save); P_NetArchiveParties(save); if (gamestate == GS_LEVEL) @@ -6011,10 +5808,12 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) { TracyCZone(__zone, true); + save->write = false; + CV_LoadNetVars(&save->p); if (!P_NetUnArchiveMisc(save,reloading)) return false; - P_NetUnArchivePlayers(save); + P_NetSyncPlayers(save); P_NetUnArchiveParties(save); if (gamestate == GS_LEVEL) diff --git a/src/p_saveg.h b/src/p_saveg.h index ef35872cc..a57578bc2 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -51,6 +51,7 @@ struct savebuffer_t UINT8 *p; UINT8 *end; size_t size; + boolean write; }; boolean P_SaveBufferZAlloc(savebuffer_t *save, size_t alloc_size, INT32 tag, void *user); From 4e8bb42fc5932f0c18038d45ef6dc25d190c7e96 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 3 Oct 2025 20:54:05 -0400 Subject: [PATCH 02/24] Refactor NetSync for misc --- src/p_saveg.c | 843 +++++++++++++++++++++----------------------------- 1 file changed, 354 insertions(+), 489 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index d4d0dbab5..61bd97040 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5100,211 +5100,51 @@ static inline void P_UnArchiveSPGame(savebuffer_t *save, INT16 mapoverride) TracyCZoneEnd(__zone); } -static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) +static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) { TracyCZone(__zone, true); - size_t i; + size_t i, j; + size_t numTasks; + const INT16 prevgamemap = gamemap; - WRITEUINT32(save->p, ARCHIVEBLOCK_MISC); + if (P_SyncUINT32(save, ARCHIVEBLOCK_MISC) != ARCHIVEBLOCK_MISC) + I_Error("Bad $$$.sav at archive block Misc"); if (resending) - WRITEUINT32(save->p, gametic); - WRITEINT16(save->p, gamemap); + gametic = P_SyncUINT32(save, gametic); - if (gamestate != GS_LEVEL) - WRITEINT16(save->p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers + gamemap = P_SyncINT16(save, gamemap); + + if (save->write) + { + if (gamestate != GS_LEVEL) + WRITEINT16(save->p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers + else + WRITEINT16(save->p, gamestate); + } else - WRITEINT16(save->p, gamestate); - WRITEINT16(save->p, gametype); + { + if (!gamemap || gamemap > nummapheaders || !mapheaderinfo[gamemap-1]) + I_Error("P_NetUnArchiveMisc: Internal map ID %d not found (nummapheaders = %d)", gamemap-1, nummapheaders); + // tell the sound code to reset the music since we're skipping what + // normally sets this flag + if (!resending) + mapmusflags |= MUSIC_RELOADRESET; + G_SetGamestate(READINT16(save->p)); + } + + gametype = P_SyncINT16(save, gametype); + + if (save->write) { UINT32 pig = 0; for (i = 0; i < MAXPLAYERS; i++) pig |= (playeringame[i] != 0)<p, pig); } - - WRITEUINT32(save->p, P_GetRandSeed()); - - WRITEUINT32(save->p, tokenlist); - - WRITEUINT8(save->p, encoremode); - WRITEUINT8(save->p, mapmusrng); - - WRITEUINT32(save->p, leveltime); - WRITEINT16(save->p, lastmap); - WRITEUINT16(save->p, bossdisabled); - WRITEUINT8(save->p, ringsactive); - WRITEUINT8(save->p, stackingactive); - WRITEUINT8(save->p, chainingactive); - WRITEUINT8(save->p, slipdashactive); - WRITEUINT8(save->p, purpledriftactive); - WRITEUINT8(save->p, slopeboostactive); - WRITEUINT8(save->p, draftingactive); - WRITEUINT8(save->p, airdropactive); - WRITEUINT8(save->p, bumpsparkactive); - - for (i = 0; i < 12; i++) - { - WRITEINT16(save->p, votelevels[i][0]); - WRITEINT16(save->p, votelevels[i][1]); - } - - for (i = 0; i < MAXPLAYERS; i++) - WRITESINT8(save->p, votes[i]); - - WRITESINT8(save->p, pickedvote); - - WRITEUINT16(save->p, emeralds); - { - UINT8 globools = 0; - if (stagefailed) - globools |= 1; - if (stoppedclock) - globools |= (1<<1); - WRITEUINT8(save->p, globools); - } - - WRITEUINT32(save->p, token); - WRITEUINT32(save->p, bluescore); - WRITEUINT32(save->p, redscore); - - WRITEUINT16(save->p, skincolor_redteam); - WRITEUINT16(save->p, skincolor_blueteam); - WRITEUINT16(save->p, skincolor_redring); - WRITEUINT16(save->p, skincolor_bluering); - - WRITEINT32(save->p, modulothing); - - WRITEINT16(save->p, autobalance); - WRITEINT16(save->p, teamscramble); - - for (i = 0; i < MAXPLAYERS; i++) - WRITEINT16(save->p, scrambleplayers[i]); - - for (i = 0; i < MAXPLAYERS; i++) - WRITEINT16(save->p, scrambleteams[i]); - - WRITEINT16(save->p, scrambletotal); - WRITEINT16(save->p, scramblecount); - - WRITEUINT32(save->p, racecountdown); - WRITEUINT32(save->p, exitcountdown); - - // exitcondition_t - WRITEUINT8(save->p, g_exit.losing); - WRITEUINT8(save->p, g_exit.retry); - WRITEUINT8(save->p, g_exit.hasfinished); - - WRITEFIXED(save->p, gravity); - WRITEFIXED(save->p, mapobjectscale); - - // SRB2kart - WRITEINT32(save->p, nummapboxes); - WRITEINT32(save->p, numgotboxes); - WRITEUINT8(save->p, numtargets); - WRITEUINT8(save->p, itembreaker); - - WRITEUINT8(save->p, gamespeed); - WRITEUINT8(save->p, numlaps); - WRITEUINT8(save->p, franticitems); - WRITEUINT8(save->p, comeback); - - WRITESINT8(save->p, speedscramble); - WRITESINT8(save->p, encorescramble); - - - // WANTED system - WRITESINT8(save->p, mostwanted); - for (i = 0; i < 4; i++) - WRITESINT8(save->p, battlewanted[i]); - - WRITEUINT32(save->p, wantedcalcdelay); - WRITEUINT32(save->p, indirectitemcooldown); - WRITEUINT32(save->p, hyubgone); - WRITEUINT32(save->p, mapreset); - - WRITEUINT8(save->p, spectateGriefed); - - WRITEUINT8(save->p, thwompsactive); - WRITEUINT8(save->p, lastLowestLap); - WRITESINT8(save->p, spbplace); - WRITEUINT8(save->p, startedInFreePlay); - - WRITEUINT32(save->p, introtime); - WRITEUINT32(save->p, starttime); - - WRITEINT32(save->p, hyudorotime); - WRITEINT32(save->p, stealtime); - WRITEINT32(save->p, sneakertime); - WRITEINT32(save->p, waterpaneltime); - WRITEINT32(save->p, itemtime); - WRITEINT32(save->p, bubbletime); - WRITEINT32(save->p, comebacktime); - WRITEINT32(save->p, bumptime); - WRITEINT32(save->p, greasetics); - WRITEINT32(save->p, wipeoutslowtime); - WRITEINT32(save->p, wantedreduce); - WRITEINT32(save->p, wantedfrequency); - - WRITEUINT32(save->p, timelimitintics); - WRITEUINT32(save->p, extratimeintics); - WRITEUINT32(save->p, secretextratime); - - // Is it paused? - if (paused) - WRITEUINT8(save->p, 0x2f); else - WRITEUINT8(save->p, 0x2e); - - // Only the server uses this, but it - // needs synched for remote admins anyway. - WRITEUINT32(save->p, schedule_len); - for (i = 0; i < schedule_len; i++) - { - scheduleTask_t *task = schedule[i]; - WRITEINT16(save->p, task->basetime); - WRITEINT16(save->p, task->timer); - WRITESTRING(save->p, task->command); - } - - WRITEUINT32(save->p, cht_debug); - - TracyCZoneEnd(__zone); -} - -FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) -{ - TracyCZone(__zone, true); - - size_t i, j; - size_t numTasks; - - const INT16 prevgamemap = gamemap; - - if (READUINT32(save->p) != ARCHIVEBLOCK_MISC) - I_Error("Bad $$$.sav at archive block Misc"); - - if (reloading) - gametic = READUINT32(save->p); - - gamemap = READINT16(save->p); - - // gamemap changed; we assume that its map header is always valid, - // so make it so - if (!gamemap || gamemap > nummapheaders || !mapheaderinfo[gamemap-1]) - I_Error("P_NetUnArchiveMisc: Internal map ID %d not found (nummapheaders = %d)", gamemap-1, nummapheaders); - - // tell the sound code to reset the music since we're skipping what - // normally sets this flag - if (!reloading) - mapmusflags |= MUSIC_RELOADRESET; - - G_SetGamestate(READINT16(save->p)); - - gametype = READINT16(save->p); - { UINT32 pig = READUINT32(save->p); for (i = 0; i < MAXPLAYERS; i++) @@ -5314,359 +5154,384 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool } } - P_SetRandSeed(READUINT32(save->p)); + P_SetRandSeed(P_SyncUINT32(save, P_GetRandSeed())); - tokenlist = READUINT32(save->p); + tokenlist = P_SyncUINT32(save, tokenlist); - encoremode = (boolean)READUINT8(save->p); - - mapmusrng = READUINT8(save->p); + encoremode = P_SyncUINT8(save, encoremode); + mapmusrng = P_SyncUINT8(save, mapmusrng); - // Only reload the level during a gamestate reload - // if the map is horribly mismatched somehow. Minor - // differences in level state are already handled - // by other parts of the reload, so doing this - // on *every* reload wastes lots of time that we - // will need for rollback down the road. - if (!reloading || prevgamemap != gamemap) + if (!save->write) { - if (!P_LoadLevel(true, reloading)) + // Only reload the level during a gamestate reload + // if the map is horribly mismatched somehow. Minor + // differences in level state are already handled + // by other parts of the reload, so doing this + // on *every* reload wastes lots of time that we + // will need for rollback down the road. + if (!resending || prevgamemap != gamemap) { - CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); - return false; + if (!P_LoadLevel(true, resending)) + { + CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); + 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 = + memcpy( + Z_Realloc( + ss->tags.tags, + spawnss->tags.count * sizeof(mtag_t), + PU_LEVEL, + NULL + ), + 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] = NULL; + } + else + { + ss->stringargs[j] = Z_Realloc(ss->stringargs[j], len + 1, PU_LEVEL, NULL); + M_Memcpy(ss->stringargs[j], spawnss->stringargs[j], len); + ss->stringargs[j][len] = '\0'; + } + } + + ss->activation = spawnss->activation; + 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 = NULL; + side_t *spawnsi = NULL; + 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 = + memcpy( + Z_Realloc( + li->tags.tags, + spawnli->tags.count * sizeof(mtag_t), + PU_LEVEL, + NULL + ), + 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] = NULL; + } + else + { + li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); + 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(); } } - 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 = - memcpy( - Z_Realloc( - ss->tags.tags, - spawnss->tags.count * sizeof(mtag_t), - PU_LEVEL, - NULL - ), - 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] = NULL; - } - else - { - ss->stringargs[j] = Z_Realloc(ss->stringargs[j], len + 1, PU_LEVEL, NULL); - M_Memcpy(ss->stringargs[j], spawnss->stringargs[j], len); - ss->stringargs[j][len] = '\0'; - } - } - - ss->activation = spawnss->activation; - 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 = NULL; - side_t *spawnsi = NULL; - 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 = - memcpy( - Z_Realloc( - li->tags.tags, - spawnli->tags.count * sizeof(mtag_t), - PU_LEVEL, - NULL - ), - 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] = NULL; - } - else - { - li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); - 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); - lastmap = READINT16(save->p); - bossdisabled = READUINT16(save->p); - ringsactive = READUINT8(save->p); - stackingactive = READUINT8(save->p); - chainingactive = READUINT8(save->p); - slipdashactive = READUINT8(save->p); - purpledriftactive = READUINT8(save->p); - slopeboostactive = READUINT8(save->p); - draftingactive = READUINT8(save->p); - airdropactive = READUINT8(save->p); - bumpsparkactive = READUINT8(save->p); + leveltime = P_SyncUINT32(save, leveltime); + lastmap = P_SyncINT16(save, lastmap); + bossdisabled = P_SyncUINT16(save, bossdisabled); + ringsactive = P_SyncUINT8(save, ringsactive); + stackingactive = P_SyncUINT8(save, stackingactive); + chainingactive = P_SyncUINT8(save, chainingactive); + slipdashactive = P_SyncUINT8(save, slipdashactive); + purpledriftactive = P_SyncUINT8(save, purpledriftactive); + slopeboostactive = P_SyncUINT8(save, slopeboostactive); + draftingactive = P_SyncUINT8(save, draftingactive); + airdropactive = P_SyncUINT8(save, airdropactive); + bumpsparkactive = P_SyncUINT8(save, bumpsparkactive); for (i = 0; i < 12; i++) { - votelevels[i][0] = READINT16(save->p); - votelevels[i][1] = READINT16(save->p); + votelevels[i][0] = P_SyncINT16(save, votelevels[i][0]); + votelevels[i][1] = P_SyncINT16(save, votelevels[i][1]); } for (i = 0; i < MAXPLAYERS; i++) - votes[i] = READSINT8(save->p); + votes[i] = P_SyncSINT8(save, votes[i]); - pickedvote = READSINT8(save->p); + pickedvote = P_SyncSINT8(save, pickedvote); - emeralds = READUINT16(save->p); + emeralds = P_SyncUINT16(save, emeralds); + if (save->write) + { + UINT8 globools = 0; + if (stagefailed) + globools |= 1; + if (stoppedclock) + globools |= (1<<1); + WRITEUINT8(save->p, globools); + } + else { UINT8 globools = READUINT8(save->p); stagefailed = !!(globools & 1); stoppedclock = !!(globools & (1<<1)); } - token = READUINT32(save->p); - bluescore = READUINT32(save->p); - redscore = READUINT32(save->p); + token = P_SyncUINT32(save, token); + bluescore = P_SyncUINT32(save, bluescore); + redscore = P_SyncUINT32(save, redscore); - skincolor_redteam = READUINT16(save->p); - skincolor_blueteam = READUINT16(save->p); - skincolor_redring = READUINT16(save->p); - skincolor_bluering = READUINT16(save->p); + skincolor_redteam = P_SyncUINT16(save, skincolor_redteam); + skincolor_blueteam = P_SyncUINT16(save, skincolor_blueteam); + skincolor_redring = P_SyncUINT16(save, skincolor_redring); + skincolor_bluering = P_SyncUINT16(save, skincolor_bluering); - modulothing = READINT32(save->p); + modulothing = P_SyncINT32(save, modulothing); - autobalance = READINT16(save->p); - teamscramble = READINT16(save->p); + autobalance = P_SyncINT16(save, autobalance); + teamscramble = P_SyncINT16(save, teamscramble); for (i = 0; i < MAXPLAYERS; i++) - scrambleplayers[i] = READINT16(save->p); + scrambleplayers[i] = P_SyncINT16(save, scrambleplayers[i]); for (i = 0; i < MAXPLAYERS; i++) - scrambleteams[i] = READINT16(save->p); + scrambleteams[i] = P_SyncINT16(save, scrambleteams[i]); - scrambletotal = READINT16(save->p); - scramblecount = READINT16(save->p); + scrambletotal = P_SyncINT16(save, scrambletotal); + scramblecount = P_SyncINT16(save, scramblecount); - racecountdown = READUINT32(save->p); - exitcountdown = READUINT32(save->p); + racecountdown = P_SyncUINT32(save, racecountdown); + exitcountdown = P_SyncUINT32(save, exitcountdown); // exitcondition_t - g_exit.losing = READUINT8(save->p); - g_exit.retry = READUINT8(save->p); - g_exit.hasfinished = READUINT8(save->p); + g_exit.losing = P_SyncUINT8(save, g_exit.losing); + g_exit.retry = P_SyncUINT8(save, g_exit.retry); + g_exit.hasfinished = P_SyncUINT8(save, g_exit.hasfinished); - gravity = READFIXED(save->p); - mapobjectscale = READFIXED(save->p); + gravity = P_SyncFixed(save, gravity); + mapobjectscale = P_SyncFixed(save, mapobjectscale); // SRB2kart - nummapboxes = READINT32(save->p); - numgotboxes = READINT32(save->p); - numtargets = READUINT8(save->p); - itembreaker = (boolean)READUINT8(save->p); + nummapboxes = P_SyncINT32(save, nummapboxes); + numgotboxes = P_SyncINT32(save, numgotboxes); + numtargets = P_SyncUINT8(save, numtargets); + itembreaker = P_SyncUINT8(save, itembreaker); - gamespeed = READUINT8(save->p); - numlaps = READUINT8(save->p); - franticitems = (boolean)READUINT8(save->p); - comeback = (boolean)READUINT8(save->p); + gamespeed = P_SyncUINT8(save, gamespeed); + numlaps = P_SyncUINT8(save, numlaps); + franticitems = P_SyncUINT8(save, franticitems); + comeback = P_SyncUINT8(save, comeback); - speedscramble = READSINT8(save->p); - encorescramble = READSINT8(save->p); + speedscramble = P_SyncSINT8(save, speedscramble); + encorescramble = P_SyncSINT8(save, encorescramble); - mostwanted = READSINT8(save->p); + // WANTED system + mostwanted = P_SyncSINT8(save, mostwanted); for (i = 0; i < 4; i++) - battlewanted[i] = READSINT8(save->p); + battlewanted[i] = P_SyncSINT8(save, battlewanted[i]); - wantedcalcdelay = READUINT32(save->p); - hyubgone = READUINT32(save->p); - indirectitemcooldown = READUINT32(save->p); - mapreset = READUINT32(save->p); + wantedcalcdelay = P_SyncUINT32(save, wantedcalcdelay); + indirectitemcooldown = P_SyncUINT32(save, indirectitemcooldown); + hyubgone = P_SyncUINT32(save, hyubgone); + mapreset = P_SyncUINT32(save, mapreset); - spectateGriefed = READUINT8(save->p); + spectateGriefed = P_SyncUINT8(save, spectateGriefed); - thwompsactive = (boolean)READUINT8(save->p); - lastLowestLap = READUINT8(save->p); - spbplace = READSINT8(save->p); - startedInFreePlay = READUINT8(save->p); + thwompsactive = P_SyncUINT8(save, thwompsactive); + lastLowestLap = P_SyncUINT8(save, lastLowestLap); + spbplace = P_SyncSINT8(save, spbplace); + startedInFreePlay = P_SyncUINT8(save, startedInFreePlay); - introtime = READUINT32(save->p); - starttime = READUINT32(save->p); + introtime = P_SyncUINT32(save, introtime); + starttime = P_SyncUINT32(save, starttime); - hyudorotime = READINT32(save->p); - stealtime = READINT32(save->p); - sneakertime = READINT32(save->p); - waterpaneltime = READINT32(save->p); - itemtime = READINT32(save->p); - bubbletime = READINT32(save->p); - comebacktime = READINT32(save->p); - bumptime = READINT32(save->p); - greasetics = READINT32(save->p); - wipeoutslowtime = READINT32(save->p); - wantedreduce = READINT32(save->p); - wantedfrequency = READINT32(save->p); - - timelimitintics = READUINT32(save->p); - extratimeintics = READUINT32(save->p); - secretextratime = READUINT32(save->p); + hyudorotime = P_SyncINT32(save, hyudorotime); + stealtime = P_SyncINT32(save, stealtime); + sneakertime = P_SyncINT32(save, sneakertime); + waterpaneltime = P_SyncINT32(save, waterpaneltime); + itemtime = P_SyncINT32(save, itemtime); + bubbletime = P_SyncINT32(save, bubbletime); + comebacktime = P_SyncINT32(save, comebacktime); + bumptime = P_SyncINT32(save, bumptime); + greasetics = P_SyncINT32(save, greasetics); + wipeoutslowtime = P_SyncINT32(save, wipeoutslowtime); + wantedreduce = P_SyncINT32(save, wantedreduce); + wantedfrequency = P_SyncINT32(save, wantedfrequency); - // Is it paused? - if (READUINT8(save->p) == 0x2f) - paused = true; + timelimitintics = P_SyncUINT32(save, timelimitintics); + extratimeintics = P_SyncUINT32(save, extratimeintics); + secretextratime = P_SyncUINT32(save, secretextratime); - // Only the server uses this, but it - // needs synched for remote admins anyway. - Schedule_Clear(); + paused = P_SyncUINT8(save, paused); - numTasks = READUINT32(save->p); - for (i = 0; i < numTasks; i++) + if (save->write) { - INT16 basetime; - INT16 timer; - char command[MAXTEXTCMD]; + // Only the server uses this, but it + // needs synched for remote admins anyway. + WRITEUINT32(save->p, schedule_len); + for (i = 0; i < schedule_len; i++) + { + scheduleTask_t *task = schedule[i]; + WRITEINT16(save->p, task->basetime); + WRITEINT16(save->p, task->timer); + WRITESTRING(save->p, task->command); + } + } + else + { + // Only the server uses this, but it + // needs synched for remote admins anyway. + Schedule_Clear(); - basetime = READINT16(save->p); - timer = READINT16(save->p); - READSTRING(save->p, command); + numTasks = READUINT32(save->p); + for (i = 0; i < numTasks; i++) + { + INT16 basetime; + INT16 timer; + char command[MAXTEXTCMD]; - Schedule_Add(basetime, timer, command); + basetime = READINT16(save->p); + timer = READINT16(save->p); + READSTRING(save->p, command); + + Schedule_Add(basetime, timer, command); + } } - cht_debug = READUINT32(save->p); - - TracyCZoneEnd(__zone); + cht_debug = P_SyncUINT32(save, cht_debug); return true; + TracyCZoneEnd(__zone); } static inline void P_ArchiveLuabanksAndConsistency(savebuffer_t *save) @@ -5742,7 +5607,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) save->write = true; CV_SaveNetVars(&save->p); - P_NetArchiveMisc(save, resending); + P_NetSyncMisc(save, resending); // Assign the mobjnumber for pointer tracking if (gamestate == GS_LEVEL) @@ -5811,7 +5676,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) save->write = false; CV_LoadNetVars(&save->p); - if (!P_NetUnArchiveMisc(save,reloading)) + if (!P_NetSyncMisc(save,reloading)) return false; P_NetSyncPlayers(save); P_NetUnArchiveParties(save); From 944cfa0cc9fe1d5f781f23bb7279a4655c7953c3 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 3 Oct 2025 21:26:28 -0400 Subject: [PATCH 03/24] Refactor NetSync for Parties --- src/p_saveg.c | 84 ++++++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 61bd97040..ab2c54c02 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -623,62 +623,58 @@ static void P_NetSyncPlayers(savebuffer_t *save) TracyCZoneEnd(__zone); } -static void P_NetArchiveParties(savebuffer_t *save) +static void P_NetSyncParties(savebuffer_t *save) { TracyCZone(__zone, true); INT32 i, k; UINT8 partySize; - WRITEUINT32(save->p, ARCHIVEBLOCK_PARTIES); + if (P_SyncUINT32(save, ARCHIVEBLOCK_PARTIES) != ARCHIVEBLOCK_PARTIES) + I_Error("Bad $$$.sav at archive block Parties"); - for (i = 0; i < MAXPLAYERS; i++) + if (!save->write) { - if (!playeringame[i]) - continue; - - partySize = G_PartySize(i); - - WRITEUINT8(save->p, partySize); - - for (k = 0; k < partySize; ++k) + for (i = 0; i < MAXPLAYERS; i++) { - WRITEUINT8(save->p, G_PartyMember(i, k)); + if (!playeringame[i]) + continue; + + G_DestroyParty(i); + G_BuildLocalSplitscreenParty(i); } } - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveParties(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - INT32 i, k; - UINT8 partySize; - - if (READUINT32(save->p) != ARCHIVEBLOCK_PARTIES) - I_Error("Bad $$$.sav at archive block Parties"); - - for (i = 0; i < MAXPLAYERS; i++) + if (save->write) { - if (!playeringame[i]) - continue; - - G_DestroyParty(i); - G_BuildLocalSplitscreenParty(i); - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - partySize = READUINT8(save->p); - - for (k = 0; k < partySize; ++k) + for (i = 0; i < MAXPLAYERS; i++) { - G_JoinParty(i, READUINT8(save->p)); + if (!playeringame[i]) + continue; + + partySize = G_PartySize(i); + + WRITEUINT8(save->p, partySize); + + for (k = 0; k < partySize; ++k) + { + WRITEUINT8(save->p, G_PartyMember(i, k)); + } + } + } + else + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + partySize = READUINT8(save->p); + + for (k = 0; k < partySize; ++k) + { + G_JoinParty(i, READUINT8(save->p)); + } } } @@ -5627,7 +5623,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) } P_NetSyncPlayers(save); - P_NetArchiveParties(save); + P_NetSyncParties(save); if (gamestate == GS_LEVEL) { @@ -5679,7 +5675,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) if (!P_NetSyncMisc(save,reloading)) return false; P_NetSyncPlayers(save); - P_NetUnArchiveParties(save); + P_NetSyncParties(save); if (gamestate == GS_LEVEL) { From 17f0c6222f6a1126d2079e69decc564d9961014c Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 09:58:41 -0400 Subject: [PATCH 04/24] Refactor tubewaypoints and specials --- src/p_saveg.c | 162 +++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 89 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index ab2c54c02..510813a41 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3312,37 +3312,22 @@ static void P_NetUnArchiveWaypoints(savebuffer_t *save) TracyCZoneEnd(__zone); } -static void P_NetArchiveTubeWaypoints(savebuffer_t *save) +static void P_NetSyncTubeWaypoints(savebuffer_t *save) { - TracyCZone(__zone, true); - INT32 i, j; - - for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) - { - WRITEUINT16(save->p, numtubewaypoints[i]); - for (j = 0; j < numtubewaypoints[i]; j++) - WRITEUINT32(save->p, tubewaypoints[i][j] ? tubewaypoints[i][j]->mobjnum : 0); - } - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveTubeWaypoints(savebuffer_t *save) -{ - TracyCZone(__zone, true); - INT32 i, j; UINT32 mobjnum; for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) { - numtubewaypoints[i] = READUINT16(save->p); + numtubewaypoints[i] = P_SyncUINT16(save, numtubewaypoints[i]); for (j = 0; j < numtubewaypoints[i]; j++) { - mobjnum = READUINT32(save->p); - tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); + mobjnum = tubewaypoints[i][j] ? tubewaypoints[i][j]->mobjnum : 0; + mobjnum = P_SyncUINT32(save, mobjnum); + if (!save->write) + tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); } } - TracyCZoneEnd(__zone); } // Now save the pointers, tracer and target, but at load time we must @@ -4945,89 +4930,88 @@ static void P_RelinkPointers(void) } } -static inline void P_NetArchiveSpecials(savebuffer_t *save) +static inline void P_NetSyncSpecials(savebuffer_t *save) { TracyCZone(__zone, true); size_t i, z; - - WRITEUINT32(save->p, ARCHIVEBLOCK_SPECIALS); - - // itemrespawn queue for deathmatch - i = iquetail; - while (iquehead != i) - { - for (z = 0; z < nummapthings; z++) - { - if (&mapthings[z] == itemrespawnque[i]) - { - WRITEUINT32(save->p, z); - break; - } - } - WRITEUINT32(save->p, itemrespawntime[i]); - i = (i + 1) & (ITEMQUESIZE-1); - } - - // end delimiter - WRITEUINT32(save->p, 0xffffffff); - - // Sky number - WRITESTRINGN(save->p, globallevelskytexture, 9); - - // Current global weather type - WRITEUINT8(save->p, globalweather); - - if (metalplayback) // Is metal sonic running? - { - WRITEUINT8(save->p, 0x01); - G_SaveMetal(&save->p); - } - else - WRITEUINT8(save->p, 0x00); - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveSpecials(savebuffer_t *save) -{ - TracyCZone(__zone, true); - char skytex[9]; - size_t i; - if (READUINT32(save->p) != ARCHIVEBLOCK_SPECIALS) + if (P_SyncUINT32(save, ARCHIVEBLOCK_SPECIALS) != ARCHIVEBLOCK_SPECIALS) I_Error("Bad $$$.sav at archive block Specials"); - // BP: added save itemrespawn queue for deathmatch - iquetail = iquehead = 0; - while ((i = READUINT32(save->p)) != 0xffffffff) + if (save->write) { - itemrespawnque[iquehead] = &mapthings[i]; - itemrespawntime[iquehead++] = READINT32(save->p); + // itemrespawn queue for deathmatch + i = iquetail; + while (iquehead != i) + { + for (z = 0; z < nummapthings; z++) + { + if (&mapthings[z] == itemrespawnque[i]) + { + WRITEUINT32(save->p, z); + break; + } + } + WRITEUINT32(save->p, itemrespawntime[i]); + i = (i + 1) & (ITEMQUESIZE-1); + } + + // end delimiter + WRITEUINT32(save->p, 0xffffffff); + } + else + { + // BP: added save itemrespawn queue for deathmatch + iquetail = iquehead = 0; + while ((i = READUINT32(save->p)) != 0xffffffff) + { + itemrespawnque[iquehead] = &mapthings[i]; + itemrespawntime[iquehead++] = READINT32(save->p); + } } - READSTRINGN(save->p, skytex, sizeof(skytex)); - if (strcmp(skytex, globallevelskytexture)) + // Sky number + P_SyncStringN(save, globallevelskytexture, 9); + + if (!save->write && strcmp(skytex, globallevelskytexture)) P_SetupLevelSky(skytex, true); - globalweather = READUINT8(save->p); + // Current global weather type + globalweather = P_SyncUINT8(save, globalweather); - if (globalweather) + if (!save->write) { - if (curWeather == globalweather) - curWeather = PRECIP_NONE; + if (globalweather) + { + if (curWeather == globalweather) + curWeather = PRECIP_NONE; - P_SwitchWeather(globalweather); - } - else // PRECIP_NONE - { - if (curWeather != PRECIP_NONE) P_SwitchWeather(globalweather); + } + else // PRECIP_NONE + { + if (curWeather != PRECIP_NONE) + P_SwitchWeather(globalweather); + } } - if (READUINT8(save->p) == 0x01) // metal sonic - G_LoadMetal(&save->p); - + if (save->write) + { + if (metalplayback) // Is metal sonic running? + { + WRITEUINT8(save->p, 0x01); + G_SaveMetal(&save->p); + } + else + WRITEUINT8(save->p, 0x00); + } + else + { + if (READUINT8(save->p) == 0x01) // metal sonic + G_LoadMetal(&save->p); + } TracyCZoneEnd(__zone); } @@ -5630,9 +5614,9 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) P_NetArchiveWorld(save); P_ArchivePolyObjects(save); P_NetArchiveThinkers(save); - P_NetArchiveSpecials(save); + P_NetSyncSpecials(save); P_NetArchiveColormaps(save); - P_NetArchiveTubeWaypoints(save); + P_NetSyncTubeWaypoints(save); P_NetArchiveWaypoints(save); } @@ -5682,9 +5666,9 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) P_NetUnArchiveWorld(save); P_UnArchivePolyObjects(save); P_NetUnArchiveThinkers(save); - P_NetUnArchiveSpecials(save); + P_NetSyncSpecials(save); P_NetUnArchiveColormaps(save); - P_NetUnArchiveTubeWaypoints(save); + P_NetSyncTubeWaypoints(save); P_NetUnArchiveWaypoints(save); P_RelinkPointers(); } From 6f7a01614a1fc339d7d675382d6986631886fd37 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 10:01:16 -0400 Subject: [PATCH 05/24] Reinstant tracy czone in P_NetSyncTubeWaypoints --- src/p_saveg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 510813a41..cdeec4f85 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3314,6 +3314,7 @@ static void P_NetUnArchiveWaypoints(savebuffer_t *save) static void P_NetSyncTubeWaypoints(savebuffer_t *save) { + TracyCZone(__zone, true); INT32 i, j; UINT32 mobjnum; @@ -3328,6 +3329,7 @@ static void P_NetSyncTubeWaypoints(savebuffer_t *save) tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); } } + TracyCZoneEnd(__zone); } // Now save the pointers, tracer and target, but at load time we must From b25cef1d69e76eb62c275d5307c8225989310b45 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 10:30:31 -0400 Subject: [PATCH 06/24] Don't keep track of objects that use MF2_DONTSYNC --- src/p_saveg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index cdeec4f85..8e40d12c0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5602,7 +5602,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) mobj = (mobj_t *)th; if (UNLIKELY(mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER // MT_SPARK: used for debug stuff - || mobj->type == MT_SPARK)) + || mobj->type == MT_SPARK || mobj->flags2 & MF2_DONTSYNC)) continue; mobj->mobjnum = i++; } From bdfe3344f029ae984be806e29d959e92f19da6f6 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 10:44:46 -0400 Subject: [PATCH 07/24] Fix follower using mobjnum on load end --- src/p_saveg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 8e40d12c0..b0e99c481 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -383,7 +383,7 @@ static void P_NetSyncPlayers(savebuffer_t *save) else { if (flags & FOLLOWER) - players[i].follower->mobjnum = READUINT32(save->p); + players[i].follower = (mobj_t *)(size_t)READUINT32(save->p); } for (j = 0; j < NUMPOWERS; j++) From e3f70bc7fda3e3cb72c7f64b35fb92c4e286c9d9 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 4 Oct 2025 17:13:58 +0200 Subject: [PATCH 08/24] Red: before C11 generics. Green: after C11 generics --- src/p_saveg.c | 570 ++++++++++++++++++++++++-------------------------- 1 file changed, 275 insertions(+), 295 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index b0e99c481..0e2c80a4d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -179,6 +179,43 @@ void P_SyncMem(savebuffer_t *save, void *s, size_t n) READMEM(save->p, s, n); } +mobj_t *P_SyncMobj(savebuffer_t *save, mobj_t *mo) +{ + if (save->write) + { + WRITEUINT32(save->p, mo ? mo->mobjnum : 0); + return mo; + } + else + return (mobj_t *)(uintptr_t)READUINT32(save->p); +} + +waypoint_t *P_SyncWaypoint(savebuffer_t *save, waypoint_t *wp) +{ + if (save->write) + { + WRITEUINT32(save->p, K_GetWaypointHeapIndex(wp)); + return wp; + } + else + return (waypoint_t *)(uintptr_t)READUINT32(save->p); +} + +#define SYNC(v) v = _Generic(v, \ + SINT8: P_SyncSINT8, \ + INT16: P_SyncINT16, \ + INT32: P_SyncINT32, \ + UINT8: P_SyncUINT8, \ + UINT16: P_SyncUINT16, \ + UINT32: P_SyncUINT32, \ + mobj_t *: P_SyncMobj, \ + waypoint_t *: P_SyncWaypoint \ +)(save, v); + +#define SYNCBOOLEAN(v) v = _Generic(v, \ + boolean: P_SyncUINT8 \ +)(save, v); + // Block UINT32s to attempt to ensure that the correct data is // being sent and received #define ARCHIVEBLOCK_MISC 0x7FEEDEED @@ -190,15 +227,6 @@ void P_SyncMem(savebuffer_t *save, void *s, size_t n) #define ARCHIVEBLOCK_SPECIALS 0x7F228378 #define ARCHIVEBLOCK_WAYPOINTS 0x7F46498F -// Note: This cannot be bigger -// than an UINT16 -typedef enum -{ - AWAYVIEW = 0x01, - FOLLOWITEM = 0x02, - FOLLOWER = 0x04, -} player_saveflags; - static inline void P_ArchivePlayer(savebuffer_t *save) { const player_t *player = &players[consoleplayer]; @@ -228,7 +256,6 @@ static void P_NetSyncPlayers(savebuffer_t *save) TracyCZone(__zone, true); INT32 i, j; - UINT16 flags; if (P_SyncUINT32(save, ARCHIVEBLOCK_PLAYERS) != ARCHIVEBLOCK_PLAYERS) I_Error("Bad $$$.sav at archive block Players"); @@ -239,385 +266,338 @@ static void P_NetSyncPlayers(savebuffer_t *save) for (j = 0; j < PWRLV_NUMTYPES; j++) { - clientpowerlevels[i][j] = P_SyncINT16(save, clientpowerlevels[i][j]); + SYNC(clientpowerlevels[i][j]); } - clientPowerAdd[i] = P_SyncINT16(save, clientPowerAdd[i]); + SYNC(clientPowerAdd[i]); if (!playeringame[i]) continue; - flags = 0; - // no longer send ticcmds P_SyncStringN(save, player_names[i], MAXPLAYERNAME); - playerconsole[i] = P_SyncUINT8(save, playerconsole[i]); - splitscreen_invitations[i] = P_SyncINT32(save, splitscreen_invitations[i]); + SYNC(playerconsole[i]); + SYNC(splitscreen_invitations[i]); - players[i].angleturn = P_SyncAngle(save, players[i].angleturn); - players[i].aiming = P_SyncAngle(save, players[i].aiming); - players[i].drawangle = P_SyncAngle(save, players[i].drawangle); - players[i].viewrollangle = P_SyncAngle(save, players[i].viewrollangle); - players[i].tilt = P_SyncAngle(save, players[i].tilt); - players[i].awayviewaiming = P_SyncAngle(save, players[i].awayviewaiming); - players[i].awayviewtics = P_SyncINT32(save, players[i].awayviewtics); + SYNC(players[i].angleturn); + SYNC(players[i].aiming); + SYNC(players[i].drawangle); + SYNC(players[i].viewrollangle); + SYNC(players[i].tilt); + SYNC(players[i].awayviewaiming); + SYNC(players[i].awayviewtics); - players[i].playerstate = P_SyncUINT8(save, players[i].playerstate); - players[i].pflags = P_SyncUINT32(save, players[i].pflags); - players[i].panim = P_SyncUINT8(save, players[i].panim); - players[i].spectator = P_SyncUINT8(save, players[i].spectator); - players[i].spectatewait = P_SyncUINT32(save, players[i].spectatewait); + SYNC(players[i].playerstate); + SYNC(players[i].pflags); + SYNC(players[i].panim); + SYNCBOOLEAN(players[i].spectator); + SYNC(players[i].spectatewait); - players[i].flashpal = P_SyncUINT16(save, players[i].flashpal); - players[i].flashcount = P_SyncUINT16(save, players[i].flashcount); + SYNC(players[i].flashpal); + SYNC(players[i].flashcount); - players[i].skincolor = P_SyncUINT8(save, players[i].skincolor); - players[i].skin = P_SyncINT32(save, players[i].skin); - players[i].availabilities = P_SyncUINT32(save, players[i].availabilities); - players[i].score = P_SyncUINT32(save, players[i].score); - players[i].lives = P_SyncSINT8(save, players[i].lives); - players[i].xtralife = P_SyncSINT8(save, players[i].xtralife); - players[i].speed = P_SyncFixed(save, players[i].speed); - players[i].lastspeed = P_SyncFixed(save, players[i].lastspeed); - players[i].deadtimer = P_SyncINT32(save, players[i].deadtimer); - players[i].exiting = P_SyncUINT32(save, players[i].exiting); + SYNC(players[i].skincolor); + SYNC(players[i].skin); + SYNC(players[i].availabilities); + SYNC(players[i].score); + SYNC(players[i].lives); + SYNC(players[i].xtralife); + SYNC(players[i].speed); + SYNC(players[i].lastspeed); + SYNC(players[i].deadtimer); + SYNC(players[i].exiting); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - players[i].cmomx = P_SyncFixed(save, players[i].cmomx); // Conveyor momx - players[i].cmomy = P_SyncFixed(save, players[i].cmomy); // Conveyor momy - players[i].rmomx = P_SyncFixed(save, players[i].rmomx); // "Real" momx (momx - cmomx) - players[i].rmomy = P_SyncFixed(save, players[i].rmomy); // "Real" momy (momy - cmomy) + SYNC(players[i].cmomx); // Conveyor momx + SYNC(players[i].cmomy); // Conveyor momy + SYNC(players[i].rmomx); // "Real" momx (momx - cmomx) + SYNC(players[i].rmomy); // "Real" momy (momy - cmomy) - players[i].totalring = P_SyncINT16(save, players[i].totalring); - players[i].realtime = P_SyncUINT32(save, players[i].realtime); + SYNC(players[i].totalring); + SYNC(players[i].realtime); for (j = 0; j < LAP__MAX; j++) { - players[i].laptime[j] = P_SyncUINT32(save, players[i].laptime[j]); + SYNC(players[i].laptime[j]); } - players[i].laps = P_SyncUINT8(save, players[i].laps); - players[i].latestlap = P_SyncUINT8(save, players[i].latestlap); + SYNC(players[i].laps); + SYNC(players[i].latestlap); - players[i].starposttime = P_SyncUINT32(save, players[i].starposttime); - players[i].starpostx = P_SyncINT16(save, players[i].starpostx); - players[i].starposty = P_SyncINT16(save, players[i].starposty); - players[i].starpostz = P_SyncINT16(save, players[i].starpostz); - players[i].starpostnum = P_SyncINT32(save, players[i].starpostnum); - players[i].starpostangle = P_SyncAngle(save, players[i].starpostangle); - players[i].starpostflip = P_SyncUINT8(save, (UINT8)players[i].starpostflip); - players[i].prevcheck = P_SyncINT32(save, players[i].prevcheck); - players[i].nextcheck = P_SyncINT32(save, players[i].nextcheck); + SYNC(players[i].starposttime); + SYNC(players[i].starpostx); + SYNC(players[i].starposty); + SYNC(players[i].starpostz); + SYNC(players[i].starpostnum); + SYNC(players[i].starpostangle); + SYNCBOOLEAN(players[i].starpostflip); + SYNC(players[i].prevcheck); + SYNC(players[i].nextcheck); - players[i].ctfteam = P_SyncUINT8(save, players[i].ctfteam); + SYNC(players[i].ctfteam); - players[i].checkskip = P_SyncUINT8(save, players[i].checkskip); + SYNC(players[i].checkskip); - players[i].lastsidehit = P_SyncINT16(save, players[i].lastsidehit); - players[i].lastlinehit = P_SyncINT16(save, players[i].lastlinehit); + SYNC(players[i].lastsidehit); + SYNC(players[i].lastlinehit); - players[i].onconveyor = P_SyncINT32(save, players[i].onconveyor); + SYNC(players[i].onconveyor); - players[i].jointime = P_SyncUINT32(save, players[i].jointime); - players[i].spectatorreentry = P_SyncUINT32(save, players[i].spectatorreentry); + SYNC(players[i].jointime); + SYNC(players[i].spectatorreentry); - players[i].grieftime = P_SyncUINT32(save, players[i].grieftime); - players[i].griefstrikes = P_SyncUINT8(save, players[i].griefstrikes); + SYNC(players[i].grieftime); + SYNC(players[i].griefstrikes); - players[i].splitscreenindex = P_SyncUINT8(save, players[i].splitscreenindex); + SYNC(players[i].splitscreenindex); - if (save->write) - { - if (players[i].awayviewmobj) - flags |= AWAYVIEW; + SYNC(players[i].awayviewmobj); + SYNC(players[i].followmobj); + SYNC(players[i].followitem); - if (players[i].followmobj) - flags |= FOLLOWITEM; - - if (players[i].follower) - flags |= FOLLOWER; - - WRITEUINT16(save->p, flags); - - if (flags & AWAYVIEW) - WRITEUINT32(save->p, players[i].awayviewmobj->mobjnum); - - if (flags & FOLLOWITEM) - WRITEUINT32(save->p, players[i].followmobj->mobjnum); - } - else - { - flags = READUINT16(save->p); - - if (flags & AWAYVIEW) - players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save->p); - - if (flags & FOLLOWITEM) - players[i].followmobj = (mobj_t *)(size_t)READUINT32(save->p); - } - - players[i].followitem = P_SyncUINT32(save, (UINT32)players[i].followitem); - - players[i].charflags = P_SyncUINT32(save, players[i].charflags); + SYNC(players[i].charflags); // SRB2kart - players[i].kartspeed = P_SyncUINT8(save, players[i].kartspeed); - players[i].kartweight = P_SyncUINT8(save, players[i].kartweight); + SYNC(players[i].kartspeed); + SYNC(players[i].kartweight); for (j = 0; j < MAXPREDICTTICS; j++) { - players[i].lturn_max[j] = P_SyncINT16(save, players[i].lturn_max[j]); - players[i].rturn_max[j] = P_SyncINT16(save, players[i].rturn_max[j]); + SYNC(players[i].lturn_max[j]); + SYNC(players[i].rturn_max[j]); } - players[i].followerskin = P_SyncUINT8(save, players[i].followerskin); - players[i].followerready = P_SyncUINT8(save, players[i].followerready); // booleans are really just numbers eh?? - players[i].followercolor = P_SyncUINT16(save, players[i].followercolor); + SYNC(players[i].followerskin); + SYNCBOOLEAN(players[i].followerready); + SYNC(players[i].followercolor); - if (save->write) - { - if (flags & FOLLOWER) - WRITEUINT32(save->p, players[i].follower->mobjnum); - } - else - { - if (flags & FOLLOWER) - players[i].follower = (mobj_t *)(size_t)READUINT32(save->p); - } + SYNC(players[i].follower); for (j = 0; j < NUMPOWERS; j++) - players[i].powers[j] = P_SyncUINT16(save, players[i].powers[j]); + SYNC(players[i].powers[j]); for (j = 0; j < NUMKARTSTUFF; j++) - players[i].kartstuff[j] = P_SyncINT32(save, players[i].kartstuff[j]); + SYNC(players[i].kartstuff[j]); - players[i].nocontrol = P_SyncUINT16(save, players[i].nocontrol); - players[i].carry = P_SyncUINT8(save, players[i].carry); - players[i].dye = P_SyncUINT16(save, players[i].dye); + SYNC(players[i].nocontrol); + SYNC(players[i].carry); + SYNC(players[i].dye); - players[i].position = P_SyncUINT8(save, players[i].position); - players[i].oldposition = P_SyncUINT8(save, players[i].oldposition); - players[i].positiondelay = P_SyncUINT8(save, players[i].positiondelay); - players[i].distancetofinish = P_SyncUINT32(save, players[i].distancetofinish); - players[i].distancetofinishprev = P_SyncUINT32(save, players[i].distancetofinishprev); - if (save->write) - { - WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].currentwaypoint)); - WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); - } - else - { - players[i].currentwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); - players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save->p); - } - players[i].bigwaypointgap = P_SyncUINT16(save, players[i].bigwaypointgap); - players[i].airtime = P_SyncUINT32(save, players[i].airtime); - players[i].startboost = P_SyncUINT8(save, players[i].startboost); + SYNC(players[i].position); + SYNC(players[i].oldposition); + SYNC(players[i].positiondelay); + SYNC(players[i].distancetofinish); + SYNC(players[i].distancetofinishprev); + SYNC(players[i].currentwaypoint); + SYNC(players[i].nextwaypoint); + SYNC(players[i].bigwaypointgap); + SYNC(players[i].airtime); + SYNC(players[i].startboost); - players[i].dropdash = P_SyncUINT8(save, players[i].dropdash); - players[i].respawn = P_SyncUINT8(save, players[i].respawn); + SYNC(players[i].dropdash); + SYNC(players[i].respawn); - players[i].flashing = P_SyncUINT16(save, players[i].flashing); - players[i].spinouttimer = P_SyncUINT16(save, players[i].spinouttimer); - players[i].spinoutrot = P_SyncINT32(save, players[i].spinoutrot); - players[i].spinouttype = P_SyncUINT8(save, players[i].spinouttype); - players[i].flipovertimer = P_SyncUINT16(save, players[i].flipovertimer); - players[i].flipoverangle = P_SyncAngle(save, players[i].flipoverangle); - players[i].squishedtimer = P_SyncINT16(save, players[i].squishedtimer); - players[i].instashield = P_SyncUINT8(save, players[i].instashield); - players[i].wipeoutslow = P_SyncUINT8(save, players[i].wipeoutslow); - players[i].justbumped = P_SyncUINT8(save, players[i].justbumped); - players[i].noclip = P_SyncUINT8(save, players[i].noclip); + SYNC(players[i].flashing); + SYNC(players[i].spinouttimer); + SYNC(players[i].spinoutrot); + SYNC(players[i].spinouttype); + SYNC(players[i].flipovertimer); + SYNC(players[i].flipoverangle); + SYNC(players[i].squishedtimer); + SYNC(players[i].instashield); + SYNC(players[i].wipeoutslow); + SYNC(players[i].justbumped); + SYNCBOOLEAN(players[i].noclip); - players[i].drift = P_SyncSINT8(save, players[i].drift); - players[i].driftlock = P_SyncSINT8(save, players[i].driftlock); - players[i].driftcharge = P_SyncFixed(save, players[i].driftcharge); - players[i].driftboost = P_SyncUINT8(save, players[i].driftboost); + SYNC(players[i].drift); + SYNC(players[i].driftlock); + SYNC(players[i].driftcharge); + SYNC(players[i].driftboost); - players[i].aizdriftstrat = P_SyncSINT8(save, players[i].aizdriftstrat); - players[i].aizdrifttilt = P_SyncINT32(save, players[i].aizdrifttilt); - players[i].aizdriftturn = P_SyncINT32(save, players[i].aizdriftturn); - players[i].slipdashcharge = P_SyncFixed(save, players[i].slipdashcharge); - players[i].slipdashdir = P_SyncSINT8(save, players[i].slipdashdir); + SYNC(players[i].aizdriftstrat); + SYNC(players[i].aizdrifttilt); + SYNC(players[i].aizdriftturn); + SYNC(players[i].slipdashcharge); + SYNC(players[i].slipdashdir); - players[i].offroad = P_SyncFixed(save, players[i].offroad); - players[i].tiregrease = P_SyncFixed(save, players[i].tiregrease); - players[i].pogospring = P_SyncUINT8(save, players[i].pogospring); - players[i].brakestop = P_SyncUINT8(save, players[i].brakestop); - players[i].waterskip = P_SyncUINT8(save, players[i].waterskip); + SYNC(players[i].offroad); + SYNC(players[i].tiregrease); + SYNC(players[i].pogospring); + SYNC(players[i].brakestop); + SYNC(players[i].waterskip); - players[i].dashpadcooldown = P_SyncUINT8(save, players[i].dashpadcooldown); + SYNC(players[i].dashpadcooldown); - players[i].boostpower = P_SyncFixed(save, players[i].boostpower); - players[i].speedboost = P_SyncFixed(save, players[i].speedboost); - players[i].prevspeedboost = P_SyncFixed(save, players[i].prevspeedboost); - players[i].accelboost = P_SyncFixed(save, players[i].accelboost); - players[i].boostangle = P_SyncAngle(save, players[i].boostangle); - players[i].numsneakers = P_SyncUINT8(save, players[i].numsneakers); - players[i].numboosts = P_SyncUINT8(save, players[i].numboosts); + SYNC(players[i].boostpower); + SYNC(players[i].speedboost); + SYNC(players[i].prevspeedboost); + SYNC(players[i].accelboost); + SYNC(players[i].boostangle); + SYNC(players[i].numsneakers); + SYNC(players[i].numboosts); - players[i].draftpower = P_SyncFixed(save, players[i].draftpower); - players[i].draftleeway = P_SyncUINT16(save, players[i].draftleeway); - players[i].lastdraft = P_SyncSINT8(save, players[i].lastdraft); + SYNC(players[i].draftpower); + SYNC(players[i].draftleeway); + SYNC(players[i].lastdraft); // boostinfo_t - players[i].boostinfo.stackspeedboost = P_SyncFixed(save, players[i].boostinfo.stackspeedboost); - players[i].boostinfo.nonstackspeedboost = P_SyncFixed(save, players[i].boostinfo.nonstackspeedboost); - players[i].boostinfo.accelboost = P_SyncFixed(save, players[i].boostinfo.accelboost); - players[i].boostinfo.grade = P_SyncUINT8(save, players[i].boostinfo.grade); + SYNC(players[i].boostinfo.stackspeedboost); + SYNC(players[i].boostinfo.nonstackspeedboost); + SYNC(players[i].boostinfo.accelboost); + SYNC(players[i].boostinfo.grade); - players[i].tripwireState = P_SyncUINT8(save, players[i].tripwireState); - players[i].tripwirePass = P_SyncUINT8(save, players[i].tripwirePass); - players[i].tripwireLeniency = P_SyncUINT16(save, players[i].tripwireLeniency); - players[i].tripwireReboundDelay = P_SyncUINT8(save, players[i].tripwireReboundDelay); + SYNC(players[i].tripwireState); + SYNC(players[i].tripwirePass); + SYNC(players[i].tripwireLeniency); + SYNC(players[i].tripwireReboundDelay); - players[i].itemroulette = P_SyncUINT16(save, players[i].itemroulette); - players[i].previtemroulette = P_SyncUINT16(save, players[i].previtemroulette); - players[i].itemblink = P_SyncUINT16(save, players[i].itemblink); - players[i].itemblinkmode = P_SyncUINT16(save, players[i].itemblinkmode); - players[i].roulettetype = P_SyncUINT8(save, players[i].roulettetype); + SYNC(players[i].itemroulette); + SYNC(players[i].previtemroulette); + SYNC(players[i].itemblink); + SYNC(players[i].itemblinkmode); + SYNC(players[i].roulettetype); - players[i].itemtype = P_SyncSINT8(save, players[i].itemtype); - players[i].itemamount = P_SyncUINT8(save, players[i].itemamount); - players[i].throwdir = P_SyncSINT8(save, players[i].throwdir); + SYNC(players[i].itemtype); + SYNC(players[i].itemamount); + SYNC(players[i].throwdir); - players[i].sadtimer = P_SyncUINT8(save, players[i].sadtimer); + SYNC(players[i].sadtimer); - players[i].rings = P_SyncSINT8(save, players[i].rings); - players[i].ringmin = P_SyncSINT8(save, players[i].ringmin); - players[i].ringmax = P_SyncSINT8(save, players[i].ringmax); - players[i].pickuprings = P_SyncUINT8(save, players[i].pickuprings); - players[i].ringdelay = P_SyncUINT8(save, players[i].ringdelay); - players[i].ringlock = P_SyncUINT8(save, players[i].ringlock); - players[i].ringboost = P_SyncUINT16(save, players[i].ringboost); - players[i].ringtime = P_SyncUINT16(save, players[i].ringtime); - players[i].superring = P_SyncUINT16(save, players[i].superring); - players[i].nextringaward = P_SyncUINT8(save, players[i].nextringaward); - players[i].ringvolume = P_SyncUINT8(save, players[i].ringvolume); - players[i].ringtransparency = P_SyncUINT8(save, players[i].ringtransparency); + SYNC(players[i].rings); + SYNC(players[i].ringmin); + SYNC(players[i].ringmax); + SYNC(players[i].pickuprings); + SYNC(players[i].ringdelay); + SYNC(players[i].ringlock); + SYNC(players[i].ringboost); + SYNC(players[i].ringtime); + SYNC(players[i].superring); + SYNC(players[i].nextringaward); + SYNC(players[i].ringvolume); + SYNC(players[i].ringtransparency); - players[i].airdroptime = P_SyncUINT8(save, players[i].airdroptime); - players[i].ringdrop = P_SyncUINT8(save, players[i].ringdrop); + SYNC(players[i].airdroptime); + SYNCBOOLEAN(players[i].ringdrop); - players[i].curshield = P_SyncUINT8(save, players[i].curshield); + SYNC(players[i].curshield); - players[i].bubblecool = P_SyncUINT8(save, players[i].bubblecool); - players[i].bubbleblowup = P_SyncUINT8(save, players[i].bubbleblowup); - players[i].bubblehealth = P_SyncUINT8(save, players[i].bubblehealth); - players[i].bubbleboost = P_SyncUINT16(save, players[i].bubbleboost); + SYNC(players[i].bubblecool); + SYNC(players[i].bubbleblowup); + SYNC(players[i].bubblehealth); + SYNC(players[i].bubbleboost); - players[i].flamedash = P_SyncUINT16(save, players[i].flamedash); - players[i].flametimer = P_SyncINT32(save, players[i].flametimer); - players[i].flamestore = P_SyncUINT8(save, players[i].flamestore); + SYNC(players[i].flamedash); + SYNC(players[i].flametimer); + SYNC(players[i].flamestore); - players[i].hyudorotimer = P_SyncUINT16(save, players[i].hyudorotimer); - players[i].stealingtimer = P_SyncSINT8(save, players[i].stealingtimer); + SYNC(players[i].hyudorotimer); + SYNC(players[i].stealingtimer); - players[i].sneakertimer = P_SyncUINT16(save, players[i].sneakertimer); - players[i].realsneakertimer = P_SyncUINT16(save, players[i].realsneakertimer); - players[i].floorboost = P_SyncUINT8(save, players[i].floorboost); - players[i].chaintimer = P_SyncUINT16(save, players[i].chaintimer); + SYNC(players[i].sneakertimer); + SYNC(players[i].realsneakertimer); + SYNC(players[i].floorboost); + SYNC(players[i].chaintimer); - players[i].boostcharge = P_SyncUINT8(save, players[i].boostcharge); + SYNC(players[i].boostcharge); - players[i].slopeboost = P_SyncFixed(save, players[i].slopeboost); - players[i].prevslopeboost = P_SyncFixed(save, players[i].prevslopeboost); - players[i].slopeaccel = P_SyncFixed(save, players[i].slopeaccel); + SYNC(players[i].slopeboost); + SYNC(players[i].prevslopeboost); + SYNC(players[i].slopeaccel); - players[i].growshrinktimer = P_SyncINT16(save, players[i].growshrinktimer); - players[i].growcancel = P_SyncINT16(save, players[i].growcancel); + SYNC(players[i].growshrinktimer); + SYNC(players[i].growcancel); - players[i].rocketsneakertimer = P_SyncUINT16(save, players[i].rocketsneakertimer); + SYNC(players[i].rocketsneakertimer); - players[i].invincibilitytimer = P_SyncUINT16(save, players[i].invincibilitytimer); - players[i].maxinvincibilitytime = P_SyncUINT16(save, players[i].maxinvincibilitytime); - players[i].invincibilitybottleneck = P_SyncUINT16(save, players[i].invincibilitybottleneck); - players[i].invincibilitycancel = P_SyncINT16(save, players[i].invincibilitycancel); + SYNC(players[i].invincibilitytimer); + SYNC(players[i].maxinvincibilitytime); + SYNC(players[i].invincibilitybottleneck); + SYNC(players[i].invincibilitycancel); - players[i].eggmanexplode = P_SyncUINT8(save, players[i].eggmanexplode); - players[i].eggmanblame = P_SyncSINT8(save, players[i].eggmanblame); + SYNC(players[i].eggmanexplode); + SYNC(players[i].eggmanblame); - players[i].bananadrag = P_SyncUINT16(save, players[i].bananadrag); + SYNC(players[i].bananadrag); - players[i].lastjawztarget = P_SyncSINT8(save, players[i].lastjawztarget); - players[i].jawztargetdelay = P_SyncUINT8(save, players[i].jawztargetdelay); + SYNC(players[i].lastjawztarget); + SYNC(players[i].jawztargetdelay); - players[i].confirmVictim = P_SyncUINT8(save, players[i].confirmVictim); - players[i].confirmVictimDelay = P_SyncUINT8(save, players[i].confirmVictimDelay); + SYNC(players[i].confirmVictim); + SYNC(players[i].confirmVictimDelay); - players[i].interpoints = P_SyncINT32(save, players[i].interpoints); - players[i].roundscore = P_SyncUINT32(save, players[i].roundscore); - players[i].emeralds = P_SyncUINT8(save, players[i].emeralds); - players[i].bumper = P_SyncUINT8(save, players[i].bumper); - players[i].karmadelay = P_SyncINT16(save, players[i].karmadelay); - players[i].karmamode = P_SyncINT16(save, players[i].karmamode); - players[i].karmapoints = P_SyncINT16(save, players[i].karmapoints); - players[i].wanted = P_SyncINT16(save, players[i].wanted); + SYNC(players[i].interpoints); + SYNC(players[i].roundscore); + SYNC(players[i].emeralds); + SYNC(players[i].bumper); + SYNC(players[i].karmadelay); + SYNC(players[i].karmamode); + SYNC(players[i].karmapoints); + SYNC(players[i].wanted); - players[i].glanceDir = P_SyncSINT8(save, players[i].glanceDir); + SYNC(players[i].glanceDir); - players[i].breathTimer = P_SyncUINT16(save, players[i].breathTimer); + SYNC(players[i].breathTimer); - players[i].lastsafelap = P_SyncUINT8(save, players[i].lastsafelap); - players[i].lastsafestarpost = P_SyncUINT8(save, players[i].lastsafestarpost); + SYNC(players[i].lastsafelap); + SYNC(players[i].lastsafestarpost); - players[i].typing_timer = P_SyncUINT8(save, players[i].typing_timer); - players[i].typing_duration = P_SyncUINT8(save, players[i].typing_duration); + SYNC(players[i].typing_timer); + SYNC(players[i].typing_duration); - players[i].kickstartaccel = P_SyncUINT8(save, players[i].kickstartaccel); + SYNC(players[i].kickstartaccel); - players[i].itemflags = P_SyncUINT8(save, players[i].itemflags); + SYNC(players[i].itemflags); // botvars_t - players[i].bot = P_SyncUINT8(save, players[i].bot); - players[i].botvars.style = P_SyncUINT8(save, players[i].botvars.style); - players[i].botvars.difficulty = P_SyncUINT8(save, players[i].botvars.difficulty); - players[i].botvars.diffincrease = P_SyncUINT8(save, players[i].botvars.diffincrease); - players[i].botvars.rival = P_SyncUINT8(save, players[i].botvars.rival); - players[i].botvars.rubberband = P_SyncFixed(save, players[i].botvars.rubberband); - players[i].botvars.controller = P_SyncUINT16(save, players[i].botvars.controller); + SYNCBOOLEAN(players[i].bot); + SYNC(players[i].botvars.style); + SYNC(players[i].botvars.difficulty); + SYNC(players[i].botvars.diffincrease); + SYNCBOOLEAN(players[i].botvars.rival); + SYNC(players[i].botvars.rubberband); + SYNC(players[i].botvars.controller); - players[i].outrun = P_SyncFixed(save, players[i].outrun); - players[i].outruntime = P_SyncUINT8(save, players[i].outruntime); + SYNC(players[i].outrun); + SYNC(players[i].outruntime); // sonicloopsvars_t - players[i].loop.radius = P_SyncFixed(save, players[i].loop.radius); - players[i].loop.revolution = P_SyncFixed(save, players[i].loop.revolution); - players[i].loop.min_revolution = P_SyncFixed(save, players[i].loop.min_revolution); - players[i].loop.max_revolution = P_SyncFixed(save, players[i].loop.max_revolution); - players[i].loop.yaw = P_SyncAngle(save, players[i].loop.yaw); - players[i].loop.origin.x = P_SyncFixed(save, players[i].loop.origin.x); - players[i].loop.origin.y = P_SyncFixed(save, players[i].loop.origin.y); - players[i].loop.origin.z = P_SyncFixed(save, players[i].loop.origin.z); - players[i].loop.origin_shift.x = P_SyncFixed(save, players[i].loop.origin_shift.x); - players[i].loop.origin_shift.y = P_SyncFixed(save, players[i].loop.origin_shift.y); - players[i].loop.shift.x = P_SyncFixed(save, players[i].loop.shift.x); - players[i].loop.shift.y = P_SyncFixed(save, players[i].loop.shift.y); - players[i].loop.flip = P_SyncUINT8(save, players[i].loop.flip); + SYNC(players[i].loop.radius); + SYNC(players[i].loop.revolution); + SYNC(players[i].loop.min_revolution); + SYNC(players[i].loop.max_revolution); + SYNC(players[i].loop.yaw); + SYNC(players[i].loop.origin.x); + SYNC(players[i].loop.origin.y); + SYNC(players[i].loop.origin.z); + SYNC(players[i].loop.origin_shift.x); + SYNC(players[i].loop.origin_shift.y); + SYNC(players[i].loop.shift.x); + SYNC(players[i].loop.shift.y); + SYNCBOOLEAN(players[i].loop.flip); // sonicloopcamvars_t - players[i].loop.camera.enter_tic = P_SyncUINT32(save, players[i].loop.camera.enter_tic); - players[i].loop.camera.exit_tic = P_SyncUINT32(save, players[i].loop.camera.exit_tic); - players[i].loop.camera.zoom_in_speed = P_SyncUINT32(save, players[i].loop.camera.zoom_in_speed); - players[i].loop.camera.zoom_out_speed = P_SyncUINT32(save, players[i].loop.camera.zoom_out_speed); - players[i].loop.camera.dist = P_SyncFixed(save, players[i].loop.camera.dist); - players[i].loop.camera.pan = P_SyncAngle(save, players[i].loop.camera.pan); - players[i].loop.camera.pan_speed = P_SyncFixed(save, players[i].loop.camera.pan_speed); - players[i].loop.camera.pan_accel = P_SyncUINT32(save, players[i].loop.camera.pan_accel); - players[i].loop.camera.pan_back = P_SyncUINT32(save, players[i].loop.camera.pan_back); + SYNC(players[i].loop.camera.enter_tic); + SYNC(players[i].loop.camera.exit_tic); + SYNC(players[i].loop.camera.zoom_in_speed); + SYNC(players[i].loop.camera.zoom_out_speed); + SYNC(players[i].loop.camera.dist); + SYNC(players[i].loop.camera.pan); + SYNC(players[i].loop.camera.pan_speed); + SYNC(players[i].loop.camera.pan_accel); + SYNC(players[i].loop.camera.pan_back); // Restored NiGHTS stuff - players[i].bumpertime = P_SyncUINT32(save, players[i].bumpertime); - players[i].linkcount = P_SyncINT32(save, players[i].linkcount); - players[i].linktimer = P_SyncUINT32(save, players[i].linktimer); - players[i].maxlink = P_SyncINT32(save, players[i].maxlink); + SYNC(players[i].bumpertime); + SYNC(players[i].linkcount); + SYNC(players[i].linktimer); + SYNC(players[i].maxlink); // Fix janky landing particle - players[i].prevonground = P_SyncUINT8(save, players[i].prevonground); + SYNCBOOLEAN(players[i].prevonground); // Wall Transfer bonus - players[i].walltransfered = P_SyncUINT8(save, players[i].walltransfered); - players[i].walltransferboost = P_SyncUINT8(save, players[i].walltransferboost); + SYNCBOOLEAN(players[i].walltransfered); + SYNC(players[i].walltransferboost); } TracyCZoneEnd(__zone); From 1f06351a29b2d28e4f534d23f7b72c3dd0a423f5 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 11:38:48 -0400 Subject: [PATCH 09/24] Adapt existing code to SYNC macro --- src/p_saveg.c | 170 +++++++++++++++++++++++++------------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 0e2c80a4d..1ade5b888 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3300,11 +3300,11 @@ static void P_NetSyncTubeWaypoints(savebuffer_t *save) for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) { - numtubewaypoints[i] = P_SyncUINT16(save, numtubewaypoints[i]); + SYNC(numtubewaypoints[i]); for (j = 0; j < numtubewaypoints[i]; j++) { mobjnum = tubewaypoints[i][j] ? tubewaypoints[i][j]->mobjnum : 0; - mobjnum = P_SyncUINT32(save, mobjnum); + SYNC(mobjnum); if (!save->write) tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); } @@ -4961,7 +4961,7 @@ static inline void P_NetSyncSpecials(savebuffer_t *save) P_SetupLevelSky(skytex, true); // Current global weather type - globalweather = P_SyncUINT8(save, globalweather); + SYNC(globalweather); if (!save->write) { @@ -5074,9 +5074,9 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) I_Error("Bad $$$.sav at archive block Misc"); if (resending) - gametic = P_SyncUINT32(save, gametic); + SYNC(gametic); - gamemap = P_SyncINT16(save, gamemap); + SYNC(gamemap); if (save->write) { @@ -5097,7 +5097,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) G_SetGamestate(READINT16(save->p)); } - gametype = P_SyncINT16(save, gametype); + SYNC(gametype); if (save->write) { @@ -5118,10 +5118,10 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) P_SetRandSeed(P_SyncUINT32(save, P_GetRandSeed())); - tokenlist = P_SyncUINT32(save, tokenlist); + SYNC(tokenlist); - encoremode = P_SyncUINT8(save, encoremode); - mapmusrng = P_SyncUINT8(save, mapmusrng); + SYNCBOOLEAN(encoremode); + SYNC(mapmusrng); if (!save->write) { @@ -5328,18 +5328,18 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) } } - leveltime = P_SyncUINT32(save, leveltime); - lastmap = P_SyncINT16(save, lastmap); - bossdisabled = P_SyncUINT16(save, bossdisabled); - ringsactive = P_SyncUINT8(save, ringsactive); - stackingactive = P_SyncUINT8(save, stackingactive); - chainingactive = P_SyncUINT8(save, chainingactive); - slipdashactive = P_SyncUINT8(save, slipdashactive); - purpledriftactive = P_SyncUINT8(save, purpledriftactive); - slopeboostactive = P_SyncUINT8(save, slopeboostactive); - draftingactive = P_SyncUINT8(save, draftingactive); - airdropactive = P_SyncUINT8(save, airdropactive); - bumpsparkactive = P_SyncUINT8(save, bumpsparkactive); + SYNC(leveltime); + SYNC(lastmap); + SYNC(bossdisabled); + SYNCBOOLEAN(ringsactive); + SYNCBOOLEAN(stackingactive); + SYNCBOOLEAN(chainingactive); + SYNCBOOLEAN(slipdashactive); + SYNCBOOLEAN(purpledriftactive); + SYNCBOOLEAN(slopeboostactive); + SYNCBOOLEAN(draftingactive); + SYNCBOOLEAN(airdropactive); + SYNC(bumpsparkactive); for (i = 0; i < 12; i++) { @@ -5348,11 +5348,11 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) } for (i = 0; i < MAXPLAYERS; i++) - votes[i] = P_SyncSINT8(save, votes[i]); + SYNC(votes[i]); - pickedvote = P_SyncSINT8(save, pickedvote); + SYNC(pickedvote); - emeralds = P_SyncUINT16(save, emeralds); + SYNC(emeralds); if (save->write) { UINT8 globools = 0; @@ -5369,92 +5369,92 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) stoppedclock = !!(globools & (1<<1)); } - token = P_SyncUINT32(save, token); - bluescore = P_SyncUINT32(save, bluescore); - redscore = P_SyncUINT32(save, redscore); + SYNC(token); + SYNC(bluescore); + SYNC(redscore); - skincolor_redteam = P_SyncUINT16(save, skincolor_redteam); - skincolor_blueteam = P_SyncUINT16(save, skincolor_blueteam); - skincolor_redring = P_SyncUINT16(save, skincolor_redring); - skincolor_bluering = P_SyncUINT16(save, skincolor_bluering); + SYNC(skincolor_redteam); + SYNC(skincolor_blueteam); + SYNC(skincolor_redring); + SYNC(skincolor_bluering); - modulothing = P_SyncINT32(save, modulothing); + SYNC(modulothing); - autobalance = P_SyncINT16(save, autobalance); - teamscramble = P_SyncINT16(save, teamscramble); + SYNC(autobalance); + SYNC(teamscramble); for (i = 0; i < MAXPLAYERS; i++) - scrambleplayers[i] = P_SyncINT16(save, scrambleplayers[i]); + SYNC(scrambleplayers[i]); for (i = 0; i < MAXPLAYERS; i++) - scrambleteams[i] = P_SyncINT16(save, scrambleteams[i]); + SYNC(scrambleteams[i]); - scrambletotal = P_SyncINT16(save, scrambletotal); - scramblecount = P_SyncINT16(save, scramblecount); + SYNC(scrambletotal); + SYNC(scramblecount); - racecountdown = P_SyncUINT32(save, racecountdown); - exitcountdown = P_SyncUINT32(save, exitcountdown); + SYNC(racecountdown); + SYNC(exitcountdown); // exitcondition_t - g_exit.losing = P_SyncUINT8(save, g_exit.losing); - g_exit.retry = P_SyncUINT8(save, g_exit.retry); - g_exit.hasfinished = P_SyncUINT8(save, g_exit.hasfinished); + SYNC(g_exit.losing); + SYNC(g_exit.retry); + SYNC(g_exit.hasfinished); - gravity = P_SyncFixed(save, gravity); - mapobjectscale = P_SyncFixed(save, mapobjectscale); + SYNC(gravity); + SYNC(mapobjectscale); // SRB2kart - nummapboxes = P_SyncINT32(save, nummapboxes); - numgotboxes = P_SyncINT32(save, numgotboxes); - numtargets = P_SyncUINT8(save, numtargets); - itembreaker = P_SyncUINT8(save, itembreaker); + SYNC(nummapboxes); + SYNC(numgotboxes); + SYNC(numtargets); + SYNC(itembreaker); - gamespeed = P_SyncUINT8(save, gamespeed); - numlaps = P_SyncUINT8(save, numlaps); - franticitems = P_SyncUINT8(save, franticitems); - comeback = P_SyncUINT8(save, comeback); + SYNC(gamespeed); + SYNC(numlaps); + SYNC(franticitems); + SYNC(comeback); - speedscramble = P_SyncSINT8(save, speedscramble); - encorescramble = P_SyncSINT8(save, encorescramble); + SYNC(speedscramble); + SYNC(encorescramble); // WANTED system - mostwanted = P_SyncSINT8(save, mostwanted); + SYNC(mostwanted); for (i = 0; i < 4; i++) - battlewanted[i] = P_SyncSINT8(save, battlewanted[i]); + SYNC(battlewanted[i]); - wantedcalcdelay = P_SyncUINT32(save, wantedcalcdelay); - indirectitemcooldown = P_SyncUINT32(save, indirectitemcooldown); - hyubgone = P_SyncUINT32(save, hyubgone); - mapreset = P_SyncUINT32(save, mapreset); + SYNC(wantedcalcdelay); + SYNC(indirectitemcooldown); + SYNC(hyubgone); + SYNC(mapreset); - spectateGriefed = P_SyncUINT8(save, spectateGriefed); + SYNC(spectateGriefed); - thwompsactive = P_SyncUINT8(save, thwompsactive); - lastLowestLap = P_SyncUINT8(save, lastLowestLap); - spbplace = P_SyncSINT8(save, spbplace); - startedInFreePlay = P_SyncUINT8(save, startedInFreePlay); + SYNCBOOLEAN(thwompsactive); + SYNC(lastLowestLap); + SYNC(spbplace); + SYNCBOOLEAN(startedInFreePlay); - introtime = P_SyncUINT32(save, introtime); - starttime = P_SyncUINT32(save, starttime); + SYNC(introtime); + SYNC(starttime); - hyudorotime = P_SyncINT32(save, hyudorotime); - stealtime = P_SyncINT32(save, stealtime); - sneakertime = P_SyncINT32(save, sneakertime); - waterpaneltime = P_SyncINT32(save, waterpaneltime); - itemtime = P_SyncINT32(save, itemtime); - bubbletime = P_SyncINT32(save, bubbletime); - comebacktime = P_SyncINT32(save, comebacktime); - bumptime = P_SyncINT32(save, bumptime); - greasetics = P_SyncINT32(save, greasetics); - wipeoutslowtime = P_SyncINT32(save, wipeoutslowtime); - wantedreduce = P_SyncINT32(save, wantedreduce); - wantedfrequency = P_SyncINT32(save, wantedfrequency); + SYNC(hyudorotime); + SYNC(stealtime); + SYNC(sneakertime); + SYNC(waterpaneltime); + SYNC(itemtime); + SYNC(bubbletime); + SYNC(comebacktime); + SYNC(bumptime); + SYNC(greasetics); + SYNC(wipeoutslowtime); + SYNC(wantedreduce); + SYNC(wantedfrequency); - timelimitintics = P_SyncUINT32(save, timelimitintics); - extratimeintics = P_SyncUINT32(save, extratimeintics); - secretextratime = P_SyncUINT32(save, secretextratime); + SYNC(timelimitintics); + SYNC(extratimeintics); + SYNC(secretextratime); - paused = P_SyncUINT8(save, paused); + SYNC(paused); if (save->write) { @@ -5490,7 +5490,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) } } - cht_debug = P_SyncUINT32(save, cht_debug); + SYNC(cht_debug); return true; TracyCZoneEnd(__zone); From c0cc66fd401425619c3cb095862b398466e7e2e4 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 11:40:14 -0400 Subject: [PATCH 10/24] Sync invintype --- src/p_saveg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1ade5b888..cae76e7e5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -5340,6 +5340,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNCBOOLEAN(draftingactive); SYNCBOOLEAN(airdropactive); SYNC(bumpsparkactive); + SYNC(invintype); for (i = 0; i < 12; i++) { From 649c53b5d92ff78afdc70135214d41e2012d20b6 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 12:03:13 -0400 Subject: [PATCH 11/24] Refactor waypoints --- src/p_saveg.c | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index cae76e7e5..ee273e0d7 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3241,44 +3241,42 @@ static void P_NetArchiveThinkers(savebuffer_t *save) TracyCZoneEnd(__zone); } -static void P_NetArchiveWaypoints(savebuffer_t *save) +static void P_NetSyncWaypoints(savebuffer_t *save) { TracyCZone(__zone, true); waypoint_t *waypoint; - size_t i; - size_t numWaypoints = K_GetNumWaypoints(); + UINT32 i; + UINT32 numWaypoints = K_GetNumWaypoints(); - WRITEUINT32(save->p, ARCHIVEBLOCK_WAYPOINTS); - WRITEUINT32(save->p, numWaypoints); + if (P_SyncUINT32(save, ARCHIVEBLOCK_WAYPOINTS) != ARCHIVEBLOCK_WAYPOINTS) + I_Error("Bad $$$.sav at archive block Waypoints"); - for (i = 0U; i < numWaypoints; i++) { - waypoint = K_GetWaypointFromIndex(i); + SYNC(numWaypoints); - // The only thing we save for each waypoint is the mobj. - // Waypoints should NEVER be completely created or destroyed mid-race as a result of this - WRITEUINT32(save->p, waypoint->mobj->mobjnum); + if (save->write) + { + for (i = 0U; i < numWaypoints; i++) { + waypoint = K_GetWaypointFromIndex(i); + + // The only thing we save for each waypoint is the mobj. + // Waypoints should NEVER be completely created or destroyed mid-race as a result of this + WRITEUINT32(save->p, waypoint->mobj->mobjnum); + } } - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveWaypoints(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - if (READUINT32(save->p) != ARCHIVEBLOCK_WAYPOINTS) - I_Error("Bad $$$.sav at archive block Waypoints!"); - else { - UINT32 numArchiveWaypoints = READUINT32(save->p); + else + { size_t numSpawnedWaypoints = K_GetNumWaypoints(); - if (numArchiveWaypoints != numSpawnedWaypoints) { + if (numWaypoints != numSpawnedWaypoints) { I_Error("Bad $$$.sav: More saved waypoints than created!"); - } else { + } + else + { waypoint_t *waypoint; UINT32 i; UINT32 temp; - for (i = 0U; i < numArchiveWaypoints; i++) { + for (i = 0U; i < numWaypoints; i++) { waypoint = K_GetWaypointFromIndex(i); temp = READUINT32(save->p); waypoint->mobj = NULL; @@ -3288,7 +3286,6 @@ static void P_NetUnArchiveWaypoints(savebuffer_t *save) } } } - TracyCZoneEnd(__zone); } @@ -5600,7 +5597,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) P_NetSyncSpecials(save); P_NetArchiveColormaps(save); P_NetSyncTubeWaypoints(save); - P_NetArchiveWaypoints(save); + P_NetSyncWaypoints(save); } ACS_Archive(save); @@ -5652,7 +5649,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) P_NetSyncSpecials(save); P_NetUnArchiveColormaps(save); P_NetSyncTubeWaypoints(save); - P_NetUnArchiveWaypoints(save); + P_NetSyncWaypoints(save); P_RelinkPointers(); } From 10aeacbe4dabbe8b79a4e80a8705b5b411213b62 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 12:16:29 -0400 Subject: [PATCH 12/24] Refactor colormaps --- src/p_saveg.c | 167 +++++++++++++++++++++++--------------------------- 1 file changed, 77 insertions(+), 90 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index ee273e0d7..249b6f5a5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -758,133 +758,120 @@ static void ClearNetColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveColormaps(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - // We save and then we clean up our colormap mess - extracolormap_t *exc, *exc_next; - UINT32 i = 0; - WRITEUINT32(save->p, num_net_colormaps); // save for safety - - for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) - { - // We must save num_net_colormaps worth of data - // So fill non-existent entries with default. - if (!exc) - exc = R_CreateDefaultColormap(false); - - WRITEUINT8(save->p, exc->fadestart); - WRITEUINT8(save->p, exc->fadeend); - WRITEUINT8(save->p, exc->flags); - - WRITEINT32(save->p, exc->rgba); - WRITEINT32(save->p, exc->fadergba); - -#ifdef EXTRACOLORMAPLUMPS - WRITESTRINGN(save->p, exc->lumpname, 9); -#endif - - exc_next = exc->next; - Z_Free(exc); // don't need anymore - } - - num_net_colormaps = 0; - num_ffloors = 0; - net_colormaps = NULL; - - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveColormaps(savebuffer_t *save) +static void P_NetSyncColormaps(savebuffer_t *save) { TracyCZone(__zone, true); // When we reach this point, we already populated our list with // dummy colormaps. Now that we are loading the color data, // set up the dummies. - extracolormap_t *exc, *existing_exc, *exc_next = NULL; + extracolormap_t *exc, *existing_exc = NULL, *exc_next = NULL; UINT32 i = 0; - num_net_colormaps = READUINT32(save->p); + SYNC(num_net_colormaps); for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { - UINT8 fadestart, fadeend, flags; - INT32 rgba, fadergba; + // TODO: Merge these paths (got lazy since i've been at this for so long now) + if (save->write) + { + // We must save num_net_colormaps worth of data + // So fill non-existent entries with default. + if (!exc) + exc = R_CreateDefaultColormap(false); + + WRITEUINT8(save->p, exc->fadestart); + WRITEUINT8(save->p, exc->fadeend); + WRITEUINT8(save->p, exc->flags); + + WRITEINT32(save->p, exc->rgba); + WRITEINT32(save->p, exc->fadergba); + #ifdef EXTRACOLORMAPLUMPS - char lumpname[9]; + P_WriteStringN(save->p, exc->lumpname, 9); #endif - fadestart = READUINT8(save->p); - fadeend = READUINT8(save->p); - flags = READUINT8(save->p); + exc_next = exc->next; + Z_Free(exc); // don't need anymore + } + else + { + UINT8 fadestart, fadeend, flags; + INT32 rgba, fadergba; +#ifdef EXTRACOLORMAPLUMPS + char lumpname[9]; +#endif - rgba = READINT32(save->p); - fadergba = READINT32(save->p); + fadestart = READUINT8(save->p); + fadeend = READUINT8(save->p); + flags = READUINT8(save->p); + + rgba = READINT32(save->p); + fadergba = READINT32(save->p); #ifdef EXTRACOLORMAPLUMPS - READSTRINGN(save->p, lumpname, 9); + P_ReadStringN(save->p, lumpname, 9); + + if (lumpname[0]) + { + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now + existing_exc = R_ColormapForName(lumpname); + *exc = *existing_exc; + R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates + continue; + } +#endif - if (lumpname[0]) - { if (!exc) // no point making a new entry since nothing points to it, // but we needed to read the data so now continue continue; exc_next = exc->next; // this gets overwritten during our operations here, so get it now - existing_exc = R_ColormapForName(lumpname); - *exc = *existing_exc; - R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates - continue; - } -#endif - if (!exc) - // no point making a new entry since nothing points to it, - // but we needed to read the data so now continue - continue; + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->flags = flags; - exc_next = exc->next; // this gets overwritten during our operations here, so get it now - - exc->fadestart = fadestart; - exc->fadeend = fadeend; - exc->flags = flags; - - exc->rgba = rgba; - exc->fadergba = fadergba; + exc->rgba = rgba; + exc->fadergba = fadergba; #ifdef EXTRACOLORMAPLUMPS - exc->lump = LUMPERROR; - exc->lumpname[0] = 0; + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; #endif - existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags); + existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags); - if (existing_exc) - exc->colormap = existing_exc->colormap; - else - // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", - // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), - // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); - exc->colormap = R_CreateLightTable(exc); + if (existing_exc) + exc->colormap = existing_exc->colormap; + else + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); + exc->colormap = R_CreateLightTable(exc); - // HACK: If this dummy is a duplicate, we're going to add it - // to the extra_colormaps list anyway. I think this is faster - // than going through every loaded sector and correcting their - // colormap address to the pre-existing one, PER net_colormap entry - R_AddColormapToList(exc); + // HACK: If this dummy is a duplicate, we're going to add it + // to the extra_colormaps list anyway. I think this is faster + // than going through every loaded sector and correcting their + // colormap address to the pre-existing one, PER net_colormap entry + R_AddColormapToList(exc); - if (i < num_net_colormaps-1 && !exc_next) - exc_next = R_CreateDefaultColormap(false); + if (i < num_net_colormaps-1 && !exc_next) + exc_next = R_CreateDefaultColormap(false); + } } // if we still have a valid net_colormap after iterating up to num_net_colormaps, // some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted. // In any case, add them to the colormap list too so that at least the sectors' colormap // addresses are valid and accounted properly - if (exc_next) + if (!save->write && exc_next) { existing_exc = R_GetDefaultColormap(); for (exc = exc_next; exc; exc = exc->next) @@ -5595,7 +5582,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) P_ArchivePolyObjects(save); P_NetArchiveThinkers(save); P_NetSyncSpecials(save); - P_NetArchiveColormaps(save); + P_NetSyncColormaps(save); P_NetSyncTubeWaypoints(save); P_NetSyncWaypoints(save); } @@ -5647,7 +5634,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) P_UnArchivePolyObjects(save); P_NetUnArchiveThinkers(save); P_NetSyncSpecials(save); - P_NetUnArchiveColormaps(save); + P_NetSyncColormaps(save); P_NetSyncTubeWaypoints(save); P_NetSyncWaypoints(save); P_RelinkPointers(); From a4e59679fa0d46d9236149f69acbf0ee6fa2496b Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sat, 4 Oct 2025 13:01:24 -0400 Subject: [PATCH 13/24] Whoops forgot to change these --- src/p_saveg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 249b6f5a5..918454e95 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -788,7 +788,7 @@ static void P_NetSyncColormaps(savebuffer_t *save) WRITEINT32(save->p, exc->fadergba); #ifdef EXTRACOLORMAPLUMPS - P_WriteStringN(save->p, exc->lumpname, 9); + WRITESTRINGN(save->p, exc->lumpname, 9); #endif exc_next = exc->next; @@ -810,7 +810,7 @@ static void P_NetSyncColormaps(savebuffer_t *save) fadergba = READINT32(save->p); #ifdef EXTRACOLORMAPLUMPS - P_ReadStringN(save->p, lumpname, 9); + READSTRINGN(save->p, lumpname, 9); if (lumpname[0]) { From de7c89bffdf01c2199801764c09118119d391d49 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 4 Oct 2025 19:18:01 +0200 Subject: [PATCH 14/24] A little bit of cleanup --- src/p_saveg.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 918454e95..764204b43 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -190,6 +190,20 @@ mobj_t *P_SyncMobj(savebuffer_t *save, mobj_t *mo) return (mobj_t *)(uintptr_t)READUINT32(save->p); } +mobj_t *P_SyncMobjAndRelink(savebuffer_t *save, mobj_t *mo) +{ + if (save->write) + { + WRITEUINT32(save->p, mo ? mo->mobjnum : 0); + return mo; + } + else + { + UINT32 mobjnum = READUINT32(save->p); + return mobjnum == 0 ? NULL : P_FindNewPosition(mobjnum); + } +} + waypoint_t *P_SyncWaypoint(savebuffer_t *save, waypoint_t *wp) { if (save->write) @@ -216,6 +230,10 @@ waypoint_t *P_SyncWaypoint(savebuffer_t *save, waypoint_t *wp) boolean: P_SyncUINT8 \ )(save, v); +#define SYNCRELINK(v) v = _Generic(v, \ + mobj_t *: P_SyncMobjAndRelink \ +)(save, v); + // Block UINT32s to attempt to ensure that the correct data is // being sent and received #define ARCHIVEBLOCK_MISC 0x7FEEDEED @@ -3280,18 +3298,12 @@ static void P_NetSyncTubeWaypoints(savebuffer_t *save) { TracyCZone(__zone, true); INT32 i, j; - UINT32 mobjnum; for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) { SYNC(numtubewaypoints[i]); for (j = 0; j < numtubewaypoints[i]; j++) - { - mobjnum = tubewaypoints[i][j] ? tubewaypoints[i][j]->mobjnum : 0; - SYNC(mobjnum); - if (!save->write) - tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); - } + SYNCRELINK(tubewaypoints[i][j]); } TracyCZoneEnd(__zone); } @@ -5326,10 +5338,10 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNC(bumpsparkactive); SYNC(invintype); - for (i = 0; i < 12; i++) + for (i = 0; i < sizeof(votelevels)/sizeof(*votelevels); i++) { - votelevels[i][0] = P_SyncINT16(save, votelevels[i][0]); - votelevels[i][1] = P_SyncINT16(save, votelevels[i][1]); + SYNC(votelevels[i][0]); + SYNC(votelevels[i][1]); } for (i = 0; i < MAXPLAYERS; i++) @@ -5381,9 +5393,9 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNC(exitcountdown); // exitcondition_t - SYNC(g_exit.losing); - SYNC(g_exit.retry); - SYNC(g_exit.hasfinished); + SYNCBOOLEAN(g_exit.losing); + SYNCBOOLEAN(g_exit.retry); + SYNCBOOLEAN(g_exit.hasfinished); SYNC(gravity); SYNC(mapobjectscale); @@ -5392,19 +5404,19 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNC(nummapboxes); SYNC(numgotboxes); SYNC(numtargets); - SYNC(itembreaker); + SYNCBOOLEAN(itembreaker); SYNC(gamespeed); SYNC(numlaps); - SYNC(franticitems); - SYNC(comeback); + SYNCBOOLEAN(franticitems); + SYNCBOOLEAN(comeback); SYNC(speedscramble); SYNC(encorescramble); // WANTED system SYNC(mostwanted); - for (i = 0; i < 4; i++) + for (i = 0; i < sizeof(battlewanted)/sizeof(*battlewanted); i++) SYNC(battlewanted[i]); SYNC(wantedcalcdelay); @@ -5439,7 +5451,7 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending) SYNC(extratimeintics); SYNC(secretextratime); - SYNC(paused); + SYNC(paused); // surprisingly not a boolean if (save->write) { From 433f9ea195a4e4d6c6d47e3987637b1156ca8172 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 5 Oct 2025 00:02:48 +0200 Subject: [PATCH 15/24] Refactor the world --- src/p_saveg.c | 1046 ++++++++++++++++++++----------------------------- 1 file changed, 433 insertions(+), 613 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 764204b43..ade09404f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -911,48 +911,51 @@ static void P_NetSyncColormaps(savebuffer_t *save) /// World Archiving /// -#define SD_FLOORHT 0x01 -#define SD_CEILHT 0x02 -#define SD_FLOORPIC 0x04 -#define SD_CEILPIC 0x08 -#define SD_LIGHT 0x10 -#define SD_SPECIAL 0x20 -#define SD_DIFF2 0x40 -#define SD_FFLOORS 0x80 +// each byte contains 7 flags +// the most signifcant bit indicates a following extra byte +enum +{ + SD_FLOORHT = 0<<3, + SD_CEILHT, + SD_FLOORPIC, + SD_CEILPIC, + SD_LIGHT, + SD_SPECIAL, + SD_FFLOORS, -// diff2 flags -#define SD_FXOFFS 0x01 -#define SD_FYOFFS 0x02 -#define SD_CXOFFS 0x04 -#define SD_CYOFFS 0x08 -#define SD_FLOORANG 0x10 -#define SD_CEILANG 0x20 -#define SD_TAG 0x40 -#define SD_DIFF3 0x80 + // diff2 flags + SD_FXOFFS = 1<<3, + SD_FYOFFS, + SD_CXOFFS, + SD_CYOFFS, + SD_FLOORANG, + SD_CEILANG, + SD_TAG, -// diff3 flags -#define SD__UNUSED 0x01 -#define SD_COLORMAP 0x02 -#define SD_CRUMBLESTATE 0x04 -#define SD_FLOORLIGHT 0x08 -#define SD_CEILLIGHT 0x10 -#define SD_FLAG 0x20 -#define SD_SPECIALFLAG 0x40 -#define SD_DIFF4 0x80 + // diff3 flags + SD__UNUSED = 2<<3, + SD_COLORMAP, + SD_CRUMBLESTATE, + SD_FLOORLIGHT, + SD_CEILLIGHT, + SD_FLAG, + SD_SPECIALFLAG, -//diff4 flags -#define SD_DAMAGETYPE 0x01 -#define SD_TRIGGERTAG 0x02 -#define SD_TRIGGERER 0x04 -#define SD_GRAVITY 0x08 -#define SD_ACTION 0x10 -#define SD_ARGS 0x20 -#define SD_STRINGARGS 0x40 -#define SD_DIFF5 0x80 + //diff4 flags + SD_DAMAGETYPE = 3<<3, + SD_TRIGGERTAG, + SD_TRIGGERER, + SD_GRAVITY, + SD_ACTION, + SD_ARGS, + SD_STRINGARGS, -//diff5 flags -#define SD_ACTIVATION 0x01 -#define SD_BOTCONTROLLER 0x02 + //diff5 flags + SD_ACTIVATION = 4<<3, + SD_BOTCONTROLLER, + + SD__MAX +}; static boolean P_SectorArgsEqual(const sector_t *sc, const sector_t *spawnsc) { @@ -979,27 +982,40 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn return true; } -#define LD_FLAG 0x01 -#define LD_SPECIAL 0x02 -#define LD_TAG 0x04 -#define LD_S1TEXOFF 0x08 -#define LD_S1TOPTEX 0x10 -#define LD_S1BOTTEX 0x20 -#define LD_S1MIDTEX 0x40 -#define LD_DIFF2 0x80 +enum +{ + LD_FLAG = 0<<3, + LD_SPECIAL, + LD_TAG, + LD_S1TEXOFF, + LD_S1TOPTEX, + LD_S1BOTTEX, + LD_S1MIDTEX, -// diff2 flags -#define LD_S2TEXOFF 0x01 -#define LD_S2TOPTEX 0x02 -#define LD_S2BOTTEX 0x04 -#define LD_S2MIDTEX 0x08 -#define LD_ARGS 0x10 -#define LD_STRINGARGS 0x20 -#define LD__UNUSED 0x40 -#define LD_DIFF3 0x80 + // diff2 flags + LD_S2TEXOFF = 1<<3, + LD_S2TOPTEX, + LD_S2BOTTEX, + LD_S2MIDTEX, + LD_ARGS, + LD_STRINGARGS, + LD__UNUSED, -// diff3 flags -#define LD_ACTIVATION 0x01 + // diff3 flags + LD_ACTIVATION = 2<<3, + + LD__MAX +}; + +// diff macros +#define SETB(b) (diff[b >> 3] |= (1 << (b & 7))) +#define DIFFNE(x, field, b) if (x->field != spawn##x->field) SETB(b) +#define DIFFIF(x, field, b) if (x->field) SETB(b) + +// sync macros +#define GETB(b) (diff[b >> 3] & (1 << (b & 7))) +#define SYNCF(b, v) if (GETB(b)) SYNC(v) +#define SYNCFB(b, v) if (GETB(b)) SYNCBOOLEAN(v) static boolean P_LineArgsEqual(const line_t *li, const line_t *spawnli) { @@ -1115,484 +1131,387 @@ static void UnArchiveFFloors(savebuffer_t *save, const sector_t *ss) } } -static void ArchiveSectors(savebuffer_t *save) +static void DiffSectors(savebuffer_t *save, const sector_t *ss, const sector_t *spawnss, UINT8 diff[]) { - size_t i, j; - const sector_t *ss = sectors; - const sector_t *spawnss = spawnsectors; - UINT8 diff, diff2, diff3, diff4, diff5; + DIFFNE(ss, floorheight, SD_FLOORHT); + DIFFNE(ss, ceilingheight, SD_CEILHT); + DIFFNE(ss, floorpic, SD_FLOORPIC); + DIFFNE(ss, ceilingpic, SD_CEILPIC); + DIFFNE(ss, lightlevel, SD_LIGHT); + DIFFNE(ss, special, SD_SPECIAL); + if (ss->ffloors && CheckFFloorDiff(ss)) + SETB(SD_FFLOORS); - for (i = 0; i < numsectors; i++, ss++, spawnss++) + DIFFNE(ss, floor_xoffs, SD_FXOFFS); + DIFFNE(ss, floor_yoffs, SD_FYOFFS); + DIFFNE(ss, ceiling_xoffs, SD_CXOFFS); + DIFFNE(ss, ceiling_yoffs, SD_CYOFFS); + DIFFNE(ss, floorpic_angle, SD_FLOORANG); + DIFFNE(ss, ceilingpic_angle, SD_CEILANG); + if (!Tag_Compare(&ss->tags, &spawnss->tags)) + SETB(SD_TAG); + + //DIFFNE(ss, ..., SD__UNUSED); + DIFFNE(ss, extra_colormap, SD_COLORMAP); + DIFFIF(ss, crumblestate, SD_CRUMBLESTATE); + if (ss->floorlightlevel != spawnss->floorlightlevel || ss->floorlightabsolute != spawnss->floorlightabsolute) + SETB(SD_FLOORLIGHT); + if (ss->ceilinglightlevel != spawnss->ceilinglightlevel || ss->ceilinglightabsolute != spawnss->ceilinglightabsolute) + SETB(SD_CEILLIGHT); + DIFFNE(ss, flags, SD_FLAG); + DIFFNE(ss, specialflags, SD_SPECIALFLAG); + + DIFFNE(ss, damagetype, SD_DAMAGETYPE); + DIFFNE(ss, triggertag, SD_TRIGGERTAG); + DIFFNE(ss, triggerer, SD_TRIGGERER); + DIFFNE(ss, gravity, SD_GRAVITY); + DIFFNE(ss, action, SD_ACTION); + if (!P_SectorArgsEqual(ss, spawnss)) + SETB(SD_ARGS); + if (!P_SectorStringArgsEqual(ss, spawnss)) + SETB(SD_STRINGARGS); + + DIFFNE(ss, activation, SD_ACTIVATION); + if (/*ss->botController.trick != spawnss->botController.trick + ||*/ss->botController.flags != spawnss->botController.flags + || ss->botController.forceAngle != spawnss->botController.forceAngle) { - diff = diff2 = diff3 = diff4 = diff5 = 0; - if (ss->floorheight != spawnss->floorheight) - diff |= SD_FLOORHT; - if (ss->ceilingheight != spawnss->ceilingheight) - diff |= SD_CEILHT; - // - // flats - // - if (ss->floorpic != spawnss->floorpic) - diff |= SD_FLOORPIC; - if (ss->ceilingpic != spawnss->ceilingpic) - diff |= SD_CEILPIC; + SETB(SD_BOTCONTROLLER); + } +} - if (ss->lightlevel != spawnss->lightlevel) - diff |= SD_LIGHT; - if (ss->special != spawnss->special) - diff |= SD_SPECIAL; +static void SyncSectors(savebuffer_t *save) +{ + size_t i = 0, j; + sector_t *sec; + UINT8 diff[(SD__MAX>>3) + 1]; - if (ss->floor_xoffs != spawnss->floor_xoffs) - diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != spawnss->floor_yoffs) - diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) - diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) - diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != spawnss->floorpic_angle) - diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) - diff2 |= SD_CEILANG; - - if (!Tag_Compare(&ss->tags, &spawnss->tags)) - diff2 |= SD_TAG; - - if (ss->extra_colormap != spawnss->extra_colormap) - diff3 |= SD_COLORMAP; - if (ss->crumblestate) - diff3 |= SD_CRUMBLESTATE; - - if (ss->floorlightlevel != spawnss->floorlightlevel || ss->floorlightabsolute != spawnss->floorlightabsolute) - diff3 |= SD_FLOORLIGHT; - if (ss->ceilinglightlevel != spawnss->ceilinglightlevel || ss->ceilinglightabsolute != spawnss->ceilinglightabsolute) - diff3 |= SD_CEILLIGHT; - if (ss->flags != spawnss->flags) - diff3 |= SD_FLAG; - if (ss->specialflags != spawnss->specialflags) - diff3 |= SD_SPECIALFLAG; - if (ss->damagetype != spawnss->damagetype) - diff4 |= SD_DAMAGETYPE; - if (ss->triggertag != spawnss->triggertag) - diff4 |= SD_TRIGGERTAG; - if (ss->triggerer != spawnss->triggerer) - diff4 |= SD_TRIGGERER; - if (ss->gravity != spawnss->gravity) - diff4 |= SD_GRAVITY; - - if (ss->action != spawnss->action) - diff4 |= SD_ACTION; - if (!P_SectorArgsEqual(ss, spawnss)) - diff4 |= SD_ARGS; - if (!P_SectorStringArgsEqual(ss, spawnss)) - diff4 |= SD_STRINGARGS; - if (ss->activation != spawnss->activation) - diff5 |= SD_ACTIVATION; - if (/*ss->botController.trick != spawnss->botController.trick - ||*/ss->botController.flags != spawnss->botController.flags - || ss->botController.forceAngle != spawnss->botController.forceAngle) + for (;;) + { + memset(diff, 0, sizeof(diff)); + if (save->write) { - diff5 |= SD_BOTCONTROLLER; + if (++i == numsectors) + break; + + DiffSectors(save, §ors[i], &spawnsectors[i], diff); + for (j = sizeof(diff)-1; j > 0; j--) + if (diff[j]) + diff[j-1] |= 0x80; + if (diff[0] == 0) + continue; + + WRITEUINT16(save->p, i); + } + else + { + i = READUINT16(save->p); + + if (i == 0xffff) + break; + + if (i >= numsectors) + I_Error("Invalid sector number %zu from server (expected end at %zu)", i, numsectors); } - if (ss->ffloors && CheckFFloorDiff(ss)) - diff |= SD_FFLOORS; + sec = §ors[i]; + j = 0; + do + SYNC(diff[j]) + while (diff[j++] & 0x80); - if (diff5) - diff4 |= SD_DIFF5; - - if (diff4) - diff3 |= SD_DIFF4; - - if (diff3) - diff2 |= SD_DIFF3; - - if (diff2) - diff |= SD_DIFF2; - - if (diff) + SYNCF(SD_FLOORHT, sec->floorheight); + SYNCF(SD_CEILHT, sec->ceilingheight); + if (GETB(SD_FLOORPIC)) { - WRITEUINT16(save->p, i); - WRITEUINT8(save->p, diff); - if (diff & SD_DIFF2) - WRITEUINT8(save->p, diff2); - if (diff2 & SD_DIFF3) - WRITEUINT8(save->p, diff3); - if (diff3 & SD_DIFF4) - WRITEUINT8(save->p, diff4); - if (diff4 & SD_DIFF5) - WRITEUINT8(save->p, diff5); - if (diff & SD_FLOORHT) - WRITEFIXED(save->p, ss->floorheight); - if (diff & SD_CEILHT) - WRITEFIXED(save->p, ss->ceilingheight); - if (diff & SD_FLOORPIC) - WRITEMEM(save->p, levelflats[ss->floorpic].name, 8); - if (diff & SD_CEILPIC) - WRITEMEM(save->p, levelflats[ss->ceilingpic].name, 8); - if (diff & SD_LIGHT) - WRITEINT16(save->p, ss->lightlevel); - if (diff & SD_SPECIAL) - WRITEINT16(save->p, ss->special); - if (diff2 & SD_FXOFFS) - WRITEFIXED(save->p, ss->floor_xoffs); - if (diff2 & SD_FYOFFS) - WRITEFIXED(save->p, ss->floor_yoffs); - if (diff2 & SD_CXOFFS) - WRITEFIXED(save->p, ss->ceiling_xoffs); - if (diff2 & SD_CYOFFS) - WRITEFIXED(save->p, ss->ceiling_yoffs); - if (diff2 & SD_FLOORANG) - WRITEANGLE(save->p, ss->floorpic_angle); - if (diff2 & SD_CEILANG) - WRITEANGLE(save->p, ss->ceilingpic_angle); - if (diff2 & SD_TAG) + if (save->write) + WRITEMEM(save->p, levelflats[sec->floorpic].name, 8); + else { - WRITEUINT32(save->p, ss->tags.count); - for (j = 0; j < ss->tags.count; j++) - WRITEINT16(save->p, ss->tags.tags[j]); + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save->p); + save->p += 8; } + } + if (GETB(SD_CEILPIC)) + { + if (save->write) + WRITEMEM(save->p, levelflats[sec->ceilingpic].name, 8); + else + { + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save->p); + save->p += 8; + } + } + SYNCF(SD_LIGHT, sec->lightlevel); + SYNCF(SD_SPECIAL, sec->special); + if (GETB(SD_FFLOORS)) + { + if (save->write) + ArchiveFFloors(save, sec); + else + UnArchiveFFloors(save, sec); + } - if (diff3 & SD_COLORMAP) - WRITEUINT32(save->p, CheckAddNetColormapToList(ss->extra_colormap)); + SYNCF(SD_FXOFFS, sec->floor_xoffs); + SYNCF(SD_FYOFFS, sec->floor_yoffs); + SYNCF(SD_CXOFFS, sec->ceiling_xoffs); + SYNCF(SD_CYOFFS, sec->ceiling_yoffs); + SYNCF(SD_FLOORANG, sec->floorpic_angle); + SYNCF(SD_CEILANG, sec->ceilingpic_angle); + if (GETB(SD_TAG)) + { + if (save->write) + { + WRITEUINT32(save->p, sec->tags.count); + for (j = 0; j < sec->tags.count; j++) + WRITEINT16(save->p, sec->tags.tags[j]); + } + else + { + size_t ncount = READUINT32(save->p); + + // Remove entries from global lists. + for (j = 0; j < sectors[i].tags.count; j++) + Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i); + + // Reallocate if size differs. + if (ncount != sectors[i].tags.count) + { + sectors[i].tags.count = ncount; + sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL); + } + + for (j = 0; j < ncount; j++) + sectors[i].tags.tags[j] = READINT16(save->p); + + // Add new entries. + for (j = 0; j < sectors[i].tags.count; j++) + Taggroup_Add(tags_sectors, sectors[i].tags.tags[j], i); + } + } + + if (GETB(SD_COLORMAP)) + { + if (save->write) + WRITEUINT32(save->p, CheckAddNetColormapToList(sec->extra_colormap)); // returns existing index if already added, or appends to net_colormaps and returns new index - if (diff3 & SD_CRUMBLESTATE) - WRITEINT32(save->p, ss->crumblestate); - if (diff3 & SD_FLOORLIGHT) - { - WRITEINT16(save->p, ss->floorlightlevel); - WRITEUINT8(save->p, ss->floorlightabsolute); - } - if (diff3 & SD_CEILLIGHT) - { - WRITEINT16(save->p, ss->ceilinglightlevel); - WRITEUINT8(save->p, ss->ceilinglightabsolute); - } - if (diff3 & SD_FLAG) - WRITEUINT32(save->p, ss->flags); - if (diff3 & SD_SPECIALFLAG) - WRITEUINT32(save->p, ss->specialflags); - if (diff4 & SD_DAMAGETYPE) - WRITEUINT8(save->p, ss->damagetype); - if (diff4 & SD_TRIGGERTAG) - WRITEINT16(save->p, ss->triggertag); - if (diff4 & SD_TRIGGERER) - WRITEUINT8(save->p, ss->triggerer); - if (diff4 & SD_GRAVITY) - WRITEFIXED(save->p, ss->gravity); + else + sec->extra_colormap = GetNetColormapFromList(READUINT32(save->p)); + } + SYNCF(SD_CRUMBLESTATE, sec->crumblestate); + SYNCF(SD_FLOORLIGHT, sec->floorlightlevel); + SYNCFB(SD_FLOORLIGHT, sec->floorlightabsolute); + SYNCF(SD_CEILLIGHT, sec->ceilinglightlevel); + SYNCFB(SD_CEILLIGHT, sec->ceilinglightabsolute); + SYNCF(SD_FLAG, sec->flags); + SYNCF(SD_SPECIALFLAG, sec->specialflags); - if (diff4 & SD_ACTION) - WRITEINT16(save->p, ss->action); - if (diff4 & SD_ARGS) + if (!save->write && GETB(SD_FLAG)) + CheckForReverseGravity |= sec->flags & MSF_GRAVITYFLIP; + + SYNCF(SD_DAMAGETYPE, sec->damagetype); + SYNCF(SD_TRIGGERTAG, sec->triggertag); + SYNCF(SD_TRIGGERER, sec->triggerer); + SYNCF(SD_GRAVITY, sec->gravity); + SYNCF(SD_ACTION, sec->action); + if (GETB(SD_ARGS)) + { + for (j = 0; j < NUM_SCRIPT_ARGS; j++) + SYNC(sec->args[j]); + } + if (GETB(SD_STRINGARGS)) + { + for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) { - for (j = 0; j < NUM_SCRIPT_ARGS; j++) - WRITEINT32(save->p, ss->args[j]); - } - if (diff4 & SD_STRINGARGS) - { - for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) + if (save->write) { size_t len, k; - if (!ss->stringargs[j]) + if (!sec->stringargs[j]) { WRITEINT32(save->p, 0); continue; } - len = strlen(ss->stringargs[j]); + len = strlen(sec->stringargs[j]); WRITEINT32(save->p, len); for (k = 0; k < len; k++) - WRITECHAR(save->p, ss->stringargs[j][k]); + WRITECHAR(save->p, sec->stringargs[j][k]); + } + else + { + size_t len = READINT32(save->p); + size_t k; + + if (!len) + { + Z_Free(sectors[i].stringargs[j]); + sectors[i].stringargs[j] = NULL; + continue; + } + + sectors[i].stringargs[j] = Z_Realloc(sectors[i].stringargs[j], len + 1, PU_LEVEL, NULL); + for (k = 0; k < len; k++) + sectors[i].stringargs[j][k] = READCHAR(save->p); + sectors[i].stringargs[j][len] = '\0'; } } - if (diff5 & SD_ACTIVATION) - WRITEUINT32(save->p, ss->activation); + } - if (diff5 & SD_BOTCONTROLLER) + SYNCF(SD_ACTIVATION, sec->activation); + if (GETB(SD_BOTCONTROLLER)) + { + if (save->write) { - //WRITEUINT8(save->p, ss->botController.trick); - WRITEUINT32(save->p, ss->botController.flags); - WRITEANGLE(save->p, ss->botController.forceAngle); + //WRITEUINT8(save->p, sec->botController.trick); + WRITEUINT32(save->p, sec->botController.flags); + WRITEANGLE(save->p, sec->botController.forceAngle); + } + else + { + //sectors[i].botController.trick = READUINT8(save->p); + sectors[i].botController.flags = READUINT32(save->p); + sectors[i].botController.forceAngle = READANGLE(save->p); } - - if (diff & SD_FFLOORS) - ArchiveFFloors(save, ss); } } - WRITEUINT16(save->p, 0xffff); + if (save->write) + WRITEUINT16(save->p, 0xffff); } -static void UnArchiveSectors(savebuffer_t *save) +static void DiffLines(savebuffer_t *save, const line_t *li, const line_t *spawnli, UINT8 diff[]) { - UINT16 i, j; - UINT8 diff, diff2, diff3, diff4, diff5; + const side_t *si, *spawnsi; + + DIFFNE(li, flags, LD_FLAG); + DIFFNE(li, special, LD_SPECIAL); + if (!Tag_Compare(&li->tags, &spawnli->tags)) + SETB(LD_TAG); + + if (!P_LineArgsEqual(li, spawnli)) + SETB(LD_ARGS); + + if (!P_LineStringArgsEqual(li, spawnli)) + SETB(LD_STRINGARGS); + + DIFFNE(li, activation, LD_ACTIVATION); + + if (li->sidenum[0] != 0xffff) + { + si = &sides[li->sidenum[0]]; + spawnsi = &spawnsides[li->sidenum[0]]; + DIFFNE(si, textureoffset, LD_S1TEXOFF); + //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. + DIFFNE(si, toptexture, LD_S1TOPTEX); + DIFFNE(si, bottomtexture, LD_S1BOTTEX); + DIFFNE(si, midtexture, LD_S1MIDTEX); + } + if (li->sidenum[1] != 0xffff) + { + si = &sides[li->sidenum[1]]; + spawnsi = &spawnsides[li->sidenum[1]]; + DIFFNE(si, textureoffset, LD_S2TEXOFF); + DIFFNE(si, toptexture, LD_S2TOPTEX); + DIFFNE(si, bottomtexture, LD_S2BOTTEX); + DIFFNE(si, midtexture, LD_S2MIDTEX); + } +} + +static void SyncLines(savebuffer_t *save) +{ + size_t i = 0, j; + line_t *li; + side_t *si; + UINT8 diff[(LD__MAX>>3)+1]; + for (;;) { - i = READUINT16(save->p); + memset(diff, 0, sizeof(diff)); + if (save->write) + { + if (++i == numlines) + break; - if (i == 0xffff) - break; + DiffLines(save, &lines[i], &spawnlines[i], diff); + for (j = sizeof(diff)-1; j > 0; j--) + if (diff[j]) + diff[j-1] |= 0x80; + if (diff[0] == 0) + continue; - if (i > numsectors) - I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - - diff = READUINT8(save->p); - if (diff & SD_DIFF2) - diff2 = READUINT8(save->p); + WRITEUINT16(save->p, i); + } else - diff2 = 0; - if (diff2 & SD_DIFF3) - diff3 = READUINT8(save->p); - else - diff3 = 0; - if (diff3 & SD_DIFF4) - diff4 = READUINT8(save->p); - else - diff4 = 0; - - if (diff4 & SD_DIFF5) - diff5 = READUINT8(save->p); - else - diff5 = 0; - - if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(save->p); - if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(save->p); - if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save->p); - save->p += 8; - } - if (diff & SD_CEILPIC) - { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save->p); - save->p += 8; - } - if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(save->p); - if (diff & SD_SPECIAL) - sectors[i].special = READINT16(save->p); + i = READUINT16(save->p); - if (diff2 & SD_FXOFFS) - sectors[i].floor_xoffs = READFIXED(save->p); - if (diff2 & SD_FYOFFS) - sectors[i].floor_yoffs = READFIXED(save->p); - if (diff2 & SD_CXOFFS) - sectors[i].ceiling_xoffs = READFIXED(save->p); - if (diff2 & SD_CYOFFS) - sectors[i].ceiling_yoffs = READFIXED(save->p); - if (diff2 & SD_FLOORANG) - sectors[i].floorpic_angle = READANGLE(save->p); - if (diff2 & SD_CEILANG) - sectors[i].ceilingpic_angle = READANGLE(save->p); - if (diff2 & SD_TAG) - { - size_t ncount = READUINT32(save->p); + if (i == 0xffff) + break; - // Remove entries from global lists. - for (j = 0; j < sectors[i].tags.count; j++) - Taggroup_Remove(tags_sectors, sectors[i].tags.tags[j], i); - - // Reallocate if size differs. - if (ncount != sectors[i].tags.count) - { - sectors[i].tags.count = ncount; - sectors[i].tags.tags = Z_Realloc(sectors[i].tags.tags, ncount*sizeof(mtag_t), PU_LEVEL, NULL); - } - - for (j = 0; j < ncount; j++) - sectors[i].tags.tags[j] = READINT16(save->p); - - // Add new entries. - for (j = 0; j < sectors[i].tags.count; j++) - Taggroup_Add(tags_sectors, sectors[i].tags.tags[j], i); + if (i >= numlines) + I_Error("Invalid line number %zu from server", i); } + li = &lines[i]; + j = 0; + do + SYNC(diff[j]) + while (diff[j++] & 0x80); - if (diff3 & SD_COLORMAP) - sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save->p)); - if (diff3 & SD_CRUMBLESTATE) - sectors[i].crumblestate = READINT32(save->p); - if (diff3 & SD_FLOORLIGHT) + SYNCF(LD_FLAG, li->flags); + SYNCF(LD_SPECIAL, li->special); + if (GETB(LD_TAG)) { - sectors[i].floorlightlevel = READINT16(save->p); - sectors[i].floorlightabsolute = READUINT8(save->p); - } - if (diff3 & SD_CEILLIGHT) - { - sectors[i].ceilinglightlevel = READINT16(save->p); - sectors[i].ceilinglightabsolute = READUINT8(save->p); - } - if (diff3 & SD_FLAG) - { - sectors[i].flags = READUINT32(save->p); - CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); - } - if (diff3 & SD_SPECIALFLAG) - sectors[i].specialflags = READUINT32(save->p); - if (diff4 & SD_DAMAGETYPE) - sectors[i].damagetype = READUINT8(save->p); - if (diff4 & SD_TRIGGERTAG) - sectors[i].triggertag = READINT16(save->p); - if (diff4 & SD_TRIGGERER) - sectors[i].triggerer = READUINT8(save->p); - if (diff4 & SD_GRAVITY) - sectors[i].gravity = READFIXED(save->p); - - if (diff4 & SD_ACTION) - sectors[i].action = READINT16(save->p); - if (diff4 & SD_ARGS) - { - for (j = 0; j < NUM_SCRIPT_ARGS; j++) - sectors[i].args[j] = READINT32(save->p); - } - if (diff4 & SD_STRINGARGS) - { - for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) - { - size_t len = READINT32(save->p); - size_t k; - - if (!len) - { - Z_Free(sectors[i].stringargs[j]); - sectors[i].stringargs[j] = NULL; - continue; - } - - sectors[i].stringargs[j] = Z_Realloc(sectors[i].stringargs[j], len + 1, PU_LEVEL, NULL); - for (k = 0; k < len; k++) - sectors[i].stringargs[j][k] = READCHAR(save->p); - sectors[i].stringargs[j][len] = '\0'; - } - } - if (diff5 & SD_ACTIVATION) - sectors[i].activation = READUINT32(save->p); - - if (diff5 & SD_BOTCONTROLLER) - { - //sectors[i].botController.trick = READUINT8(save->p); - sectors[i].botController.flags = READUINT32(save->p); - sectors[i].botController.forceAngle = READANGLE(save->p); - } - - if (diff & SD_FFLOORS) - UnArchiveFFloors(save, §ors[i]); - } -} - -static void ArchiveLines(savebuffer_t *save) -{ - size_t i, j; - const line_t *li = lines; - const line_t *spawnli = spawnlines; - const side_t *si; - const side_t *spawnsi; - UINT8 diff, diff2, diff3; - - for (i = 0; i < numlines; i++, spawnli++, li++) - { - diff = diff2 = diff3 = 0; - - if (li->flags != spawnli->flags) - diff |= LD_FLAG; - - if (li->special != spawnli->special) - diff |= LD_SPECIAL; - - if (!Tag_Compare(&li->tags, &spawnli->tags)) - diff |= LD_TAG; - - if (!P_LineArgsEqual(li, spawnli)) - diff2 |= LD_ARGS; - - if (!P_LineStringArgsEqual(li, spawnli)) - diff2 |= LD_STRINGARGS; - - if (li->activation != spawnli->activation) - diff3 |= LD_ACTIVATION; - - if (li->sidenum[0] != 0xffff) - { - si = &sides[li->sidenum[0]]; - spawnsi = &spawnsides[li->sidenum[0]]; - if (si->textureoffset != spawnsi->textureoffset) - diff |= LD_S1TEXOFF; - //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. - if (si->toptexture != spawnsi->toptexture) - diff |= LD_S1TOPTEX; - if (si->bottomtexture != spawnsi->bottomtexture) - diff |= LD_S1BOTTEX; - if (si->midtexture != spawnsi->midtexture) - diff |= LD_S1MIDTEX; - } - if (li->sidenum[1] != 0xffff) - { - si = &sides[li->sidenum[1]]; - spawnsi = &spawnsides[li->sidenum[1]]; - if (si->textureoffset != spawnsi->textureoffset) - diff2 |= LD_S2TEXOFF; - if (si->toptexture != spawnsi->toptexture) - diff2 |= LD_S2TOPTEX; - if (si->bottomtexture != spawnsi->bottomtexture) - diff2 |= LD_S2BOTTEX; - if (si->midtexture != spawnsi->midtexture) - diff2 |= LD_S2MIDTEX; - } - - if (diff3) - diff2 |= LD_DIFF3; - - if (diff2) - diff |= LD_DIFF2; - - if (diff) - { - WRITEINT16(save->p, i); - WRITEUINT8(save->p, diff); - if (diff & LD_DIFF2) - WRITEUINT8(save->p, diff2); - if (diff2 & LD_DIFF3) - WRITEUINT8(save->p, diff3); - if (diff & LD_FLAG) - WRITEUINT32(save->p, li->flags); - if (diff & LD_SPECIAL) - WRITEINT16(save->p, li->special); - if (diff & LD_TAG) + if (save->write) { 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) - WRITEFIXED(save->p, si->textureoffset); - if (diff & LD_S1TOPTEX) - WRITEINT32(save->p, si->toptexture); - if (diff & LD_S1BOTTEX) - WRITEINT32(save->p, si->bottomtexture); - if (diff & LD_S1MIDTEX) - WRITEINT32(save->p, si->midtexture); - - si = &sides[li->sidenum[1]]; - if (diff2 & LD_S2TEXOFF) - WRITEFIXED(save->p, si->textureoffset); - if (diff2 & LD_S2TOPTEX) - WRITEINT32(save->p, si->toptexture); - if (diff2 & LD_S2BOTTEX) - WRITEINT32(save->p, si->bottomtexture); - if (diff2 & LD_S2MIDTEX) - WRITEINT32(save->p, si->midtexture); - if (diff2 & LD_ARGS) + else { - for (j = 0; j < NUM_SCRIPT_ARGS; j++) - WRITEINT32(save->p, li->args[j]); + 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); } - if (diff2 & LD_STRINGARGS) + } + + si = &sides[li->sidenum[0]]; + SYNCF(LD_S1TEXOFF, si->textureoffset); + SYNCF(LD_S1TOPTEX, si->toptexture); + SYNCF(LD_S1BOTTEX, si->bottomtexture); + SYNCF(LD_S1MIDTEX, si->midtexture); + + si = &sides[li->sidenum[1]]; + SYNCF(LD_S2TEXOFF, si->textureoffset); + SYNCF(LD_S2TOPTEX, si->toptexture); + SYNCF(LD_S2BOTTEX, si->bottomtexture); + SYNCF(LD_S2MIDTEX, si->midtexture); + if (GETB(LD_ARGS)) + { + for (j = 0; j < NUM_SCRIPT_ARGS; j++) + SYNC(li->args[j]); + } + if (GETB(LD_STRINGARGS)) + { + if (save->write) { for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) { @@ -1610,157 +1529,58 @@ static void ArchiveLines(savebuffer_t *save) WRITECHAR(save->p, li->stringargs[j][k]); } } - if (diff3 & LD_ACTIVATION) - WRITEUINT32(save->p, li->activation); - } - } - WRITEUINT16(save->p, 0xffff); -} - -static void UnArchiveLines(savebuffer_t *save) -{ - UINT16 i, j; - line_t *li; - side_t *si; - UINT8 diff, diff2, diff3; - - for (;;) - { - i = READUINT16(save->p); - - if (i == 0xffff) - break; - if (i > numlines) - I_Error("Invalid line number %u from server", i); - - diff = READUINT8(save->p); - li = &lines[i]; - - if (diff & LD_DIFF2) - diff2 = READUINT8(save->p); - else - diff2 = 0; - - if (diff2 & LD_DIFF3) - diff3 = READUINT8(save->p); - else - diff3 = 0; - - if (diff & LD_FLAG) - li->flags = READUINT32(save->p); - if (diff & LD_SPECIAL) - li->special = 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) + else { - 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) - si->textureoffset = READFIXED(save->p); - if (diff & LD_S1TOPTEX) - si->toptexture = READINT32(save->p); - if (diff & LD_S1BOTTEX) - si->bottomtexture = READINT32(save->p); - if (diff & LD_S1MIDTEX) - si->midtexture = READINT32(save->p); - - si = &sides[li->sidenum[1]]; - if (diff2 & LD_S2TEXOFF) - si->textureoffset = READFIXED(save->p); - if (diff2 & LD_S2TOPTEX) - si->toptexture = READINT32(save->p); - if (diff2 & LD_S2BOTTEX) - si->bottomtexture = READINT32(save->p); - if (diff2 & LD_S2MIDTEX) - si->midtexture = READINT32(save->p); - if (diff2 & LD_ARGS) - { - for (j = 0; j < NUM_SCRIPT_ARGS; j++) - li->args[j] = READINT32(save->p); - } - if (diff2 & LD_STRINGARGS) - { - for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) - { - size_t len = READINT32(save->p); - size_t k; - - if (!len) + for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) { - Z_Free(li->stringargs[j]); - li->stringargs[j] = NULL; - continue; - } + size_t len = READINT32(save->p); + size_t k; - li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); - for (k = 0; k < len; k++) - li->stringargs[j][k] = READCHAR(save->p); - li->stringargs[j][len] = '\0'; + if (!len) + { + Z_Free(li->stringargs[j]); + li->stringargs[j] = NULL; + continue; + } + + li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); + for (k = 0; k < len; k++) + li->stringargs[j][k] = READCHAR(save->p); + li->stringargs[j][len] = '\0'; + } } } - if (diff3 & LD_ACTIVATION) - li->activation = READUINT32(save->p); + SYNCF(LD_ACTIVATION, li->activation); } + + if (save->write) + WRITEUINT16(save->p, 0xffff); } -static void P_NetArchiveWorld(savebuffer_t *save) +static void P_NetSyncWorld(savebuffer_t *save) { TracyCZone(__zone, true); - // initialize colormap vars because paranoia - ClearNetColormaps(); - - WRITEUINT32(save->p, ARCHIVEBLOCK_WORLD); - - ArchiveSectors(save); - ArchiveLines(save); - R_ClearTextureNumCache(false); - - TracyCZoneEnd(__zone); -} - -static void P_NetUnArchiveWorld(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - UINT16 i; - - if (READUINT32(save->p) != ARCHIVEBLOCK_WORLD) + if (P_SyncUINT32(save, ARCHIVEBLOCK_WORLD) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); // initialize colormap vars because paranoia ClearNetColormaps(); // count the level's ffloors so that colormap loading can have an upper limit - for (i = 0; i < numsectors; i++) - { - ffloor_t *rover; - for (rover = sectors[i].ffloors; rover; rover = rover->next) - num_ffloors++; - } + if (!save->write) + for (size_t i = 0; i < numsectors; i++) + { + ffloor_t *rover; + for (rover = sectors[i].ffloors; rover; rover = rover->next) + num_ffloors++; + } - UnArchiveSectors(save); - UnArchiveLines(save); + SyncSectors(save); + SyncLines(save); + if (save->write) + R_ClearTextureNumCache(false); TracyCZoneEnd(__zone); } @@ -5590,7 +5410,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) if (gamestate == GS_LEVEL) { - P_NetArchiveWorld(save); + P_NetSyncWorld(save); P_ArchivePolyObjects(save); P_NetArchiveThinkers(save); P_NetSyncSpecials(save); @@ -5642,7 +5462,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) if (gamestate == GS_LEVEL) { - P_NetUnArchiveWorld(save); + P_NetSyncWorld(save); P_UnArchivePolyObjects(save); P_NetUnArchiveThinkers(save); P_NetSyncSpecials(save); From d65156d69642bc59781887312694aeb3fd598481 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 5 Oct 2025 00:58:23 +0200 Subject: [PATCH 16/24] Refactor FOF archiving too! --- src/p_saveg.c | 107 +++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 66 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index ade09404f..36f525da8 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -912,8 +912,8 @@ static void P_NetSyncColormaps(savebuffer_t *save) /// // each byte contains 7 flags -// the most signifcant bit indicates a following extra byte -enum +// the most significant bit indicates a following extra byte +enum sectordiff_e { SD_FLOORHT = 0<<3, SD_CEILHT, @@ -957,6 +957,12 @@ enum SD__MAX }; +enum ffloordiff_e +{ + FD_FLAGS, + FD_ALPHA, +}; + static boolean P_SectorArgsEqual(const sector_t *sc, const sector_t *spawnsc) { UINT8 i; @@ -982,7 +988,7 @@ static boolean P_SectorStringArgsEqual(const sector_t *sc, const sector_t *spawn return true; } -enum +enum linediff_e { LD_FLAG = 0<<3, LD_SPECIAL, @@ -1042,9 +1048,6 @@ static boolean P_LineStringArgsEqual(const line_t *li, const line_t *spawnli) return true; } -#define FD_FLAGS 0x01 -#define FD_ALPHA 0x02 - // Check if any of the sector's FOFs differ from how they spawned static boolean CheckFFloorDiff(const sector_t *ss) { @@ -1064,71 +1067,48 @@ static boolean CheckFFloorDiff(const sector_t *ss) // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed -static void ArchiveFFloors(savebuffer_t *save, const sector_t *ss) +static void SyncFFloors(savebuffer_t *save, const sector_t *ss) { size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc ffloor_t *rover; - UINT8 fflr_diff; - for (rover = ss->ffloors; rover; rover = rover->next) - { - fflr_diff = 0; // reset diff flags - if (rover->fofflags != rover->spawnflags) - fflr_diff |= FD_FLAGS; - if (rover->alpha != rover->spawnalpha) - fflr_diff |= FD_ALPHA; - - if (fflr_diff) - { - WRITEUINT16(save->p, j); // save ffloor "number" - WRITEUINT8(save->p, fflr_diff); - if (fflr_diff & FD_FLAGS) - WRITEUINT32(save->p, rover->fofflags); - if (fflr_diff & FD_ALPHA) - WRITEINT16(save->p, rover->alpha); - } - j++; - } - WRITEUINT16(save->p, 0xffff); -} - -static void UnArchiveFFloors(savebuffer_t *save, const sector_t *ss) -{ - UINT16 j = 0; // number of current ffloor in loop UINT16 fflr_i; // saved ffloor "number" of next modified ffloor - UINT16 fflr_diff; // saved ffloor diff - ffloor_t *rover; + UINT8 diff[1]; - rover = ss->ffloors; - if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... - I_Error("Sector does not have any ffloors!"); + if (!save->write) + fflr_i = READUINT16(save->p); // get first modified ffloor's number ready - fflr_i = READUINT16(save->p); // get first modified ffloor's number ready - for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? + for (rover = ss->ffloors; rover; rover = rover->next, j++) { - if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already - break; - // should NEVER need to be checked - //if (rover == NULL) - //break; - if (j != fflr_i) // this ffloor was not modified + memset(diff, 0, sizeof(diff)); + if (save->write) { - j++; - rover = rover->next; - continue; + if (rover->fofflags != rover->spawnflags) + SETB(FD_FLAGS); + if (rover->alpha != rover->spawnalpha) + SETB(FD_ALPHA); + + if (diff[0] == 0) + continue; + + WRITEUINT16(save->p, j); + } + else + { + if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already + break; + if (j != fflr_i) // this ffloor was not modified + continue; + + fflr_i = READUINT16(save->p); // get next ffloor "number" ready } - fflr_diff = READUINT8(save->p); - - if (fflr_diff & FD_FLAGS) - rover->fofflags = READUINT32(save->p); - if (fflr_diff & FD_ALPHA) - rover->alpha = READINT16(save->p); - - fflr_i = READUINT16(save->p); // get next ffloor "number" ready - - j++; - rover = rover->next; + SYNC(diff[0]); + SYNCF(FD_FLAGS, rover->fofflags); + SYNCF(FD_ALPHA, rover->alpha); } + + if (save->write) + WRITEUINT16(save->p, 0xffff); } static void DiffSectors(savebuffer_t *save, const sector_t *ss, const sector_t *spawnss, UINT8 diff[]) @@ -1245,12 +1225,7 @@ static void SyncSectors(savebuffer_t *save) SYNCF(SD_LIGHT, sec->lightlevel); SYNCF(SD_SPECIAL, sec->special); if (GETB(SD_FFLOORS)) - { - if (save->write) - ArchiveFFloors(save, sec); - else - UnArchiveFFloors(save, sec); - } + SyncFFloors(save, sec); SYNCF(SD_FXOFFS, sec->floor_xoffs); SYNCF(SD_FYOFFS, sec->floor_yoffs); From a9c3a9950d81eb9bf88f2bf041569d5fb9bd8486 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 5 Oct 2025 13:29:32 -0400 Subject: [PATCH 17/24] Refactor thinkers (currently not working) --- src/p_saveg.c | 4030 ++++++++++++++++++++----------------------------- 1 file changed, 1665 insertions(+), 2365 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 36f525da8..03cab0182 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -224,15 +224,15 @@ waypoint_t *P_SyncWaypoint(savebuffer_t *save, waypoint_t *wp) UINT32: P_SyncUINT32, \ mobj_t *: P_SyncMobj, \ waypoint_t *: P_SyncWaypoint \ -)(save, v); +)(save, v) #define SYNCBOOLEAN(v) v = _Generic(v, \ boolean: P_SyncUINT8 \ -)(save, v); +)(save, v) #define SYNCRELINK(v) v = _Generic(v, \ mobj_t *: P_SyncMobjAndRelink \ -)(save, v); +)(save, v) // Block UINT32s to attempt to ensure that the correct data is // being sent and received @@ -1014,14 +1014,16 @@ enum linediff_e }; // diff macros -#define SETB(b) (diff[b >> 3] |= (1 << (b & 7))) +#define SETB(b) (diff[b / (8*sizeof(*diff))] |= (1 << (b & (8*sizeof(*diff) - 1)))) #define DIFFNE(x, field, b) if (x->field != spawn##x->field) SETB(b) #define DIFFIF(x, field, b) if (x->field) SETB(b) +#define DIFF(x, b) if (x) SETB(b) // sync macros -#define GETB(b) (diff[b >> 3] & (1 << (b & 7))) +#define GETB(b) (diff[b / (8*sizeof(*diff))] & (1 << (b & (8*sizeof(*diff) - 1)))) #define SYNCF(b, v) if (GETB(b)) SYNC(v) #define SYNCFB(b, v) if (GETB(b)) SYNCBOOLEAN(v) +#define SYNCDEF(b, v, d) (GETB(b) ? SYNC(v) : (v = d)) static boolean P_LineArgsEqual(const line_t *li, const line_t *spawnli) { @@ -1197,7 +1199,7 @@ static void SyncSectors(savebuffer_t *save) sec = §ors[i]; j = 0; do - SYNC(diff[j]) + SYNC(diff[j]); while (diff[j++] & 0x80); SYNCF(SD_FLOORHT, sec->floorheight); @@ -1431,7 +1433,7 @@ static void SyncLines(savebuffer_t *save) li = &lines[i]; j = 0; do - SYNC(diff[j]) + SYNC(diff[j]); while (diff[j++] & 0x80); SYNCF(LD_FLAG, li->flags); @@ -1611,86 +1613,80 @@ static boolean P_ThingScriptEqual(const mobj_t *mobj, const mapthing_t *mapthing return true; } -typedef enum +enum mobj_diff_t { - MD_SPAWNPOINT = 1, - MD_POS = 1<<1, - MD_TYPE = 1<<2, - MD_MOM = 1<<3, - MD_RADIUS = 1<<4, - MD_HEIGHT = 1<<5, - MD_FLAGS = 1<<6, - MD_HEALTH = 1<<7, - MD_RTIME = 1<<8, - MD_STATE = 1<<9, - MD_TICS = 1<<10, - MD_SPRITE = 1<<11, - MD_FRAME = 1<<12, - MD_EFLAGS = 1<<13, - MD_PLAYER = 1<<14, - MD_MOVEDIR = 1<<15, - MD_MOVECOUNT = 1<<16, - MD_THRESHOLD = 1<<17, - MD_LASTLOOK = 1<<18, - MD_TARGET = 1<<19, - MD_TRACER = 1<<20, - MD_FRICTION = 1<<21, - MD_MOVEFACTOR = 1<<22, - MD_FLAGS2 = 1<<23, - MD_FUSE = 1<<24, - MD_WATERTOP = 1<<25, - MD_WATERBOTTOM = 1<<26, - MD_SCALE = 1<<27, - MD_DSCALE = 1<<28, - MD_ARGS = 1<<29, - MD_STRINGARGS = 1<<30, - MD_MORE = (INT32)(1U<<31) -} mobj_diff_t; + MD_SPAWNPOINT = 0<<5, + MD_POS, + MD_TYPE, + MD_MOM, + MD_RADIUS, + MD_HEIGHT, + MD_FLAGS, + MD_HEALTH, + MD_RTIME, + MD_STATE, + MD_TICS, + MD_SPRITE, + MD_FRAME, + MD_EFLAGS, + MD_PLAYER, + MD_MOVEDIR, + MD_MOVECOUNT, + MD_THRESHOLD, + MD_LASTLOOK, + MD_TARGET, + MD_TRACER, + MD_FRICTION, + MD_MOVEFACTOR, + MD_FLAGS2, + MD_FUSE, + MD_WATERTOP, + MD_WATERBOTTOM, + MD_SCALE, + MD_DSCALE, + MD_ARGS, + MD_STRINGARGS, -typedef enum -{ - MD2_CUSVAL = 1, - MD2_CVMEM = 1<<1, - MD2_SKIN = 1<<2, - MD2_COLOR = 1<<3, - MD2_SCALESPEED = 1<<4, - MD2_EXTVAL1 = 1<<5, - MD2_EXTVAL2 = 1<<6, - MD2_HNEXT = 1<<7, - MD2_HPREV = 1<<8, - MD2_FLOORROVER = 1<<9, - MD2_CEILINGROVER = 1<<10, - MD2_SLOPE = 1<<11, - MD2_COLORIZED = 1<<12, - MD2_MIRRORED = 1<<13, - MD2_ROLLANGLE = 1<<14, - MD2_SHADOWSCALE = 1<<15, - MD2_RENDERFLAGS = 1<<16, - MD2_TID = 1<<17, - MD2_SPRITESCALE = 1<<18, - MD2_SPRITEOFFSET = 1<<19, - MD2_WORLDOFFSET = 1<<20, - MD2_SPECIAL = 1<<21, - MD2_FLOORSPRITESLOPE = 1<<22, - MD2_DISPOFFSET = 1<<23, - MD2_BOSS3CAP = 1<<24, - MD2_WAYPOINTCAP = 1<<25, - MD2_KITEMCAP = 1<<26, - MD2_ITNEXT = 1<<27, - MD2_LASTMOMZ = 1<<28, - MD2_TERRAIN = 1<<29, - MD2_LIGHTLEVEL = 1<<30, - MD2_MORE = (INT32)(1U<<31) -} mobj_diff2_t; + MD2_CUSVAL = 1<<5, + MD2_CVMEM, + MD2_SKIN, + MD2_COLOR, + MD2_SCALESPEED, + MD2_EXTVAL1, + MD2_EXTVAL2, + MD2_HNEXT, + MD2_HPREV, + MD2_FLOORROVER, + MD2_CEILINGROVER, + MD2_SLOPE, + MD2_COLORIZED, + MD2_MIRRORED, + MD2_ROLLANGLE, + MD2_SHADOWSCALE, + MD2_RENDERFLAGS, + MD2_TID, + MD2_SPRITESCALE, + MD2_SPRITEOFFSET, + MD2_WORLDOFFSET, + MD2_SPECIAL, + MD2_FLOORSPRITESLOPE, + MD2_DISPOFFSET, + MD2_BOSS3CAP, + MD2_WAYPOINTCAP, + MD2_KITEMCAP, + MD2_ITNEXT, + MD2_LASTMOMZ, + MD2_TERRAIN, + MD2_LIGHTLEVEL, -typedef enum -{ - MD3_GRAVITY = 1, - MD3_MISCCAP = 1<<1, - MD3_BAKEDOFFSET = 1<<2, - MD3_EXTVAL3 = 1<<3, - MD3_SHIELDTRACER = 1<<4, -} mobj_diff3_t; + MD3_GRAVITY = 2<<5, + MD3_MISCCAP, + MD3_BAKEDOFFSET, + MD3_EXTVAL3, + MD3_SHIELDTRACER, + + MD__MAX +}; typedef enum { @@ -1738,16 +1734,107 @@ typedef enum tc_end } specials_e; +const actionf_p1 actionspecials[tc_end] = +{ + (actionf_p1)P_MobjThinker, + (actionf_p1)T_MoveCeiling, + (actionf_p1)T_CrushCeiling, + (actionf_p1)T_MoveFloor, + (actionf_p1)T_LightningFlash, + (actionf_p1)T_StrobeFlash, + (actionf_p1)T_Glow, + (actionf_p1)T_FireFlicker, + (actionf_p1)T_MoveElevator, + (actionf_p1)T_ContinuousFalling, + (actionf_p1)T_ThwompSector, + (actionf_p1)T_NoEnemiesSector, + (actionf_p1)T_EachTimeThinker, + (actionf_p1)T_RaiseSector, + (actionf_p1)T_CameraScanner, + (actionf_p1)T_Scroll, + (actionf_p1)T_Friction, + (actionf_p1)T_Pusher, + (actionf_p1)T_BounceCheese, + (actionf_p1)T_StartCrumble, + (actionf_p1)T_MarioBlock, + (actionf_p1)T_MarioBlockChecker, + (actionf_p1)T_FloatSector, + (actionf_p1)T_LaserFlash, + (actionf_p1)T_LightFade, + (actionf_p1)T_ExecutorDelay, + (actionf_p1)T_Disappear, + (actionf_p1)T_Fade, + (actionf_p1)T_FadeColormap, + (actionf_p1)T_PlaneDisplace, + (actionf_p1)T_PolyObjRotate, + (actionf_p1)T_PolyObjMove, + (actionf_p1)T_PolyObjWaypoint, + (actionf_p1)T_PolyDoorSlide, + (actionf_p1)T_PolyDoorSwing, + (actionf_p1)T_PolyObjFlag, + (actionf_p1)T_PolyObjDisplace, + (actionf_p1)T_PolyObjRotDisplace, + (actionf_p1)T_PolyObjFade, + (actionf_p1)T_DynamicSlopeLine, + (actionf_p1)T_DynamicSlopeVert, +}; + +I_StaticAssert(sizeof(actionspecials) / sizeof(actionspecials[0]) == tc_end); + static inline UINT32 SaveMobjnum(const mobj_t *mobj) { if (mobj) return mobj->mobjnum; return 0; } -static UINT32 SaveSector(const sector_t *sector) +static mobj_t *SyncMobj(savebuffer_t *save, mobj_t *mobj) +{ + if (save->write) + { + if (mobj) WRITEUINT32(save->p, mobj->mobjnum); + else WRITEUINT32(save->p, 0); + return mobj; + } + else + { + UINT32 mobjnum = READUINT32(save->p); + if (mobjnum == 0) return NULL; + return (mobj_t *)(size_t)mobjnum; + } +} + +static sector_t *LoadSector(UINT32 sector) +{ + if (sector >= numsectors) return NULL; + return §ors[sector]; +} + +static UINT32 SaveSector(sector_t *sector) { if (sector) return (UINT32)(sector - sectors); - return 0xFFFFFFFF; + else return 0xFFFFFFFF; +} + +static sector_t *SyncSector(savebuffer_t *save, sector_t *sector) +{ + if (save->write) + { + if (sector) WRITEUINT32(save->p, (UINT32)(sector - sectors)); + else WRITEUINT32(save->p, 0xFFFFFFFF); + return sector; + } + else + { + UINT32 sectornum = READUINT32(save->p); + if (sectornum >= numsectors) return NULL; + return §ors[sectornum]; + } +} + +static line_t *LoadLine(UINT32 line) +{ + if (line >= numlines) return NULL; + return &lines[line]; } static UINT32 SaveLine(const line_t *line) @@ -1756,6 +1843,28 @@ static UINT32 SaveLine(const line_t *line) return 0xFFFFFFFF; } +static line_t *SyncLine(savebuffer_t *save, line_t *line) +{ + if (save->write) + { + if (line) WRITEUINT32(save->p, (UINT32)(line - lines)); + else WRITEUINT32(save->p, 0xFFFFFFFF); + return line; + } + else + { + UINT32 linenum = READUINT32(save->p); + if (linenum >= numlines) return NULL; + return &lines[linenum]; + } +} + +static inline player_t *LoadPlayer(UINT32 player) +{ + if (player >= MAXPLAYERS) return NULL; + return &players[player]; +} + static inline UINT32 SavePlayer(const player_t *player) { if (player) return (UINT32)(player - players); @@ -1768,70 +1877,75 @@ static UINT32 SaveSlope(const pslope_t *slope) return 0xFFFFFFFF; } -static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static pslope_t *SyncSlope(savebuffer_t *save, pslope_t *slope) { - const mobj_t *mobj = (const mobj_t *)th; - UINT32 diff; - UINT32 diff2; - UINT32 diff3; - size_t j; + if (save->write) + { + if (slope) WRITEUINT32(save->p, (UINT32)(slope->id)); + else WRITEUINT32(save->p, 0xFFFFFFFF); + return slope; + } + else + { + UINT32 slopeid = READUINT32(save->p); + pslope_t *p = slopelist; + if (slopeid > slopecount) return NULL; + do + { + if (p->id == slopeid) + return p; + } while ((p = p->next)); + return NULL; + } +} - // Ignore stationary hoops - these will be respawned from mapthings. - if (mobj->type == MT_HOOP) - return; +static mobjtype_t g_doomednum_to_mobjtype[UINT16_MAX]; - // These are NEVER saved. - if (mobj->type == MT_HOOPCOLLIDE) - return; +static void CalculateDoomednumToMobjtype(void) +{ + memset(g_doomednum_to_mobjtype, MT_NULL, sizeof(g_doomednum_to_mobjtype)); - // This hoop has already been collected. - if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242) - return; + 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 ] = i; + } + } +} - // MT_SPARK: used for debug stuff - if (mobj->type == MT_SPARK) - return; - - // This is a non-synched visual effect mobj - if (mobj->flags2 & MF2_DONTSYNC) - return; - - diff = diff2 = diff3 = 0; - - if (mobj->spawnpoint) +static void DiffMobj(const mobj_t *mobj, UINT32 diff[]) +{ + if (mobj->spawnpoint && mobj->info->doomednum != -1) { // spawnpoint is not modified but we must save it since it is an identifier - diff = MD_SPAWNPOINT; + SETB(MD_SPAWNPOINT); if ((mobj->x != mobj->spawnpoint->x << FRACBITS) || (mobj->y != mobj->spawnpoint->y << FRACBITS) || (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)) || (mobj->pitch != FixedAngle(mobj->spawnpoint->pitch*FRACUNIT)) || (mobj->roll != FixedAngle(mobj->spawnpoint->roll*FRACUNIT)) ) - diff |= MD_POS; + SETB(MD_POS); - if (mobj->info->doomednum != mobj->spawnpoint->type) - diff |= MD_TYPE; - - 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; + DIFF(mobj->info->doomednum != mobj->spawnpoint->type, MD_TYPE); + DIFF(!P_ThingArgsEqual(mobj, mobj->spawnpoint), MD_ARGS); + DIFF(!P_ThingStringArgsEqual(mobj, mobj->spawnpoint), MD_STRINGARGS); + DIFF(!P_ThingScriptEqual(mobj, mobj->spawnpoint), MD2_SPECIAL); } else { + size_t j; + // not a map spawned thing, so make it from scratch - diff = MD_POS | MD_TYPE; + SETB(MD_POS); + SETB(MD_TYPE); for (j = 0; j < NUM_MAPTHING_ARGS; j++) { if (mobj->args[j] != 0) { - diff |= MD_ARGS; + SETB(MD_ARGS); break; } } @@ -1840,21 +1954,19 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 { if (mobj->stringargs[j] != NULL) { - diff |= MD_STRINGARGS; + SETB(MD_STRINGARGS); break; } } if (mobj->special != 0) - { - diff2 |= MD2_SPECIAL; - } + SETB(MD2_SPECIAL); for (j = 0; j < NUM_SCRIPT_ARGS; j++) { if (mobj->script_args[j] != 0) { - diff2 |= MD2_SPECIAL; + SETB(MD2_SPECIAL); break; } } @@ -1863,1181 +1975,1715 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 { if (mobj->stringargs[j] != NULL) { - diff2 |= MD2_SPECIAL; + SETB(MD2_SPECIAL); break; } } } // not the default but the most probable - if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0) - diff |= MD_MOM; - if (mobj->radius != FixedMul(mapobjectscale, mobj->info->radius)) - diff |= MD_RADIUS; - if (mobj->height != FixedMul(mapobjectscale, mobj->info->height)) - diff |= MD_HEIGHT; - if (mobj->flags != mobj->info->flags) - diff |= MD_FLAGS; - if (mobj->flags2) - diff |= MD_FLAGS2; - if (mobj->health != mobj->info->spawnhealth) - diff |= MD_HEALTH; - if (mobj->reactiontime != mobj->info->reactiontime) - diff |= MD_RTIME; - if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) - diff |= MD_STATE; - if (mobj->tics != mobj->state->tics) - diff |= MD_TICS; - if (mobj->sprite != mobj->state->sprite) - diff |= MD_SPRITE; - if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK)) - diff |= MD_SPRITE; - if (mobj->frame != mobj->state->frame) - diff |= MD_FRAME; - if (mobj->anim_duration != (UINT16)mobj->state->var2) - diff |= MD_FRAME; - if (mobj->eflags) - diff |= MD_EFLAGS; - if (mobj->player) - diff |= MD_PLAYER; + DIFF(mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz != 0, MD_MOM); + DIFF(mobj->radius != FixedMul(mapobjectscale, mobj->info->radius), MD_RADIUS); + DIFF(mobj->height != FixedMul(mapobjectscale, mobj->info->height), MD_HEIGHT); + DIFF(mobj->flags != mobj->info->flags, MD_FLAGS); + DIFF(mobj->flags2, MD_FLAGS2); + DIFF(mobj->health != mobj->info->spawnhealth, MD_HEALTH); + DIFF(mobj->reactiontime != mobj->info->reactiontime, MD_RTIME); + DIFF((statenum_t)(mobj->state-states) != mobj->info->spawnstate, MD_STATE); + DIFF(mobj->tics != mobj->state->tics, MD_TICS); + DIFF(mobj->sprite != mobj->state->sprite, MD_SPRITE); + DIFF(mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK), MD_SPRITE); + DIFF(mobj->frame != mobj->state->frame, MD_FRAME); + DIFF(mobj->anim_duration != (UINT16)mobj->state->var2, MD_FRAME); + DIFF(mobj->eflags, MD_EFLAGS); + DIFF(mobj->player, MD_PLAYER); - if (mobj->movedir) - diff |= MD_MOVEDIR; - if (mobj->movecount) - diff |= MD_MOVECOUNT; - if (mobj->threshold) - diff |= MD_THRESHOLD; - if (mobj->lastlook != -1) - diff |= MD_LASTLOOK; - if (mobj->target) - diff |= MD_TARGET; - if (mobj->tracer) - diff |= MD_TRACER; - if (mobj->friction != ORIG_FRICTION) - diff |= MD_FRICTION; - if (mobj->movefactor != FRACUNIT) - diff |= MD_MOVEFACTOR; - if (mobj->fuse) - diff |= MD_FUSE; - if (mobj->watertop != INT32_MAX) - diff |= MD_WATERTOP; - if (mobj->waterbottom) - diff |= MD_WATERBOTTOM; - if (mobj->scale != mapobjectscale) - diff |= MD_SCALE; - if (mobj->destscale != mobj->scale) - diff |= MD_DSCALE; - if (mobj->scalespeed != mapobjectscale/12) - diff2 |= MD2_SCALESPEED; + DIFF(mobj->movedir, MD_MOVEDIR); + DIFF(mobj->movecount, MD_MOVECOUNT); + DIFF(mobj->threshold, MD_THRESHOLD); + DIFF(mobj->lastlook != -1, MD_LASTLOOK); + DIFF(mobj->target, MD_TARGET); + DIFF(mobj->tracer, MD_TRACER); + DIFF(mobj->friction != ORIG_FRICTION, MD_FRICTION); + DIFF(mobj->movefactor != FRACUNIT, MD_MOVEFACTOR); + DIFF(mobj->fuse, MD_FUSE); + DIFF(mobj->watertop != INT32_MAX, MD_WATERTOP); + DIFF(mobj->waterbottom, MD_WATERBOTTOM); + DIFF(mobj->scale != mapobjectscale, MD_SCALE); + DIFF(mobj->destscale != mobj->scale, MD_DSCALE); + DIFF(mobj->scalespeed != mapobjectscale/12, MD2_SCALESPEED); - if (mobj->cusval) - diff2 |= MD2_CUSVAL; - if (mobj->cvmem) - diff2 |= MD2_CVMEM; - if (mobj->color) - diff2 |= MD2_COLOR; - if (mobj->skin) - diff2 |= MD2_SKIN; - if (mobj->extravalue1) - diff2 |= MD2_EXTVAL1; - if (mobj->extravalue2) - diff2 |= MD2_EXTVAL2; - if (mobj->hnext) - diff2 |= MD2_HNEXT; - if (mobj->hprev) - diff2 |= MD2_HPREV; - if (mobj->standingslope) - diff2 |= MD2_SLOPE; - if (mobj->colorized) - diff2 |= MD2_COLORIZED; - if (mobj->floorrover) - diff2 |= MD2_FLOORROVER; - if (mobj->ceilingrover) - diff2 |= MD2_CEILINGROVER; - if (mobj->mirrored) - diff2 |= MD2_MIRRORED; - if (mobj->rollangle) - diff2 |= MD2_ROLLANGLE; - if (mobj->shadowscale) - diff2 |= MD2_SHADOWSCALE; - if (mobj->renderflags) - diff2 |= MD2_RENDERFLAGS; - if (mobj->tid != 0) - diff2 |= MD2_TID; - if (mobj->spritexscale != FRACUNIT || mobj->spriteyscale != FRACUNIT) - diff2 |= MD2_SPRITESCALE; - if (mobj->spritexoffset || mobj->spriteyoffset || - mobj->rollingxoffset || mobj->rollingyoffset) - diff2 |= MD2_SPRITEOFFSET; - if (mobj->sprxoff || mobj->spryoff || mobj->sprzoff) - diff2 |= MD2_WORLDOFFSET; + DIFF(mobj->cusval, MD2_CUSVAL); + DIFF(mobj->cvmem, MD2_CVMEM); + DIFF(mobj->color, MD2_COLOR); + DIFF(mobj->skin, MD2_SKIN); + DIFF(mobj->extravalue1, MD2_EXTVAL1); + DIFF(mobj->extravalue2, MD2_EXTVAL2); + DIFF(mobj->hnext, MD2_HNEXT); + DIFF(mobj->hprev, MD2_HPREV); + DIFF(mobj->standingslope, MD2_SLOPE); + DIFF(mobj->colorized, MD2_COLORIZED); + DIFF(mobj->floorrover, MD2_FLOORROVER); + DIFF(mobj->ceilingrover, MD2_CEILINGROVER); + DIFF(mobj->mirrored, MD2_MIRRORED); + DIFF(mobj->rollangle, MD2_ROLLANGLE); + DIFF(mobj->shadowscale, MD2_SHADOWSCALE); + DIFF(mobj->renderflags, MD2_RENDERFLAGS); + DIFF(mobj->tid != 0, MD2_TID); + DIFF(mobj->spritexscale != FRACUNIT || mobj->spriteyscale != FRACUNIT, MD2_SPRITESCALE); + DIFF(mobj->spritexoffset || mobj->spriteyoffset || mobj->rollingxoffset || mobj->rollingyoffset, MD2_SPRITEOFFSET); + DIFF(mobj->sprxoff || mobj->spryoff || mobj->sprzoff, MD2_WORLDOFFSET); if (mobj->floorspriteslope) { pslope_t *slope = mobj->floorspriteslope; - if (slope->zangle || slope->zdelta || slope->xydirection + DIFF(slope->zangle || slope->zdelta || slope->xydirection || slope->o.x || slope->o.y || slope->o.z || slope->d.x || slope->d.y || slope->normal.x || slope->normal.y - || (slope->normal.z != FRACUNIT)) - diff2 |= MD2_FLOORSPRITESLOPE; + || (slope->normal.z != FRACUNIT), + MD2_FLOORSPRITESLOPE); } - if (mobj->lightlevel) - diff2 |= MD2_LIGHTLEVEL; - if (mobj->dispoffset) - diff2 |= MD2_DISPOFFSET; - if (mobj == boss3cap) - diff2 |= MD2_BOSS3CAP; - if (mobj == waypointcap) - diff2 |= MD2_WAYPOINTCAP; - if (mobj == kitemcap) - diff2 |= MD2_KITEMCAP; - if (mobj->itnext) - diff2 |= MD2_ITNEXT; - if (mobj->lastmomz) - diff2 |= MD2_LASTMOMZ; - if (mobj->terrain != NULL || mobj->terrainOverlay != NULL) - diff2 |= MD2_TERRAIN; + DIFF(mobj->lightlevel, MD2_LIGHTLEVEL); + DIFF(mobj->dispoffset, MD2_DISPOFFSET); + DIFF(mobj == boss3cap, MD2_BOSS3CAP); + DIFF(mobj == waypointcap, MD2_WAYPOINTCAP); + DIFF(mobj == kitemcap, MD2_KITEMCAP); + DIFF(mobj->itnext, MD2_ITNEXT); + DIFF(mobj->lastmomz, MD2_LASTMOMZ); + DIFF(mobj->terrain != NULL || mobj->terrainOverlay != NULL, MD2_TERRAIN); - if (mobj->gravity != FRACUNIT) - diff3 |= MD3_GRAVITY; - if (mobj == misccap) - diff3 |= MD3_MISCCAP; - if (mobj->bakexoff || mobj->bakeyoff || mobj->bakezoff || mobj->bakexpiv || - mobj->bakeypiv || mobj->bakezpiv) - diff3 |= MD3_BAKEDOFFSET; - if (mobj->extravalue3) - diff3 |= MD3_EXTVAL3; - if (mobj->shieldtracer) - diff3 |= MD3_SHIELDTRACER; + DIFF(mobj->gravity != FRACUNIT, MD3_GRAVITY); + DIFF(mobj == misccap, MD3_MISCCAP); + DIFF(mobj->bakexoff || mobj->bakeyoff || mobj->bakezoff || mobj->bakexpiv || mobj->bakeypiv || mobj->bakezpiv, MD3_BAKEDOFFSET); + DIFF(mobj->extravalue3, MD3_EXTVAL3); + DIFF(mobj->shieldtracer, MD3_SHIELDTRACER); +} - if (diff3 != 0) - diff2 |= MD2_MORE; +static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) +{ + mobj_t *mobj = (mobj_t *)th; + UINT32 diff[(MD__MAX>>5)+1] = {0}; + size_t j; - if (diff2 != 0) - diff |= MD_MORE; - - // Scrap all of that. If we're a hoop center, this is ALL we're saving. - if (mobj->type == MT_HOOPCENTER) - diff = MD_SPAWNPOINT; - - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, diff); - if (diff & MD_MORE) - WRITEUINT32(save->p, diff2); - if (diff2 & MD2_MORE) - WRITEUINT32(save->p, diff3); - - WRITEFIXED(save->p, mobj->z); // Force this so 3dfloor problems don't arise. - WRITEFIXED(save->p, mobj->floorz); - WRITEFIXED(save->p, mobj->ceilingz); - - if (diff2 & MD2_FLOORROVER) + if (save->write) { - WRITEUINT32(save->p, SaveSector(mobj->floorrover->target)); - WRITEUINT16(save->p, P_GetFFloorID(mobj->floorrover)); - } + // Ignore stationary hoops - these will be respawned from mapthings. + if (mobj->type == MT_HOOP) + return th; - if (diff2 & MD2_CEILINGROVER) - { - WRITEUINT32(save->p, SaveSector(mobj->ceilingrover->target)); - WRITEUINT16(save->p, P_GetFFloorID(mobj->ceilingrover)); - } + // These are NEVER saved. + if (mobj->type == MT_HOOPCOLLIDE) + return th; - if (diff & MD_SPAWNPOINT) - { - size_t z; + // This hoop has already been collected. + if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242) + return th; - for (z = 0; z < nummapthings; z++) - { - if (&mapthings[z] != mobj->spawnpoint) - continue; - WRITEUINT16(save->p, z); - break; - } + // MT_SPARK: used for debug stuff + if (mobj->type == MT_SPARK) + return th; + + // This is a non-synched visual effect mobj + if (mobj->flags2 & MF2_DONTSYNC) + return th; + + // Scrap all of that. If we're a hoop center, this is ALL we're saving. if (mobj->type == MT_HOOPCENTER) - return; + SETB(MD_SPAWNPOINT); + else + DiffMobj(mobj, diff); + + // already read by the client + WRITEUINT8(save->p, type); } - if (diff & MD_TYPE) - WRITEUINT32(save->p, mobj->type); - if (diff & MD_POS) + // diff is somehow not being sent correctly over the wire. + // client has a diff of 16 instead its intended value + j = 0; + do + SYNC(diff[j]); + while (diff[j++] & 0x80000000); + + if (GETB(MD_SPAWNPOINT)) { - WRITEFIXED(save->p, mobj->x); - WRITEFIXED(save->p, mobj->y); - WRITEANGLE(save->p, mobj->angle); - WRITEANGLE(save->p, mobj->pitch); - WRITEANGLE(save->p, mobj->roll); + if (save->write) + { + size_t z; + + for (z = 0; z < nummapthings; z++) + { + if (&mapthings[z] != mobj->spawnpoint) + continue; + WRITEUINT16(save->p, z); + break; + } + if (mobj->type == MT_HOOPCENTER) + return th; + } + else + { + UINT16 spawnpointnum = READUINT16(save->p); + + if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case + { + P_SpawnHoop(&mapthings[spawnpointnum]); + return NULL; + } + + mobj = P_AllocateMobj(); + + mobj->spawnpoint = &mapthings[spawnpointnum]; + mapthings[spawnpointnum].mobj = mobj; + } } - if (diff & MD_MOM) + else if (!save->write) + mobj = P_AllocateMobj(); + + // declare this as a valid mobj as soon as possible. + mobj->thinker.function.acp1 = thinker; + + // manually link to thinkerlist, since the thinker isn't returned anymore + if (!save->write) + P_AddThinker(type, &mobj->thinker); + + SYNC(mobj->z); // Force this so 3dfloor problems don't arise. + SYNC(mobj->floorz); + SYNC(mobj->ceilingz); + + if (GETB(MD2_FLOORROVER)) { - WRITEFIXED(save->p, mobj->momx); - WRITEFIXED(save->p, mobj->momy); - WRITEFIXED(save->p, mobj->momz); - WRITEFIXED(save->p, mobj->pmomz); + if (save->write) + { + WRITEUINT32(save->p, SaveSector(mobj->floorrover->target)); + WRITEUINT16(save->p, P_GetFFloorID(mobj->floorrover)); + } + else + { + sector_t *sec = LoadSector(READUINT32(save->p)); + UINT16 id = READUINT16(save->p); + mobj->floorrover = P_GetFFloorByID(sec, id); + } } - if (diff & MD_RADIUS) - WRITEFIXED(save->p, mobj->radius); - if (diff & MD_HEIGHT) - WRITEFIXED(save->p, mobj->height); - if (diff & MD_FLAGS) - WRITEUINT32(save->p, mobj->flags); - if (diff & MD_FLAGS2) - WRITEUINT32(save->p, mobj->flags2); - if (diff & MD_HEALTH) - WRITEINT32(save->p, mobj->health); - if (diff & MD_RTIME) - WRITEINT32(save->p, mobj->reactiontime); - if (diff & MD_STATE) - WRITEUINT16(save->p, mobj->state-states); - if (diff & MD_TICS) - WRITEINT32(save->p, mobj->tics); - if (diff & MD_SPRITE) { - WRITEUINT16(save->p, mobj->sprite); - if (mobj->sprite == SPR_PLAY) - WRITEUINT8(save->p, mobj->sprite2); - } - if (diff & MD_FRAME) + + if (GETB(MD2_CEILINGROVER)) { - WRITEUINT32(save->p, mobj->frame); - WRITEUINT16(save->p, mobj->anim_duration); + if (save->write) + { + WRITEUINT32(save->p, SaveSector(mobj->ceilingrover->target)); + WRITEUINT16(save->p, P_GetFFloorID(mobj->ceilingrover)); + } + else + { + sector_t *sec = LoadSector(READUINT32(save->p)); + UINT16 id = READUINT16(save->p); + mobj->ceilingrover = P_GetFFloorByID(sec, id); + } } - if (diff & MD_EFLAGS) - WRITEUINT16(save->p, mobj->eflags); - if (diff & MD_PLAYER) - WRITEUINT8(save->p, mobj->player-players); - if (diff & MD_MOVEDIR) - WRITEANGLE(save->p, mobj->movedir); - if (diff & MD_MOVECOUNT) - WRITEINT32(save->p, mobj->movecount); - if (diff & MD_THRESHOLD) - WRITEINT32(save->p, mobj->threshold); - if (diff & MD_LASTLOOK) - WRITEINT32(save->p, mobj->lastlook); - if (diff & MD_TARGET) - WRITEUINT32(save->p, mobj->target->mobjnum); - if (diff & MD_TRACER) - WRITEUINT32(save->p, mobj->tracer->mobjnum); - if (diff & MD_FRICTION) - WRITEFIXED(save->p, mobj->friction); - if (diff & MD_MOVEFACTOR) - WRITEFIXED(save->p, mobj->movefactor); - if (diff & MD_FUSE) - WRITEINT32(save->p, mobj->fuse); - if (diff & MD_WATERTOP) - WRITEFIXED(save->p, mobj->watertop); - if (diff & MD_WATERBOTTOM) - WRITEFIXED(save->p, mobj->waterbottom); - if (diff & MD_SCALE) - WRITEFIXED(save->p, mobj->scale); - if (diff & MD_DSCALE) - WRITEFIXED(save->p, mobj->destscale); - if (diff2 & MD2_SCALESPEED) - WRITEFIXED(save->p, mobj->scalespeed); - if (diff & MD_ARGS) + + if (GETB(MD_TYPE)) + { + SYNC(mobj->type); + } + else if (!save->write) + { + 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 doomednum %d\n", mobj->spawnpoint->type); + else + CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum NULL\n"); + + I_Error("Netsave corrupted"); + } + + mobj->type = new_type; + } + mobj->info = &mobjinfo[mobj->type]; + if (GETB(MD_POS)) + { + SYNC(mobj->x); + SYNC(mobj->y); + SYNC(mobj->angle); + SYNC(mobj->pitch); + SYNC(mobj->roll); + } + else + { + mobj->x = mobj->old_x = mobj->spawnpoint->x << FRACBITS; + mobj->y = mobj->old_y = mobj->spawnpoint->y << FRACBITS; + mobj->angle = mobj->old_angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); + mobj->pitch = mobj->old_pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT); + mobj->roll = mobj->old_roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT); + } + + SYNCF(MD_MOM, mobj->momx); + SYNCF(MD_MOM, mobj->momy); + SYNCF(MD_MOM, mobj->momz); + SYNCF(MD_MOM, mobj->pmomz); + + SYNCDEF(MD_RADIUS, mobj->radius, mobj->info->radius); + SYNCDEF(MD_HEIGHT, mobj->height, mobj->info->height); + SYNCDEF(MD_FLAGS, mobj->flags, mobj->info->flags); + SYNCF(MD_FLAGS2, mobj->flags2); + SYNCDEF(MD_HEALTH, mobj->health, mobj->info->spawnhealth); + SYNCDEF(MD_RTIME, mobj->reactiontime, mobj->info->reactiontime); + if (GETB(MD_STATE)) + { + if (save->write) + WRITEUINT16(save->p, mobj->state-states); + else + mobj->state = &states[READUINT16(save->p)]; + } + else + mobj->state = &states[mobj->info->spawnstate]; + SYNCF(MD_TICS, mobj->tics); + SYNCDEF(MD_SPRITE, mobj->sprite, mobj->state->sprite); + if (mobj->sprite == SPR_PLAY) + SYNCDEF(MD_SPRITE, mobj->sprite2, mobj->state->frame & FF_FRAMEMASK); + SYNCDEF(MD_FRAME, mobj->frame, mobj->state->frame); + SYNCDEF(MD_FRAME, mobj->anim_duration, (UINT16)mobj->state->var2); + SYNCF(MD_EFLAGS, mobj->eflags); + if (GETB(MD_PLAYER)) + { + UINT8 i; + i = P_SyncUINT8(save, mobj->player-players); + mobj->player = &players[i]; + mobj->player->mo = mobj; + } + SYNCF(MD_MOVEDIR, mobj->movedir); + SYNCF(MD_MOVECOUNT, mobj->movecount); + SYNCF(MD_THRESHOLD, mobj->threshold); + SYNCDEF(MD_LASTLOOK, mobj->lastlook, -1); + SYNCF(MD_TARGET, mobj->target); + SYNCF(MD_TRACER, mobj->tracer); + SYNCDEF(MD_FRICTION, mobj->friction, ORIG_FRICTION); + SYNCDEF(MD_MOVEFACTOR, mobj->movefactor, FRACUNIT); + SYNCF(MD_FUSE, mobj->fuse); + SYNCF(MD_WATERTOP, mobj->watertop); + SYNCF(MD_WATERBOTTOM, mobj->waterbottom); + SYNCDEF(MD_SCALE, mobj->scale, FRACUNIT); + SYNCDEF(MD_DSCALE, mobj->destscale, mobj->scale); + SYNCDEF(MD2_SCALESPEED, mobj->scalespeed, FRACUNIT/12); + if (GETB(MD_ARGS)) { for (j = 0; j < NUM_MAPTHING_ARGS; j++) - WRITEINT32(save->p, mobj->args[j]); + SYNC(mobj->args[j]); } - if (diff & MD_STRINGARGS) + if (GETB(MD_STRINGARGS)) { for (j = 0; j < NUM_MAPTHING_STRINGARGS; j++) { - size_t len, k; - - if (!mobj->stringargs[j]) + size_t len = P_SyncINT32(save, mobj->stringargs[j] ? strlen(mobj->stringargs[j]) : 0); + if (!len) { - WRITEINT32(save->p, 0); + if (!save->write) + { + Z_Free(mobj->stringargs[j]); + mobj->stringargs[j] = NULL; + } continue; } - len = strlen(mobj->stringargs[j]); - WRITEINT32(save->p, len); - for (k = 0; k < len; k++) - WRITECHAR(save->p, mobj->stringargs[j][k]); + if (!save->write) + mobj->stringargs[j] = Z_Realloc(mobj->stringargs[j], len + 1, PU_LEVEL, NULL); + P_SyncMem(save, mobj->stringargs[j], len); + mobj->stringargs[j][len] = '\0'; } } - if (diff2 & MD2_CUSVAL) - WRITEINT32(save->p, mobj->cusval); - if (diff2 & MD2_CVMEM) - WRITEINT32(save->p, mobj->cvmem); - if (diff2 & MD2_SKIN) - WRITEUINT16(save->p, (UINT16)((skin_t *)mobj->skin - skins)); - if (diff2 & MD2_COLOR) - WRITEUINT16(save->p, mobj->color); - if (diff2 & MD2_EXTVAL1) - WRITEINT32(save->p, mobj->extravalue1); - if (diff2 & MD2_EXTVAL2) - WRITEINT32(save->p, mobj->extravalue2); - if (diff2 & MD2_HNEXT) - WRITEUINT32(save->p, mobj->hnext->mobjnum); - if (diff2 & MD2_HPREV) - WRITEUINT32(save->p, mobj->hprev->mobjnum); - if (diff2 & MD2_ITNEXT) - WRITEUINT32(save->p, mobj->itnext->mobjnum); - if (diff2 & MD2_SLOPE) - WRITEUINT16(save->p, mobj->standingslope->id); - if (diff2 & MD2_COLORIZED) - WRITEUINT8(save->p, mobj->colorized); - if (diff2 & MD2_MIRRORED) - WRITEUINT8(save->p, mobj->mirrored); - if (diff2 & MD2_ROLLANGLE) - WRITEANGLE(save->p, mobj->rollangle); - if (diff2 & MD2_SHADOWSCALE) - { - WRITEFIXED(save->p, mobj->shadowscale); - WRITEUINT8(save->p, mobj->whiteshadow); - WRITEUINT8(save->p, mobj->shadowcolor); - } - if (diff2 & MD2_RENDERFLAGS) - { - UINT32 rf = mobj->renderflags; - UINT32 q = rf & RF_DONTDRAW; - if (q != RF_DONTDRAW // visible for more than one local player - && q != (RF_DONTDRAWP1|RF_DONTDRAWP2|RF_DONTDRAWP3) - && q != (RF_DONTDRAWP4|RF_DONTDRAWP1|RF_DONTDRAWP2) - && q != (RF_DONTDRAWP4|RF_DONTDRAWP1|RF_DONTDRAWP3) - && q != (RF_DONTDRAWP4|RF_DONTDRAWP2|RF_DONTDRAWP3)) - rf &= ~q; + SYNCF(MD2_CUSVAL, mobj->cusval); + SYNCF(MD2_CVMEM, mobj->cvmem); + if (GETB(MD2_SKIN)) + { + if (save->write) + WRITEUINT16(save->p, (UINT16)((skin_t *)mobj->skin - skins)); + else + mobj->skin = &skins[READUINT16(save->p)]; + } + SYNCF(MD2_COLOR, mobj->color); + SYNCF(MD2_EXTVAL1, mobj->extravalue1); + SYNCF(MD2_EXTVAL2, mobj->extravalue2); + SYNCF(MD2_HNEXT, mobj->hnext); + SYNCF(MD2_HPREV, mobj->hprev); + SYNCF(MD2_ITNEXT, mobj->itnext); + if (GETB(MD2_SLOPE)) + { + if (save->write) + WRITEUINT16(save->p, mobj->standingslope->id); + else + mobj->standingslope = P_SlopeById(READUINT16(save->p)); + } + SYNCFB(MD2_COLORIZED, mobj->colorized); + SYNCFB(MD2_MIRRORED, mobj->mirrored); + SYNCF(MD2_ROLLANGLE, mobj->rollangle); + SYNCF(MD2_SHADOWSCALE, mobj->shadowscale); + SYNCFB(MD2_SHADOWSCALE, mobj->whiteshadow); + SYNCF(MD2_SHADOWSCALE, mobj->shadowcolor); + if (GETB(MD2_RENDERFLAGS)) + { + if (save->write) + { + UINT32 rf = mobj->renderflags; + UINT32 q = rf & RF_DONTDRAW; - WRITEUINT32(save->p, rf); + if (q != RF_DONTDRAW // visible for more than one local player + && q != (RF_DONTDRAWP1|RF_DONTDRAWP2|RF_DONTDRAWP3) + && q != (RF_DONTDRAWP4|RF_DONTDRAWP1|RF_DONTDRAWP2) + && q != (RF_DONTDRAWP4|RF_DONTDRAWP1|RF_DONTDRAWP3) + && q != (RF_DONTDRAWP4|RF_DONTDRAWP2|RF_DONTDRAWP3)) + rf &= ~q; + + WRITEUINT32(save->p, rf); + } + else + { + mobj->renderflags = READUINT32(save->p); + } } - if (diff2 & MD2_TID) - WRITEINT16(save->p, mobj->tid); - if (diff2 & MD2_SPRITESCALE) + SYNCF(MD2_TID, mobj->tid); + SYNCDEF(MD2_SPRITESCALE, mobj->spritexscale, FRACUNIT); + SYNCDEF(MD2_SPRITESCALE, mobj->spriteyscale, FRACUNIT); + SYNCDEF(MD2_SPRITEOFFSET, mobj->spritexoffset, FRACUNIT); + SYNCDEF(MD2_SPRITEOFFSET, mobj->spriteyoffset, FRACUNIT); + SYNCDEF(MD2_SPRITEOFFSET, mobj->rollingxoffset, 0); + SYNCDEF(MD2_SPRITEOFFSET, mobj->rollingyoffset, 0); + SYNCF(MD2_WORLDOFFSET, mobj->sprxoff); + SYNCF(MD2_WORLDOFFSET, mobj->spryoff); + SYNCF(MD2_WORLDOFFSET, mobj->sprzoff); + + if (GETB(MD2_SPECIAL)) { - WRITEFIXED(save->p, mobj->spritexscale); - WRITEFIXED(save->p, mobj->spriteyscale); - } - if (diff2 & MD2_SPRITEOFFSET) - { - WRITEFIXED(save->p, mobj->spritexoffset); - WRITEFIXED(save->p, mobj->spriteyoffset); - WRITEINT16(save->p, mobj->rollingxoffset); - WRITEINT16(save->p, mobj->rollingyoffset); - } - if (diff2 & MD2_WORLDOFFSET) - { - WRITEFIXED(save->p, mobj->sprxoff); - WRITEFIXED(save->p, mobj->spryoff); - WRITEFIXED(save->p, mobj->sprzoff); - } - if (diff2 & MD2_SPECIAL) - { - WRITEINT16(save->p, mobj->special); + SYNC(mobj->special); for (j = 0; j < NUM_SCRIPT_ARGS; j++) - WRITEINT32(save->p, mobj->script_args[j]); + SYNC(mobj->script_args[j]); for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) { - size_t len, k; - - if (!mobj->script_stringargs[j]) + size_t len = P_SyncINT32(save, mobj->script_stringargs[j] ? strlen(mobj->script_stringargs[j]) : 0); + if (!len) { - WRITEINT32(save->p, 0); + if (!save->write) + { + Z_Free(mobj->script_stringargs[j]); + mobj->script_stringargs[j] = NULL; + } continue; } - len = strlen(mobj->script_stringargs[j]); - WRITEINT32(save->p, len); - for (k = 0; k < len; k++) - WRITECHAR(save->p, mobj->script_stringargs[j][k]); + if (!save->write) + mobj->script_stringargs[j] = Z_Realloc(mobj->script_stringargs[j], len + 1, PU_LEVEL, NULL); + P_SyncMem(save, mobj->script_stringargs[j], len); + mobj->script_stringargs[j][len] = '\0'; } } - if (diff2 & MD2_FLOORSPRITESLOPE) + if (GETB(MD2_FLOORSPRITESLOPE)) { pslope_t *slope = mobj->floorspriteslope; + if (!save->write) + slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj); - WRITEFIXED(save->p, slope->zdelta); - WRITEANGLE(save->p, slope->zangle); - WRITEANGLE(save->p, slope->xydirection); + SYNC(slope->zdelta); + SYNC(slope->zangle); + SYNC(slope->xydirection); - WRITEFIXED(save->p, slope->o.x); - WRITEFIXED(save->p, slope->o.y); - WRITEFIXED(save->p, slope->o.z); + SYNC(slope->o.x); + SYNC(slope->o.y); + SYNC(slope->o.z); - WRITEFIXED(save->p, slope->d.x); - WRITEFIXED(save->p, slope->d.y); + SYNC(slope->d.x); + SYNC(slope->d.y); - WRITEFIXED(save->p, slope->normal.x); - WRITEFIXED(save->p, slope->normal.y); - WRITEFIXED(save->p, slope->normal.z); - + SYNC(slope->normal.x); + SYNC(slope->normal.y); + SYNC(slope->normal.z); + + if (!save->write) + P_UpdateSlopeLightOffset(slope); } - if (diff2 & MD2_LIGHTLEVEL) + SYNCF(MD2_LIGHTLEVEL, mobj->lightlevel); + SYNCDEF(MD2_DISPOFFSET, mobj->dispoffset, mobj->info->dispoffset); + SYNCF(MD2_LASTMOMZ, mobj->lastmomz); + + if (GETB(MD2_TERRAIN)) { - WRITEINT16(save->p, mobj->lightlevel); + if (save->write) + { + WRITEUINT32(save->p, K_GetTerrainHeapIndex(mobj->terrain) + 1); + WRITEUINT32(save->p, SaveMobjnum(mobj->terrainOverlay)); + } + else + { + UINT32 terrain_index = READUINT32(save->p); + if (terrain_index > 0) + mobj->terrain = K_GetTerrainByIndex(terrain_index - 1); + mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save->p); + } } - if (diff2 & MD2_DISPOFFSET) + SYNCF(MD3_GRAVITY, mobj->gravity); + SYNCF(MD3_BAKEDOFFSET, mobj->bakexoff); + SYNCF(MD3_BAKEDOFFSET, mobj->bakeyoff); + SYNCF(MD3_BAKEDOFFSET, mobj->bakezoff); + SYNCF(MD3_BAKEDOFFSET, mobj->bakexpiv); + SYNCF(MD3_BAKEDOFFSET, mobj->bakeypiv); + SYNCF(MD3_BAKEDOFFSET, mobj->bakezpiv); + SYNCF(MD3_EXTVAL3, mobj->extravalue3); + SYNCF(MD3_SHIELDTRACER, mobj->shieldtracer); + + if (!save->write) { - WRITEINT32(save->p, mobj->dispoffset); - } - if (diff2 & MD2_LASTMOMZ) - { - WRITEINT32(save->p, mobj->lastmomz); - } - if (diff2 & MD2_TERRAIN) - { - WRITEUINT32(save->p, K_GetTerrainHeapIndex(mobj->terrain) + 1); - WRITEUINT32(save->p, SaveMobjnum(mobj->terrainOverlay)); - } - if (diff3 & MD3_GRAVITY) - { - WRITEFIXED(save->p, mobj->gravity); - } - if (diff3 & MD3_BAKEDOFFSET) - { - WRITEFIXED(save->p, mobj->bakexoff); - WRITEFIXED(save->p, mobj->bakeyoff); - WRITEFIXED(save->p, mobj->bakezoff); - WRITEFIXED(save->p, mobj->bakexpiv); - WRITEFIXED(save->p, mobj->bakeypiv); - WRITEFIXED(save->p, mobj->bakezpiv); - } - if (diff3 & MD3_EXTVAL3) - { - WRITEINT32(save->p, mobj->extravalue3); - } - if (diff3 & MD3_SHIELDTRACER) - { - WRITEUINT32(save->p, mobj->shieldtracer->mobjnum); + // Reset some non-synch values + mobj->sloperoll = 0; + mobj->slopepitch = 0; + + // link tid set earlier + P_AddThingTID(mobj); + + // set sprev, snext, bprev, bnext, subsector + P_SetThingPosition(mobj); } - WRITEUINT32(save->p, mobj->mobjnum); + SYNC(mobj->mobjnum); + + if (!save->write) + { + if (mobj->player) + { + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight; + else + mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; + } + + if (mobj->type == MT_SKYBOX && mobj->spawnpoint) + { + P_InitSkyboxPoint(mobj, mobj->spawnpoint); + } + + if (GETB(MD2_BOSS3CAP)) + P_SetTarget(&boss3cap, mobj); + + if (GETB(MD2_WAYPOINTCAP)) + P_SetTarget(&waypointcap, mobj); + + if (GETB(MD2_KITEMCAP)) + P_SetTarget(&kitemcap, mobj); + + if (GETB(MD3_MISCCAP)) + P_SetTarget(&misccap, mobj); + + R_AddMobjInterpolator(mobj); + } + + // don't allow the mobj's refcount to be reset by P_AddThinker + // we might've already called P_SetTarget! + return &mobj->thinker; } -static void SaveNoEnemiesThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncNoEnemiesThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const noenemies_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); + noenemies_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + ht->sourceline = SyncLine(save, ht->sourceline); + return &ht->thinker; } -static void SaveBounceCheeseThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncBounceCheeseThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const bouncecheese_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->speed); - WRITEFIXED(save->p, ht->distance); - WRITEFIXED(save->p, ht->floorwasheight); - WRITEFIXED(save->p, ht->ceilingwasheight); - WRITECHAR(save->p, ht->low); + bouncecheese_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sourceline = SyncLine(save, ht->sourceline); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->speed); + SYNC(ht->distance); + SYNC(ht->floorwasheight); + SYNC(ht->ceilingwasheight); + SYNCBOOLEAN(ht->low); + if (!save->write && ht->sector) + ht->sector->ceilingdata = ht; + return &ht->thinker; } -static void SaveContinuousFallThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncContinuousFallThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const continuousfall_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->speed); - WRITEINT32(save->p, ht->direction); - WRITEFIXED(save->p, ht->floorstartheight); - WRITEFIXED(save->p, ht->ceilingstartheight); - WRITEFIXED(save->p, ht->destheight); + continuousfall_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->speed); + SYNC(ht->direction); + SYNC(ht->floorstartheight); + SYNC(ht->ceilingstartheight); + SYNC(ht->destheight); + if (!save->write && ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } -static void SaveMarioBlockThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncMarioBlockThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const mariothink_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->speed); - WRITEINT32(save->p, ht->direction); - WRITEFIXED(save->p, ht->floorstartheight); - WRITEFIXED(save->p, ht->ceilingstartheight); - WRITEINT16(save->p, ht->tag); + mariothink_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->speed); + SYNC(ht->direction); + SYNC(ht->floorstartheight); + SYNC(ht->ceilingstartheight); + SYNC(ht->tag); + if (!save->write && ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } -static void SaveMarioCheckThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncMarioCheckThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const mariocheck_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT32(save->p, SaveSector(ht->sector)); + mariocheck_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sourceline = SyncLine(save, ht->sourceline); + ht->sector = SyncSector(save, ht->sector); + return &ht->thinker; } -static void SaveThwompThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncThwompThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const thwomp_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->crushspeed); - WRITEFIXED(save->p, ht->retractspeed); - WRITEINT32(save->p, ht->direction); - WRITEFIXED(save->p, ht->floorstartheight); - WRITEFIXED(save->p, ht->ceilingstartheight); - WRITEINT32(save->p, ht->delay); - WRITEINT16(save->p, ht->tag); - WRITEUINT16(save->p, ht->sound); - WRITEINT32(save->p, ht->initDelay); + thwomp_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sourceline = SyncLine(save, ht->sourceline); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->crushspeed); + SYNC(ht->retractspeed); + SYNC(ht->direction); + SYNC(ht->floorstartheight); + SYNC(ht->ceilingstartheight); + SYNC(ht->delay); + SYNC(ht->tag); + SYNC(ht->sound); + SYNC(ht->initDelay); + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } -static void SaveFloatThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFloatThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const floatthink_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT16(save->p, ht->tag); + floatthink_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sourceline = SyncLine(save, ht->sourceline); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->tag); + return &ht->thinker; } -static void SaveEachTimeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncEachTimeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const eachtime_t *ht = (const void *)th; + eachtime_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + size_t i; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); + ht->sourceline = SyncLine(save, ht->sourceline); for (i = 0; i < MAXPLAYERS; i++) { - WRITECHAR(save->p, ht->playersInArea[i]); + SYNCBOOLEAN(ht->playersInArea[i]); } - WRITECHAR(save->p, ht->triggerOnExit); + SYNCBOOLEAN(ht->triggerOnExit); + return &ht->thinker; } -static void SaveRaiseThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncRaiseThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const raise_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT16(save->p, ht->tag); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->ceilingbottom); - WRITEFIXED(save->p, ht->ceilingtop); - WRITEFIXED(save->p, ht->basespeed); - WRITEFIXED(save->p, ht->extraspeed); - WRITEUINT8(save->p, ht->shaketimer); - WRITEUINT8(save->p, ht->flags); + raise_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->tag); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->ceilingbottom); + SYNC(ht->ceilingtop); + SYNC(ht->basespeed); + SYNC(ht->extraspeed); + SYNC(ht->shaketimer); + SYNC(ht->flags); + return &ht->thinker; } -static void SaveCeilingThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncCeilingThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const ceiling_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT8(save->p, ht->type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEFIXED(save->p, ht->bottomheight); - WRITEFIXED(save->p, ht->topheight); - WRITEFIXED(save->p, ht->speed); - WRITEFIXED(save->p, ht->delay); - WRITEFIXED(save->p, ht->delaytimer); - WRITEUINT8(save->p, ht->crush); - WRITEINT32(save->p, ht->texture); - WRITEINT32(save->p, ht->direction); - WRITEINT16(save->p, ht->tag); - WRITEFIXED(save->p, ht->sourceline); - WRITEFIXED(save->p, ht->origspeed); - WRITEFIXED(save->p, ht->crushHeight); - WRITEFIXED(save->p, ht->crushSpeed); - WRITEFIXED(save->p, ht->returnHeight); - WRITEFIXED(save->p, ht->returnSpeed); + ceiling_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->type); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->bottomheight); + SYNC(ht->topheight); + SYNC(ht->speed); + SYNC(ht->delay); + SYNC(ht->delaytimer); + SYNC(ht->crush); + SYNC(ht->texture); + SYNC(ht->direction); + SYNC(ht->tag); + SYNC(ht->sourceline); + SYNC(ht->origspeed); + SYNC(ht->crushHeight); + SYNC(ht->crushSpeed); + SYNC(ht->returnHeight); + SYNC(ht->returnSpeed); + if (!save->write && ht->sector) + ht->sector->ceilingdata = ht; + + return &ht->thinker; } -static void SaveFloormoveThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFloormoveThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const floormove_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT8(save->p, ht->type); - WRITEUINT8(save->p, ht->crush); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT32(save->p, ht->direction); - WRITEINT32(save->p, ht->texture); - WRITEFIXED(save->p, ht->floordestheight); - WRITEFIXED(save->p, ht->speed); - WRITEFIXED(save->p, ht->origspeed); - WRITEFIXED(save->p, ht->delay); - WRITEFIXED(save->p, ht->delaytimer); - WRITEINT16(save->p, ht->tag); - WRITEFIXED(save->p, ht->sourceline); - WRITEFIXED(save->p, ht->crushHeight); - WRITEFIXED(save->p, ht->crushSpeed); - WRITEFIXED(save->p, ht->returnHeight); - WRITEFIXED(save->p, ht->returnSpeed); + floormove_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->crush); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->direction); + SYNC(ht->texture); + SYNC(ht->floordestheight); + SYNC(ht->speed); + SYNC(ht->origspeed); + SYNC(ht->delay); + SYNC(ht->delaytimer); + SYNC(ht->tag); + SYNC(ht->sourceline); + SYNC(ht->crushHeight); + SYNC(ht->crushSpeed); + SYNC(ht->returnHeight); + SYNC(ht->returnSpeed); + return &ht->thinker; } -static void SaveLightflashThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncLightflashThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const lightflash_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT32(save->p, ht->maxlight); - WRITEINT32(save->p, ht->minlight); + lightflash_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->maxlight); + SYNC(ht->minlight); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + return &ht->thinker; } -static void SaveStrobeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncStrobeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const strobe_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT32(save->p, ht->count); - WRITEINT16(save->p, ht->minlight); - WRITEINT16(save->p, ht->maxlight); - WRITEINT32(save->p, ht->darktime); - WRITEINT32(save->p, ht->brighttime); + strobe_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->count); + SYNC(ht->minlight); + SYNC(ht->maxlight); + SYNC(ht->darktime); + SYNC(ht->brighttime); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + return &ht->thinker; } -static void SaveGlowThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncGlowThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const glow_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT16(save->p, ht->minlight); - WRITEINT16(save->p, ht->maxlight); - WRITEINT16(save->p, ht->direction); - WRITEINT16(save->p, ht->speed); + glow_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->minlight); + SYNC(ht->maxlight); + SYNC(ht->direction); + SYNC(ht->speed); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + return &ht->thinker; } -static inline void SaveFireflickerThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFireflickerThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const fireflicker_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT32(save->p, ht->count); - WRITEINT32(save->p, ht->resetcount); - WRITEINT16(save->p, ht->maxlight); - WRITEINT16(save->p, ht->minlight); + fireflicker_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->count); + SYNC(ht->resetcount); + SYNC(ht->maxlight); + SYNC(ht->minlight); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + return &ht->thinker; } -static void SaveElevatorThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncElevatorThinker(savebuffer_t *save, actionf_p1 thinker, boolean setplanedata, thinker_t *th, UINT8 type) { - const elevator_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT8(save->p, ht->type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEUINT32(save->p, SaveSector(ht->actionsector)); - WRITEINT32(save->p, ht->direction); - WRITEFIXED(save->p, ht->floordestheight); - WRITEFIXED(save->p, ht->ceilingdestheight); - WRITEFIXED(save->p, ht->speed); - WRITEFIXED(save->p, ht->origspeed); - WRITEFIXED(save->p, ht->low); - WRITEFIXED(save->p, ht->high); - WRITEFIXED(save->p, ht->distance); - WRITEFIXED(save->p, ht->delay); - WRITEFIXED(save->p, ht->delaytimer); - WRITEFIXED(save->p, ht->floorwasheight); - WRITEFIXED(save->p, ht->ceilingwasheight); + elevator_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->type); + ht->sector = SyncSector(save, ht->sector); + ht->actionsector = SyncSector(save, ht->actionsector); + SYNC(ht->direction); + SYNC(ht->floordestheight); + SYNC(ht->ceilingdestheight); + SYNC(ht->speed); + SYNC(ht->origspeed); + SYNC(ht->low); + SYNC(ht->high); + SYNC(ht->distance); + SYNC(ht->delay); + SYNC(ht->delaytimer); + SYNC(ht->floorwasheight); + SYNC(ht->ceilingwasheight); + + if (!save->write && ht->sector && setplanedata) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + return &ht->thinker; } -static void SaveCrumbleThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncCrumbleThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const crumble_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEUINT32(save->p, SaveSector(ht->actionsector)); - WRITEUINT32(save->p, SavePlayer(ht->player)); // was dummy - WRITEINT32(save->p, ht->direction); - WRITEINT32(save->p, ht->origalpha); - WRITEINT32(save->p, ht->timer); - WRITEFIXED(save->p, ht->speed); - WRITEFIXED(save->p, ht->floorwasheight); - WRITEFIXED(save->p, ht->ceilingwasheight); - WRITEUINT8(save->p, ht->flags); + crumble_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sourceline = SyncLine(save, ht->sourceline); + ht->sector = SyncSector(save, ht->sector); + ht->actionsector = SyncSector(save, ht->actionsector); + ht->player = LoadPlayer(P_SyncUINT32(save, SavePlayer(ht->player))); // was dummy + SYNC(ht->direction); + SYNC(ht->origalpha); + SYNC(ht->timer); + SYNC(ht->speed); + SYNC(ht->floorwasheight); + SYNC(ht->ceilingwasheight); + SYNC(ht->flags); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + if (!save->write && ht->actionsector) + ht->actionsector->lightingdata = ht; + return &ht->thinker; } -static inline void SaveScrollThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncScrollThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const scroll_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEFIXED(save->p, ht->dx); - WRITEFIXED(save->p, ht->dy); - WRITEINT32(save->p, ht->affectee); - WRITEINT32(save->p, ht->control); - WRITEFIXED(save->p, ht->last_height); - WRITEFIXED(save->p, ht->vdx); - WRITEFIXED(save->p, ht->vdy); - WRITEINT32(save->p, ht->accel); - WRITEINT32(save->p, ht->exclusive); - WRITEUINT8(save->p, ht->type); + scroll_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->dx); + SYNC(ht->dy); + SYNC(ht->affectee); + SYNC(ht->control); + SYNC(ht->last_height); + SYNC(ht->vdx); + SYNC(ht->vdy); + SYNC(ht->accel); + SYNC(ht->exclusive); + SYNC(ht->type); + return &ht->thinker; } -static inline void SaveFrictionThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFrictionThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const friction_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->friction); - WRITEINT32(save->p, ht->movefactor); - WRITEINT32(save->p, ht->affectee); - WRITEINT32(save->p, ht->referrer); - WRITEUINT8(save->p, ht->roverfriction); + friction_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->friction); + SYNC(ht->movefactor); + SYNC(ht->affectee); + SYNC(ht->referrer); + SYNC(ht->roverfriction); + return &ht->thinker; } -static inline void SavePusherThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPusherThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const pusher_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT8(save->p, ht->type); - WRITEFIXED(save->p, ht->x_mag); - WRITEFIXED(save->p, ht->y_mag); - WRITEFIXED(save->p, ht->z_mag); - WRITEINT32(save->p, ht->affectee); - WRITEUINT8(save->p, ht->roverpusher); - WRITEINT32(save->p, ht->referrer); - WRITEINT32(save->p, ht->exclusive); - WRITEINT32(save->p, ht->slider); + pusher_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->type); + SYNC(ht->x_mag); + SYNC(ht->y_mag); + SYNC(ht->z_mag); + SYNC(ht->affectee); + SYNC(ht->roverpusher); + SYNC(ht->referrer); + SYNC(ht->exclusive); + SYNC(ht->slider); + return &ht->thinker; } -static void SaveLaserThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncLaserThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const laserthink_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT16(save->p, ht->tag); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEUINT8(save->p, ht->nobosses); + laserthink_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->tag); + ht->sourceline = SyncLine(save, ht->sourceline); + SYNC(ht->nobosses); + return &ht->thinker; } -static void SaveLightlevelThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncLightlevelThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const lightlevel_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT16(save->p, ht->sourcelevel); - WRITEINT16(save->p, ht->destlevel); - WRITEFIXED(save->p, ht->fixedcurlevel); - WRITEFIXED(save->p, ht->fixedpertic); - WRITEINT32(save->p, ht->timer); + lightlevel_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->sourcelevel); + SYNC(ht->destlevel); + SYNC(ht->fixedcurlevel); + SYNC(ht->fixedpertic); + SYNC(ht->timer); + if (!save->write && ht->sector) + ht->sector->lightingdata = ht; + return &ht->thinker; } -static void SaveExecutorThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncExecutorThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const executor_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveLine(ht->line)); - WRITEUINT32(save->p, SaveMobjnum(ht->caller)); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEINT32(save->p, ht->timer); + executor_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->line = SyncLine(save, ht->line); + ht->caller = SyncMobj(save, ht->caller); + ht->sector = SyncSector(save, ht->sector); + SYNC(ht->timer); + return &ht->thinker; } -static void SaveDisappearThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncDisappearThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const disappear_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, ht->appeartime); - WRITEUINT32(save->p, ht->disappeartime); - WRITEUINT32(save->p, ht->offset); - WRITEUINT32(save->p, ht->timer); - WRITEINT32(save->p, ht->affectee); - WRITEINT32(save->p, ht->sourceline); - WRITEINT32(save->p, ht->exists); + disappear_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->appeartime); + SYNC(ht->disappeartime); + SYNC(ht->offset); + SYNC(ht->timer); + SYNC(ht->affectee); + SYNC(ht->sourceline); + SYNC(ht->exists); + return &ht->thinker; } -static void SaveFadeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFadeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const fade_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT32(save->p, ht->sectornum); - WRITEUINT32(save->p, ht->ffloornum); - WRITEINT32(save->p, ht->alpha); - WRITEINT16(save->p, ht->sourcevalue); - WRITEINT16(save->p, ht->destvalue); - WRITEINT16(save->p, ht->destlightlevel); - WRITEINT16(save->p, ht->speed); - WRITEUINT8(save->p, (UINT8)ht->ticbased); - WRITEINT32(save->p, ht->timer); - WRITEUINT8(save->p, ht->doexists); - WRITEUINT8(save->p, ht->dotranslucent); - WRITEUINT8(save->p, ht->dolighting); - WRITEUINT8(save->p, ht->docolormap); - WRITEUINT8(save->p, ht->docollision); - WRITEUINT8(save->p, ht->doghostfade); - WRITEUINT8(save->p, ht->exactalpha); + fade_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->dest_exc = GetNetColormapFromList(P_SyncUINT32(save, CheckAddNetColormapToList(ht->dest_exc))); + SYNC(ht->sectornum); + SYNC(ht->ffloornum); + SYNC(ht->alpha); + SYNC(ht->sourcevalue); + SYNC(ht->destvalue); + SYNC(ht->destlightlevel); + SYNC(ht->speed); + SYNCBOOLEAN(ht->ticbased); + SYNC(ht->timer); + SYNC(ht->doexists); + SYNC(ht->dotranslucent); + SYNC(ht->dolighting); + SYNC(ht->docolormap); + SYNCBOOLEAN(ht->docollision); + SYNCBOOLEAN(ht->doghostfade); + SYNC(ht->exactalpha); + + if (!save->write) + { + sector_t *ss = LoadSector(ht->sectornum); + if (ss) + { + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (j == ht->ffloornum) + { + ht->rover = rover; + rover->fadingdata = ht; + break; + } + j++; + } + } + } + return &ht->thinker; } -static void SaveFadeColormapThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncFadeColormapThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const fadecolormap_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSector(ht->sector)); - WRITEUINT32(save->p, CheckAddNetColormapToList(ht->source_exc)); - WRITEUINT32(save->p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT8(save->p, (UINT8)ht->ticbased); - WRITEINT32(save->p, ht->duration); - WRITEINT32(save->p, ht->timer); + fadecolormap_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + ht->sector = SyncSector(save, ht->sector); + ht->source_exc = GetNetColormapFromList(P_SyncUINT32(save, CheckAddNetColormapToList(ht->source_exc))); + ht->dest_exc = GetNetColormapFromList(P_SyncUINT32(save, CheckAddNetColormapToList(ht->dest_exc))); + SYNCBOOLEAN(ht->ticbased); + SYNC(ht->duration); + SYNC(ht->timer); + if (ht->sector) + ht->sector->fadecolormapdata = ht; + return &ht->thinker; } -static void SavePlaneDisplaceThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPlaneDisplaceThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const planedisplace_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->affectee); - WRITEINT32(save->p, ht->control); - WRITEFIXED(save->p, ht->last_height); - WRITEFIXED(save->p, ht->speed); - WRITEUINT8(save->p, ht->type); + planedisplace_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->affectee); + SYNC(ht->control); + SYNC(ht->last_height); + SYNC(ht->speed); + SYNC(ht->type); + return &ht->thinker; } -static inline void SaveDynamicLineSlopeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncDynamicLineSlopeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const dynlineplanethink_t* ht = (const void*)th; + dynlineplanethink_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } - WRITEUINT8(save->p, type); - WRITEUINT8(save->p, ht->type); - WRITEUINT32(save->p, SaveSlope(ht->slope)); - WRITEUINT32(save->p, SaveLine(ht->sourceline)); - WRITEFIXED(save->p, ht->extent); + SYNC(ht->type); + ht->slope = SyncSlope(save, ht->slope); + ht->sourceline = SyncLine(save, ht->sourceline); + SYNC(ht->extent); + return &ht->thinker; } -static inline void SaveDynamicVertexSlopeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncDynamicVertexSlopeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { size_t i; - const dynvertexplanethink_t* ht = (const void*)th; + dynvertexplanethink_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } - WRITEUINT8(save->p, type); - WRITEUINT32(save->p, SaveSlope(ht->slope)); + ht->slope = SyncSlope(save, ht->slope); for (i = 0; i < 3; i++) - WRITEUINT32(save->p, SaveSector(ht->secs[i])); - WRITEMEM(save->p, ht->vex, sizeof(ht->vex)); - WRITEMEM(save->p, ht->origsecheights, sizeof(ht->origsecheights)); - WRITEMEM(save->p, ht->origvecheights, sizeof(ht->origvecheights)); - WRITEUINT8(save->p, ht->relative); + ht->secs[i] = SyncSector(save, ht->secs[i]); + P_SyncMem(save, ht->vex, sizeof(ht->vex)); + P_SyncMem(save, ht->origsecheights, sizeof(ht->origsecheights)); + P_SyncMem(save, ht->origvecheights, sizeof(ht->origvecheights)); + SYNC(ht->relative); + return &ht->thinker; } -static inline void SavePolyrotatetThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polyrotate_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->speed); - WRITEINT32(save->p, ht->distance); - WRITEUINT8(save->p, ht->turnobjs); + polyrotate_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->speed); + SYNC(ht->distance); + SYNC(ht->turnobjs); + return &ht->thinker; } -static void SavePolymoveThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolymoveThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polymove_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->speed); - WRITEFIXED(save->p, ht->momx); - WRITEFIXED(save->p, ht->momy); - WRITEINT32(save->p, ht->distance); - WRITEANGLE(save->p, ht->angle); + polymove_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->speed); + SYNC(ht->momx); + SYNC(ht->momy); + SYNC(ht->distance); + SYNC(ht->angle); + return &ht->thinker; } -static void SavePolywaypointThinker(savebuffer_t *save, const thinker_t *th, UINT8 type) +static thinker_t *SyncPolywaypointThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polywaypoint_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->speed); - WRITEINT32(save->p, ht->sequence); - WRITEINT32(save->p, ht->pointnum); - WRITEINT32(save->p, ht->direction); - WRITEUINT8(save->p, ht->returnbehavior); - WRITEUINT8(save->p, ht->continuous); - WRITEUINT8(save->p, ht->stophere); + polywaypoint_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->speed); + SYNC(ht->sequence); + SYNC(ht->pointnum); + SYNC(ht->direction); + SYNC(ht->returnbehavior); + SYNC(ht->continuous); + SYNC(ht->stophere); + return &ht->thinker; } -static void SavePolyslidedoorThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolyslidedoorThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polyslidedoor_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->delay); - WRITEINT32(save->p, ht->delayCount); - WRITEINT32(save->p, ht->initSpeed); - WRITEINT32(save->p, ht->speed); - WRITEINT32(save->p, ht->initDistance); - WRITEINT32(save->p, ht->distance); - WRITEUINT32(save->p, ht->initAngle); - WRITEUINT32(save->p, ht->angle); - WRITEUINT32(save->p, ht->revAngle); - WRITEFIXED(save->p, ht->momx); - WRITEFIXED(save->p, ht->momy); - WRITEUINT8(save->p, ht->closing); + polyslidedoor_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->delay); + SYNC(ht->delayCount); + SYNC(ht->initSpeed); + SYNC(ht->speed); + SYNC(ht->initDistance); + SYNC(ht->distance); + SYNC(ht->initAngle); + SYNC(ht->angle); + SYNC(ht->revAngle); + SYNC(ht->momx); + SYNC(ht->momy); + SYNC(ht->closing); + return &ht->thinker; } -static void SavePolyswingdoorThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolyswingdoorThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polyswingdoor_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->delay); - WRITEINT32(save->p, ht->delayCount); - WRITEINT32(save->p, ht->initSpeed); - WRITEINT32(save->p, ht->speed); - WRITEINT32(save->p, ht->initDistance); - WRITEINT32(save->p, ht->distance); - WRITEUINT8(save->p, ht->closing); + polyswingdoor_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->delay); + SYNC(ht->delayCount); + SYNC(ht->initSpeed); + SYNC(ht->speed); + SYNC(ht->initDistance); + SYNC(ht->distance); + SYNC(ht->closing); + return &ht->thinker; } -static void SavePolydisplaceThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polydisplace_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEUINT32(save->p, SaveSector(ht->controlSector)); - WRITEFIXED(save->p, ht->dx); - WRITEFIXED(save->p, ht->dy); - WRITEFIXED(save->p, ht->oldHeights); + polydisplace_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + ht->controlSector = SyncSector(save, ht->controlSector); + SYNC(ht->dx); + SYNC(ht->dy); + SYNC(ht->oldHeights); + return &ht->thinker; } -static void SavePolyrotdisplaceThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolyrotdisplaceThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polyrotdisplace_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEUINT32(save->p, SaveSector(ht->controlSector)); - WRITEFIXED(save->p, ht->rotscale); - WRITEUINT8(save->p, ht->turnobjs); - WRITEFIXED(save->p, ht->oldHeights); + polyrotdisplace_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + ht->controlSector = SyncSector(save, ht->controlSector); + SYNC(ht->rotscale); + SYNC( ht->turnobjs); + SYNC(ht->oldHeights); + return &ht->thinker; } -static void SavePolyfadeThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static thinker_t *SyncPolyfadeThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { - const polyfade_t *ht = (const void *)th; - WRITEUINT8(save->p, type); - WRITEINT32(save->p, ht->polyObjNum); - WRITEINT32(save->p, ht->sourcevalue); - WRITEINT32(save->p, ht->destvalue); - WRITEUINT8(save->p, (UINT8)ht->docollision); - WRITEUINT8(save->p, (UINT8)ht->doghostfade); - WRITEUINT8(save->p, (UINT8)ht->ticbased); - WRITEINT32(save->p, ht->duration); - WRITEINT32(save->p, ht->timer); + polyfade_t *ht = (void *)th; + if (save->write) + { + WRITEUINT8(save->p, type); + } + else + { + ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + } + + SYNC(ht->polyObjNum); + SYNC(ht->sourcevalue); + SYNC(ht->destvalue); + SYNCBOOLEAN(ht->docollision); + SYNCBOOLEAN(ht->doghostfade); + SYNCBOOLEAN(ht->ticbased); + SYNC(ht->duration); + SYNC(ht->timer); + return &ht->thinker; } -static void P_NetArchiveThinkers(savebuffer_t *save) +static void P_NetSyncThinkers(savebuffer_t *save) { TracyCZone(__zone, true); - const thinker_t *th; + thinker_t *currentthinker; + thinker_t *next; + UINT8 tclass; + UINT8 restoreNum = false; UINT32 i; + UINT32 numloaded = 0; - WRITEUINT32(save->p, ARCHIVEBLOCK_THINKERS); + if (P_SyncUINT32(save, ARCHIVEBLOCK_THINKERS) != ARCHIVEBLOCK_THINKERS) + I_Error("Bad $$$.sav at archive block Thinkers"); + + if (!save->write) + { + // 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++) + { + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = next) + { + next = currentthinker->next; + + currentthinker->references = 0; // Heinous but this is the only place the assertion in P_UnlinkThinkers is wrong + + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker) + P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it + else + { + (next->prev = currentthinker->prev)->next = next; + R_DestroyLevelInterpolators(currentthinker); + Z_Free(currentthinker); + } + } + } + + // we don't want the removed mobjs to come back + P_InitThinkers(); + + // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity + for (i = 0; i < numsectors; i++) + { + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL; + } + } for (i = 0; i < NUM_THINKERLISTS; i++) { - UINT32 numsaved = 0; - // save off the current thinkers - for (th = thlist[i].next; th != &thlist[i]; th = th->next) + thinker_t* th = &thlist[i]; + for (;;) { - if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) - numsaved++; + actionf_p1 acp; + if (save->write) + { + th = th->next; + if (th == &thlist[i]) + { + WRITEUINT8(save->p, tc_end); + break; + } + acp = th->function.acp1; + } + else + { + th = NULL; + tclass = READUINT8(save->p); // NOTE: this is normally written within the sync functions + if (tclass == tc_end) + break; + acp = actionspecials[tclass]; + } - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + numloaded++; + if (acp == (actionf_p1)P_MobjThinker) { - SaveMobjThinker(save, th, tc_mobj); - continue; + th = SyncMobjThinker(save, (actionf_p1)P_MobjThinker, th, tc_mobj); } - #ifdef PARANOIA - else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); - #endif - else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) +#ifdef PARANOIA + else if (acp == (actionf_p1)P_NullPrecipThinker); +#endif + else if (acp == (actionf_p1)T_MoveCeiling) { - SaveCeilingThinker(save, th, tc_ceiling); - continue; + th = SyncCeilingThinker(save, (actionf_p1)T_MoveCeiling, th, tc_ceiling); } - else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) + else if (acp == (actionf_p1)T_CrushCeiling) { - SaveCeilingThinker(save, th, tc_crushceiling); - continue; + th = SyncCeilingThinker(save, (actionf_p1)T_CrushCeiling, th, tc_crushceiling); } - else if (th->function.acp1 == (actionf_p1)T_MoveFloor) + else if (acp == (actionf_p1)T_MoveFloor) { - SaveFloormoveThinker(save, th, tc_floor); - continue; + th = SyncFloormoveThinker(save, (actionf_p1)T_MoveFloor, th, tc_floor); } - else if (th->function.acp1 == (actionf_p1)T_LightningFlash) + else if (acp == (actionf_p1)T_LightningFlash) { - SaveLightflashThinker(save, th, tc_flash); - continue; + th = SyncLightflashThinker(save, (actionf_p1)T_LightningFlash, th, tc_flash); } - else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) + else if (acp == (actionf_p1)T_StrobeFlash) { - SaveStrobeThinker(save, th, tc_strobe); - continue; + th = SyncStrobeThinker(save, (actionf_p1)T_StrobeFlash, th, tc_strobe); } - else if (th->function.acp1 == (actionf_p1)T_Glow) + else if (acp == (actionf_p1)T_Glow) { - SaveGlowThinker(save, th, tc_glow); - continue; + th = SyncGlowThinker(save, (actionf_p1)T_Glow, th, tc_glow); } - else if (th->function.acp1 == (actionf_p1)T_FireFlicker) + else if (acp == (actionf_p1)T_FireFlicker) { - SaveFireflickerThinker(save, th, tc_fireflicker); - continue; + th = SyncFireflickerThinker(save, (actionf_p1)T_FireFlicker, th, tc_fireflicker); } - else if (th->function.acp1 == (actionf_p1)T_MoveElevator) + else if (acp == (actionf_p1)T_MoveElevator) { - SaveElevatorThinker(save, th, tc_elevator); - continue; + th = SyncElevatorThinker(save, (actionf_p1)T_MoveElevator, true, th, tc_elevator); } - else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) + else if (acp == (actionf_p1)T_ContinuousFalling) { - SaveContinuousFallThinker(save, th, tc_continuousfalling); - continue; + th = SyncContinuousFallThinker(save, (actionf_p1)T_ContinuousFalling, th, tc_continuousfalling); } - else if (th->function.acp1 == (actionf_p1)T_ThwompSector) + else if (acp == (actionf_p1)T_ThwompSector) { - SaveThwompThinker(save, th, tc_thwomp); - continue; + th = SyncThwompThinker(save, (actionf_p1)T_ThwompSector, th, tc_thwomp); } - else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) + else if (acp == (actionf_p1)T_NoEnemiesSector) { - SaveNoEnemiesThinker(save, th, tc_noenemies); - continue; + th = SyncNoEnemiesThinker(save, (actionf_p1)T_NoEnemiesSector, th, tc_noenemies); } - else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) + else if (acp == (actionf_p1)T_EachTimeThinker) { - SaveEachTimeThinker(save, th, tc_eachtime); - continue; + th = SyncEachTimeThinker(save, (actionf_p1)T_EachTimeThinker, th, tc_eachtime); } - else if (th->function.acp1 == (actionf_p1)T_RaiseSector) + else if (acp == (actionf_p1)T_RaiseSector) { - SaveRaiseThinker(save, th, tc_raisesector); - continue; + th = SyncRaiseThinker(save, (actionf_p1)T_RaiseSector, th, tc_raisesector); } - else if (th->function.acp1 == (actionf_p1)T_CameraScanner) + else if (acp == (actionf_p1)T_CameraScanner) { - SaveElevatorThinker(save, th, tc_camerascanner); - continue; + th = SyncElevatorThinker(save, (actionf_p1)T_CameraScanner, false, th, tc_camerascanner); } - else if (th->function.acp1 == (actionf_p1)T_Scroll) + else if (acp == (actionf_p1)T_Scroll) { - SaveScrollThinker(save, th, tc_scroll); - continue; + th = SyncScrollThinker(save, (actionf_p1)T_Scroll, th, tc_scroll); } - else if (th->function.acp1 == (actionf_p1)T_Friction) + else if (acp == (actionf_p1)T_Friction) { - SaveFrictionThinker(save, th, tc_friction); - continue; + th = SyncFrictionThinker(save, (actionf_p1)T_Friction, th, tc_friction); } - else if (th->function.acp1 == (actionf_p1)T_Pusher) + else if (acp == (actionf_p1)T_Pusher) { - SavePusherThinker(save, th, tc_pusher); - continue; + th = SyncPusherThinker(save, (actionf_p1)T_Pusher, th, tc_pusher); } - else if (th->function.acp1 == (actionf_p1)T_BounceCheese) + else if (acp == (actionf_p1)T_BounceCheese) { - SaveBounceCheeseThinker(save, th, tc_bouncecheese); - continue; + th = SyncBounceCheeseThinker(save, (actionf_p1)T_BounceCheese, th, tc_bouncecheese); } - else if (th->function.acp1 == (actionf_p1)T_StartCrumble) + else if (acp == (actionf_p1)T_StartCrumble) { - SaveCrumbleThinker(save, th, tc_startcrumble); - continue; + th = SyncCrumbleThinker(save, (actionf_p1)T_StartCrumble, th, tc_startcrumble); } - else if (th->function.acp1 == (actionf_p1)T_MarioBlock) + else if (acp == (actionf_p1)T_MarioBlock) { - SaveMarioBlockThinker(save, th, tc_marioblock); - continue; + th = SyncMarioBlockThinker(save, (actionf_p1)T_MarioBlock, th, tc_marioblock); } - else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) + else if (acp == (actionf_p1)T_MarioBlockChecker) { - SaveMarioCheckThinker(save, th, tc_marioblockchecker); - continue; + th = SyncMarioCheckThinker(save, (actionf_p1)T_MarioBlockChecker, th, tc_marioblockchecker); } - else if (th->function.acp1 == (actionf_p1)T_FloatSector) + else if (acp == (actionf_p1)T_FloatSector) { - SaveFloatThinker(save, th, tc_floatsector); - continue; + th = SyncFloatThinker(save, (actionf_p1)T_FloatSector, th, tc_floatsector); } - else if (th->function.acp1 == (actionf_p1)T_LaserFlash) + else if (acp == (actionf_p1)T_LaserFlash) { - SaveLaserThinker(save, th, tc_laserflash); - continue; + th = SyncLaserThinker(save, (actionf_p1)T_LaserFlash, th, tc_laserflash); } - else if (th->function.acp1 == (actionf_p1)T_LightFade) + else if (acp == (actionf_p1)T_LightFade) { - SaveLightlevelThinker(save, th, tc_lightfade); - continue; + th = SyncLightlevelThinker(save, (actionf_p1)T_LightFade, th, tc_lightfade); } - else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) + else if (acp == (actionf_p1)T_ExecutorDelay) { - SaveExecutorThinker(save, th, tc_executor); - continue; + th = SyncExecutorThinker(save, (actionf_p1)T_ExecutorDelay, th, tc_executor); + restoreNum = true; } - else if (th->function.acp1 == (actionf_p1)T_Disappear) + else if (acp == (actionf_p1)T_Disappear) { - SaveDisappearThinker(save, th, tc_disappear); - continue; + th = SyncDisappearThinker(save, (actionf_p1)T_Disappear, th, tc_disappear); } - else if (th->function.acp1 == (actionf_p1)T_Fade) + else if (acp == (actionf_p1)T_Fade) { - SaveFadeThinker(save, th, tc_fade); - continue; + th = SyncFadeThinker(save, (actionf_p1)T_Fade, th, tc_fade); } - else if (th->function.acp1 == (actionf_p1)T_FadeColormap) + else if (acp == (actionf_p1)T_FadeColormap) { - SaveFadeColormapThinker(save, th, tc_fadecolormap); - continue; + th = SyncFadeColormapThinker(save, (actionf_p1)T_FadeColormap, th, tc_fadecolormap); } - else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) + else if (acp == (actionf_p1)T_PlaneDisplace) { - SavePlaneDisplaceThinker(save, th, tc_planedisplace); - continue; + th = SyncPlaneDisplaceThinker(save, (actionf_p1)T_PlaneDisplace, th, tc_planedisplace); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) + else if (acp == (actionf_p1)T_PolyObjRotate) { - SavePolyrotatetThinker(save, th, tc_polyrotate); - continue; + th = SyncPolyrotatetThinker(save, (actionf_p1)T_PolyObjRotate, th, tc_polyrotate); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) + else if (acp == (actionf_p1)T_PolyObjMove) { - SavePolymoveThinker(save, th, tc_polymove); - continue; + th = SyncPolymoveThinker(save, (actionf_p1)T_PolyObjFlag, th, tc_polyflag); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) + else if (acp == (actionf_p1)T_PolyObjWaypoint) { - SavePolywaypointThinker(save, th, tc_polywaypoint); - continue; + th = SyncPolywaypointThinker(save, (actionf_p1)T_PolyObjWaypoint, th, tc_polywaypoint); } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) + else if (acp == (actionf_p1)T_PolyDoorSlide) { - SavePolyslidedoorThinker(save, th, tc_polyslidedoor); - continue; + th = SyncPolyslidedoorThinker(save, (actionf_p1)T_PolyDoorSlide, th, tc_polyslidedoor); } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) + else if (acp == (actionf_p1)T_PolyDoorSwing) { - SavePolyswingdoorThinker(save, th, tc_polyswingdoor); - continue; + th = SyncPolyswingdoorThinker(save, (actionf_p1)T_PolyDoorSwing, th, tc_polyswingdoor); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) + else if (acp == (actionf_p1)T_PolyObjFlag) { - SavePolymoveThinker(save, th, tc_polyflag); - continue; + th = SyncPolymoveThinker(save, (actionf_p1)T_PolyObjFlag, th, tc_polyflag); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) + else if (acp == (actionf_p1)T_PolyObjDisplace) { - SavePolydisplaceThinker(save, th, tc_polydisplace); - continue; + th = SyncPolydisplaceThinker(save, (actionf_p1)T_PolyObjDisplace, th, tc_polydisplace); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) + else if (acp == (actionf_p1)T_PolyObjRotDisplace) { - SavePolyrotdisplaceThinker(save, th, tc_polyrotdisplace); - continue; + th = SyncPolyrotdisplaceThinker(save, (actionf_p1)T_PolyObjRotDisplace, th, tc_polyrotdisplace); } - else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) + else if (acp == (actionf_p1)T_PolyObjFade) { - SavePolyfadeThinker(save, th, tc_polyfade); - continue; + th = SyncPolyfadeThinker(save, (actionf_p1)T_PolyObjFade, th, tc_polyfade); } - else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) + else if (acp == (actionf_p1)T_DynamicSlopeLine) { - SaveDynamicLineSlopeThinker(save, th, tc_dynslopeline); - continue; + th = SyncDynamicLineSlopeThinker(save, (actionf_p1)T_DynamicSlopeLine, th, tc_dynslopeline); } - else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) + else if (acp == (actionf_p1)T_DynamicSlopeVert) { - SaveDynamicVertexSlopeThinker(save, th, tc_dynslopevert); - continue; + th = SyncDynamicVertexSlopeThinker(save, (actionf_p1)T_DynamicSlopeVert, th, tc_dynslopevert); } #ifdef PARANOIA else I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection #endif + if (!save->write && th && tclass != tc_mobj) + P_AddThinker(i, th); } - CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); - - WRITEUINT8(save->p, tc_end); + CONS_Debug(DBG_NETPLAY, "%u thinkers synchronized in list %d\n", numloaded, i); } + + if (!save->write) + { + // Set each skyboxmo to the first skybox (or NULL) + skyboxmo[0] = skyboxviewpnts[0]; + skyboxmo[1] = skyboxcenterpnts[0]; + + if (restoreNum) + { + executor_t *delay = NULL; + UINT32 mobjnum; + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) + { + if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) + continue; + delay = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)delay->caller)) + continue; + delay->caller = P_FindNewPosition(mobjnum); + } + } + } + TracyCZoneEnd(__zone); } @@ -3133,24 +3779,6 @@ static inline mobj_t *LoadMobj(UINT32 mobjnum) return (mobj_t *)(size_t)mobjnum; } -static sector_t *LoadSector(UINT32 sector) -{ - if (sector >= numsectors) return NULL; - return §ors[sector]; -} - -static line_t *LoadLine(UINT32 line) -{ - if (line >= numlines) return NULL; - return &lines[line]; -} - -static inline player_t *LoadPlayer(UINT32 player) -{ - if (player >= MAXPLAYERS) return NULL; - return &players[player]; -} - static inline pslope_t *LoadSlope(UINT32 slopeid) { pslope_t *p = slopelist; @@ -3163,1334 +3791,6 @@ 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 ] = i; - } - } -} - -static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 tclass) -{ - mobj_t *mobj; - UINT32 diff; - UINT32 diff2; - UINT32 diff3; - INT32 i; - fixed_t z, floorz, ceilingz; - ffloor_t *floorrover = NULL, *ceilingrover = NULL; - size_t j; - - diff = READUINT32(save->p); - if (diff & MD_MORE) - diff2 = READUINT32(save->p); - else - diff2 = 0; - - if (diff2 & MD2_MORE) - diff3 = READUINT32(save->p); - else - diff3 = 0; - - z = READFIXED(save->p); // Force this so 3dfloor problems don't arise. - floorz = READFIXED(save->p); - ceilingz = READFIXED(save->p); - - if (diff2 & MD2_FLOORROVER) - { - sector_t *sec = LoadSector(READUINT32(save->p)); - UINT16 id = READUINT16(save->p); - floorrover = P_GetFFloorByID(sec, id); - } - - if (diff2 & MD2_CEILINGROVER) - { - sector_t *sec = LoadSector(READUINT32(save->p)); - UINT16 id = READUINT16(save->p); - ceilingrover = P_GetFFloorByID(sec, id); - } - - if (diff & MD_SPAWNPOINT) - { - UINT16 spawnpointnum = READUINT16(save->p); - - if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case - { - P_SpawnHoop(&mapthings[spawnpointnum]); - return NULL; - } - - mobj = P_AllocateMobj(); - - mobj->spawnpoint = &mapthings[spawnpointnum]; - mapthings[spawnpointnum].mobj = mobj; - } - else - mobj = P_AllocateMobj(); - - // declare this as a valid mobj as soon as possible. - mobj->thinker.function.acp1 = thinker; - - // manually link to thinkerlist, since the thinker isn't returned anymore - P_AddThinker(tclass, &mobj->thinker); - - mobj->z = z; - mobj->floorz = floorz; - mobj->ceilingz = ceilingz; - mobj->floorrover = floorrover; - mobj->ceilingrover = ceilingrover; - - if (diff & MD_TYPE) - mobj->type = READUINT32(save->p); - else - { - 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 doomednum %d\n", mobj->spawnpoint->type); - else - CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum NULL\n"); - - I_Error("Netsave corrupted"); - } - - mobj->type = new_type; - } - mobj->info = &mobjinfo[mobj->type]; - - if (diff & MD_POS) - { - mobj->x = mobj->old_x = READFIXED(save->p); - mobj->y = mobj->old_y = READFIXED(save->p); - mobj->angle = mobj->old_angle = READANGLE(save->p); - mobj->pitch = mobj->old_pitch = READANGLE(save->p); - mobj->roll = mobj->old_roll = READANGLE(save->p); - } - else - { - mobj->x = mobj->old_x = mobj->spawnpoint->x << FRACBITS; - mobj->y = mobj->old_y = mobj->spawnpoint->y << FRACBITS; - mobj->angle = mobj->old_angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); - mobj->pitch = mobj->old_pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT); - mobj->roll = mobj->old_roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT); - } - if (diff & MD_MOM) - { - mobj->momx = READFIXED(save->p); - mobj->momy = READFIXED(save->p); - mobj->momz = READFIXED(save->p); - mobj->pmomz = READFIXED(save->p); - } // otherwise they're zero, and the memset took care of it - - if (diff & MD_RADIUS) - mobj->radius = READFIXED(save->p); - else - mobj->radius = FixedMul(mobj->info->radius, mapobjectscale); - if (diff & MD_HEIGHT) - mobj->height = READFIXED(save->p); - else - mobj->height = FixedMul(mobj->info->height, mapobjectscale); - if (diff & MD_FLAGS) - mobj->flags = READUINT32(save->p); - else - mobj->flags = mobj->info->flags; - if (diff & MD_FLAGS2) - mobj->flags2 = READUINT32(save->p); - if (diff & MD_HEALTH) - mobj->health = READINT32(save->p); - else - mobj->health = mobj->info->spawnhealth; - if (diff & MD_RTIME) - mobj->reactiontime = READINT32(save->p); - else - mobj->reactiontime = mobj->info->reactiontime; - - if (diff & MD_STATE) - mobj->state = &states[READUINT16(save->p)]; - else - mobj->state = &states[mobj->info->spawnstate]; - if (diff & MD_TICS) - mobj->tics = READINT32(save->p); - else - mobj->tics = mobj->state->tics; - if (diff & MD_SPRITE) { - mobj->sprite = READUINT16(save->p); - if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = READUINT8(save->p); - } - else { - mobj->sprite = mobj->state->sprite; - if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = mobj->state->frame&FF_FRAMEMASK; - } - if (diff & MD_FRAME) - { - mobj->frame = READUINT32(save->p); - mobj->anim_duration = READUINT16(save->p); - } - else - { - mobj->frame = mobj->state->frame; - mobj->anim_duration = (UINT16)mobj->state->var2; - } - if (diff & MD_EFLAGS) - mobj->eflags = READUINT16(save->p); - if (diff & MD_PLAYER) - { - i = READUINT8(save->p); - mobj->player = &players[i]; - mobj->player->mo = mobj; - } - if (diff & MD_MOVEDIR) - mobj->movedir = READANGLE(save->p); - if (diff & MD_MOVECOUNT) - mobj->movecount = READINT32(save->p); - if (diff & MD_THRESHOLD) - mobj->threshold = READINT32(save->p); - if (diff & MD_LASTLOOK) - mobj->lastlook = READINT32(save->p); - else - mobj->lastlook = -1; - if (diff & MD_TARGET) - mobj->target = (mobj_t *)(size_t)READUINT32(save->p); - if (diff & MD_TRACER) - mobj->tracer = (mobj_t *)(size_t)READUINT32(save->p); - if (diff & MD_FRICTION) - mobj->friction = READFIXED(save->p); - else - mobj->friction = ORIG_FRICTION; - if (diff & MD_MOVEFACTOR) - mobj->movefactor = READFIXED(save->p); - else - mobj->movefactor = FRACUNIT; - if (diff & MD_FUSE) - 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 = mapobjectscale; - if (diff & MD_DSCALE) - mobj->destscale = READFIXED(save->p); - else - mobj->destscale = mobj->scale; - if (diff2 & MD2_SCALESPEED) - mobj->scalespeed = READFIXED(save->p); - else - mobj->scalespeed = mapobjectscale/12; - if (diff & MD_ARGS) - { - for (j = 0; j < NUM_MAPTHING_ARGS; j++) - mobj->args[j] = READINT32(save->p); - } - if (diff & MD_STRINGARGS) - { - for (j = 0; j < NUM_MAPTHING_STRINGARGS; j++) - { - size_t len = READINT32(save->p); - size_t k; - - if (!len) - { - Z_Free(mobj->stringargs[j]); - mobj->stringargs[j] = NULL; - continue; - } - - mobj->stringargs[j] = Z_Realloc(mobj->stringargs[j], len + 1, PU_LEVEL, NULL); - for (k = 0; k < len; k++) - mobj->stringargs[j][k] = READCHAR(save->p); - mobj->stringargs[j][len] = '\0'; - } - } - if (diff2 & MD2_CUSVAL) - mobj->cusval = READINT32(save->p); - if (diff2 & MD2_CVMEM) - mobj->cvmem = READINT32(save->p); - if (diff2 & MD2_SKIN) - mobj->skin = &skins[READUINT16(save->p)]; - if (diff2 & MD2_COLOR) - mobj->color = READUINT16(save->p); - if (diff2 & MD2_EXTVAL1) - mobj->extravalue1 = READINT32(save->p); - if (diff2 & MD2_EXTVAL2) - mobj->extravalue2 = READINT32(save->p); - if (diff2 & MD2_HNEXT) - mobj->hnext = (mobj_t *)(size_t)READUINT32(save->p); - if (diff2 & MD2_HPREV) - mobj->hprev = (mobj_t *)(size_t)READUINT32(save->p); - if (diff2 & MD2_ITNEXT) - mobj->itnext = (mobj_t *)(size_t)READUINT32(save->p); - if (diff2 & MD2_SLOPE) - mobj->standingslope = P_SlopeById(READUINT16(save->p)); - if (diff2 & MD2_COLORIZED) - mobj->colorized = READUINT8(save->p); - if (diff2 & MD2_MIRRORED) - mobj->mirrored = READUINT8(save->p); - if (diff2 & MD2_ROLLANGLE) - mobj->rollangle = READANGLE(save->p); - if (diff2 & MD2_SHADOWSCALE) - { - mobj->shadowscale = READFIXED(save->p); - mobj->whiteshadow = READUINT8(save->p); - mobj->shadowcolor = READUINT8(save->p); - } - if (diff2 & MD2_RENDERFLAGS) - mobj->renderflags = READUINT32(save->p); - if (diff2 & MD2_TID) - mobj->tid = READINT16(save->p); - if (diff2 & MD2_SPRITESCALE) - { - mobj->spritexscale = READFIXED(save->p); - mobj->spriteyscale = READFIXED(save->p); - } - else - { - mobj->spritexscale = mobj->spriteyscale = FRACUNIT; - } - if (diff2 & MD2_SPRITEOFFSET) - { - mobj->spritexoffset = READFIXED(save->p); - mobj->spriteyoffset = READFIXED(save->p); - mobj->rollingxoffset = READINT16(save->p); - mobj->rollingyoffset = READINT16(save->p); - } - else - { - mobj->spritexoffset = mobj->spriteyoffset = 0; - mobj->rollingxoffset = mobj->rollingyoffset = 0; - } - if (diff2 & MD2_WORLDOFFSET) - { - mobj->sprxoff = READFIXED(save->p); - mobj->spryoff = READFIXED(save->p); - mobj->sprzoff = READFIXED(save->p); - } - else - { - mobj->sprxoff = mobj->spryoff = mobj->sprzoff = 0; - } - if (diff2 & MD2_SPECIAL) - { - mobj->special = READINT16(save->p); - - for (j = 0; j < NUM_SCRIPT_ARGS; j++) - mobj->script_args[j] = READINT32(save->p); - - for (j = 0; j < NUM_SCRIPT_STRINGARGS; j++) - { - size_t len = READINT32(save->p); - size_t k; - - if (!len) - { - Z_Free(mobj->script_stringargs[j]); - mobj->script_stringargs[j] = NULL; - continue; - } - - mobj->script_stringargs[j] = Z_Realloc(mobj->script_stringargs[j], len + 1, PU_LEVEL, NULL); - for (k = 0; k < len; k++) - mobj->script_stringargs[j][k] = READCHAR(save->p); - mobj->script_stringargs[j][len] = '\0'; - } - } - if (diff2 & MD2_FLOORSPRITESLOPE) - { - pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj); - - slope->zdelta = READFIXED(save->p); - slope->zangle = READANGLE(save->p); - slope->xydirection = READANGLE(save->p); - - slope->o.x = READFIXED(save->p); - slope->o.y = READFIXED(save->p); - slope->o.z = READFIXED(save->p); - - slope->d.x = READFIXED(save->p); - slope->d.y = READFIXED(save->p); - - slope->normal.x = READFIXED(save->p); - slope->normal.y = READFIXED(save->p); - slope->normal.z = READFIXED(save->p); - - P_UpdateSlopeLightOffset(slope); - } - if (diff2 & MD2_LIGHTLEVEL) - { - mobj->lightlevel = READINT16(save->p); - } - if (diff2 & MD2_DISPOFFSET) - { - mobj->dispoffset = READINT32(save->p); - } - if (diff2 & MD2_LASTMOMZ) - { - mobj->lastmomz = READINT32(save->p); - } - if (diff2 & MD2_TERRAIN) - { - UINT32 terrain_index = READUINT32(save->p); - if (terrain_index > 0) - mobj->terrain = K_GetTerrainByIndex(terrain_index - 1); - mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save->p); - } - else - { - mobj->terrain = NULL; - } - if (diff3 & MD3_GRAVITY) - { - mobj->gravity = READFIXED(save->p); - } - else - { - mobj->gravity = FRACUNIT; - } - if (diff3 & MD3_BAKEDOFFSET) - { - mobj->bakexoff = READFIXED(save->p); - mobj->bakeyoff = READFIXED(save->p); - mobj->bakezoff = READFIXED(save->p); - mobj->bakexpiv = READFIXED(save->p); - mobj->bakeypiv = READFIXED(save->p); - mobj->bakezpiv = READFIXED(save->p); - } - else - { - mobj->bakexoff = mobj->bakeyoff = mobj->bakezoff = 0; - mobj->bakexpiv = mobj->bakeypiv = mobj->bakezpiv = 0; - } - if (diff3 & MD3_EXTVAL3) - { - mobj->extravalue3 = READINT32(save->p); - } - if (diff3 & MD3_SHIELDTRACER) - { - mobj->shieldtracer = (mobj_t *)(size_t)READUINT32(save->p); - } - - // Reset some non-synch values - mobj->sloperoll = 0; - mobj->slopepitch = 0; - - // link tid set earlier - P_AddThingTID(mobj); - - // set sprev, snext, bprev, bnext, subsector - P_SetThingPosition(mobj); - - mobj->mobjnum = READUINT32(save->p); - - if (mobj->player) - { - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight; - else - mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; - } - - if (mobj->type == MT_SKYBOX && mobj->spawnpoint) - { - P_InitSkyboxPoint(mobj, mobj->spawnpoint); - } - - if (diff2 & MD2_BOSS3CAP) - P_SetTarget(&boss3cap, mobj); - - if (diff2 & MD2_WAYPOINTCAP) - P_SetTarget(&waypointcap, mobj); - - if (diff2 & MD2_KITEMCAP) - P_SetTarget(&kitemcap, mobj); - - if (diff3 & MD3_MISCCAP) - P_SetTarget(&misccap, mobj); - - R_AddMobjInterpolator(mobj); - - // don't allow the mobj's refcount to be reset by P_AddThinker - // we might've already called P_SetTarget! - return NULL;//&mobj->thinker; -} - -static thinker_t* LoadNoEnemiesThinker(savebuffer_t *save, actionf_p1 thinker) -{ - noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - return &ht->thinker; -} - -static thinker_t* LoadBounceCheeseThinker(savebuffer_t *save, actionf_p1 thinker) -{ - bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - ht->speed = READFIXED(save->p); - ht->distance = READFIXED(save->p); - ht->floorwasheight = READFIXED(save->p); - ht->ceilingwasheight = READFIXED(save->p); - ht->low = READCHAR(save->p); - - if (ht->sector) - ht->sector->ceilingdata = ht; - - return &ht->thinker; -} - -static thinker_t* LoadContinuousFallThinker(savebuffer_t *save, actionf_p1 thinker) -{ - continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->speed = READFIXED(save->p); - ht->direction = READINT32(save->p); - ht->floorstartheight = READFIXED(save->p); - ht->ceilingstartheight = READFIXED(save->p); - ht->destheight = READFIXED(save->p); - - if (ht->sector) - { - ht->sector->ceilingdata = ht; - ht->sector->floordata = ht; - } - - return &ht->thinker; -} - -static thinker_t* LoadMarioBlockThinker(savebuffer_t *save, actionf_p1 thinker) -{ - mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->speed = READFIXED(save->p); - ht->direction = READINT32(save->p); - ht->floorstartheight = READFIXED(save->p); - ht->ceilingstartheight = READFIXED(save->p); - ht->tag = READINT16(save->p); - - if (ht->sector) - { - ht->sector->ceilingdata = ht; - ht->sector->floordata = ht; - } - - return &ht->thinker; -} - -static thinker_t* LoadMarioCheckThinker(savebuffer_t *save, actionf_p1 thinker) -{ - mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - return &ht->thinker; -} - -static thinker_t* LoadThwompThinker(savebuffer_t *save, actionf_p1 thinker) -{ - thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - ht->crushspeed = READFIXED(save->p); - ht->retractspeed = READFIXED(save->p); - ht->direction = READINT32(save->p); - ht->floorstartheight = READFIXED(save->p); - ht->ceilingstartheight = READFIXED(save->p); - ht->delay = READINT32(save->p); - ht->tag = READINT16(save->p); - ht->sound = READUINT16(save->p); - ht->initDelay = READINT32(save->p); - - if (ht->sector) - { - ht->sector->ceilingdata = ht; - ht->sector->floordata = ht; - } - - return &ht->thinker; -} - -static thinker_t* LoadFloatThinker(savebuffer_t *save, actionf_p1 thinker) -{ - floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - ht->tag = READINT16(save->p); - return &ht->thinker; -} - -static thinker_t* LoadEachTimeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - size_t i; - eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - for (i = 0; i < MAXPLAYERS; i++) - { - ht->playersInArea[i] = READCHAR(save->p); - } - ht->triggerOnExit = READCHAR(save->p); - return &ht->thinker; -} - -static thinker_t* LoadRaiseThinker(savebuffer_t *save, actionf_p1 thinker) -{ - raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save->p); - ht->sector = LoadSector(READUINT32(save->p)); - ht->ceilingbottom = READFIXED(save->p); - ht->ceilingtop = READFIXED(save->p); - ht->basespeed = READFIXED(save->p); - ht->extraspeed = READFIXED(save->p); - ht->shaketimer = READUINT8(save->p); - ht->flags = READUINT8(save->p); - return &ht->thinker; -} - -static thinker_t* LoadCeilingThinker(savebuffer_t *save, actionf_p1 thinker) -{ - ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save->p); - ht->sector = LoadSector(READUINT32(save->p)); - ht->bottomheight = READFIXED(save->p); - ht->topheight = READFIXED(save->p); - ht->speed = READFIXED(save->p); - ht->delay = READFIXED(save->p); - ht->delaytimer = READFIXED(save->p); - ht->crush = READUINT8(save->p); - ht->texture = READINT32(save->p); - ht->direction = READINT32(save->p); - ht->tag = READINT16(save->p); - ht->sourceline = READFIXED(save->p); - ht->origspeed = READFIXED(save->p); - ht->crushHeight = READFIXED(save->p); - ht->crushSpeed = READFIXED(save->p); - ht->returnHeight = READFIXED(save->p); - ht->returnSpeed = READFIXED(save->p); - if (ht->sector) - ht->sector->ceilingdata = ht; - return &ht->thinker; -} - -static thinker_t* LoadFloormoveThinker(savebuffer_t *save, actionf_p1 thinker) -{ - floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save->p); - ht->crush = READUINT8(save->p); - ht->sector = LoadSector(READUINT32(save->p)); - ht->direction = READINT32(save->p); - ht->texture = READINT32(save->p); - ht->floordestheight = READFIXED(save->p); - ht->speed = READFIXED(save->p); - ht->origspeed = READFIXED(save->p); - ht->delay = READFIXED(save->p); - ht->delaytimer = READFIXED(save->p); - ht->tag = READINT16(save->p); - ht->sourceline = READFIXED(save->p); - ht->crushHeight = READFIXED(save->p); - ht->crushSpeed = READFIXED(save->p); - ht->returnHeight = READFIXED(save->p); - ht->returnSpeed = READFIXED(save->p); - if (ht->sector) - ht->sector->floordata = ht; - return &ht->thinker; -} - -static thinker_t* LoadLightflashThinker(savebuffer_t *save, actionf_p1 thinker) -{ - lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->maxlight = READINT32(save->p); - ht->minlight = READINT32(save->p); - if (ht->sector) - ht->sector->lightingdata = ht; - return &ht->thinker; -} - -static thinker_t* LoadStrobeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->count = READINT32(save->p); - ht->minlight = READINT16(save->p); - ht->maxlight = READINT16(save->p); - ht->darktime = READINT32(save->p); - ht->brighttime = READINT32(save->p); - if (ht->sector) - ht->sector->lightingdata = ht; - return &ht->thinker; -} - -static thinker_t* LoadGlowThinker(savebuffer_t *save, actionf_p1 thinker) -{ - glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->minlight = READINT16(save->p); - ht->maxlight = READINT16(save->p); - ht->direction = READINT16(save->p); - ht->speed = READINT16(save->p); - if (ht->sector) - ht->sector->lightingdata = ht; - return &ht->thinker; -} - -static thinker_t* LoadFireflickerThinker(savebuffer_t *save, actionf_p1 thinker) -{ - fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->count = READINT32(save->p); - ht->resetcount = READINT32(save->p); - ht->maxlight = READINT16(save->p); - ht->minlight = READINT16(save->p); - if (ht->sector) - ht->sector->lightingdata = ht; - return &ht->thinker; -} - -static thinker_t* LoadElevatorThinker(savebuffer_t *save, actionf_p1 thinker, boolean setplanedata) -{ - elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save->p); - ht->sector = LoadSector(READUINT32(save->p)); - ht->actionsector = LoadSector(READUINT32(save->p)); - ht->direction = READINT32(save->p); - ht->floordestheight = READFIXED(save->p); - ht->ceilingdestheight = READFIXED(save->p); - ht->speed = READFIXED(save->p); - ht->origspeed = READFIXED(save->p); - ht->low = READFIXED(save->p); - ht->high = READFIXED(save->p); - ht->distance = READFIXED(save->p); - ht->delay = READFIXED(save->p); - ht->delaytimer = READFIXED(save->p); - ht->floorwasheight = READFIXED(save->p); - ht->ceilingwasheight = READFIXED(save->p); - - if (ht->sector && setplanedata) - { - ht->sector->ceilingdata = ht; - ht->sector->floordata = ht; - } - - return &ht->thinker; -} - -static thinker_t* LoadCrumbleThinker(savebuffer_t *save, actionf_p1 thinker) -{ - crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - ht->actionsector = LoadSector(READUINT32(save->p)); - ht->player = LoadPlayer(READUINT32(save->p)); - ht->direction = READINT32(save->p); - ht->origalpha = READINT32(save->p); - ht->timer = READINT32(save->p); - ht->speed = READFIXED(save->p); - ht->floorwasheight = READFIXED(save->p); - ht->ceilingwasheight = READFIXED(save->p); - ht->flags = READUINT8(save->p); - - if (ht->sector) - ht->sector->floordata = ht; - - return &ht->thinker; -} - -static thinker_t* LoadScrollThinker(savebuffer_t *save, actionf_p1 thinker) -{ - scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->dx = READFIXED(save->p); - ht->dy = READFIXED(save->p); - ht->affectee = READINT32(save->p); - ht->control = READINT32(save->p); - ht->last_height = READFIXED(save->p); - ht->vdx = READFIXED(save->p); - ht->vdy = READFIXED(save->p); - ht->accel = READINT32(save->p); - ht->exclusive = READINT32(save->p); - ht->type = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadFrictionThinker(savebuffer_t *save, actionf_p1 thinker) -{ - friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->friction = READINT32(save->p); - ht->movefactor = READINT32(save->p); - ht->affectee = READINT32(save->p); - ht->referrer = READINT32(save->p); - ht->roverfriction = READUINT8(save->p); - return &ht->thinker; -} - -static thinker_t* LoadPusherThinker(savebuffer_t *save, actionf_p1 thinker) -{ - pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save->p); - ht->x_mag = READFIXED(save->p); - ht->y_mag = READFIXED(save->p); - ht->z_mag = READFIXED(save->p); - ht->affectee = READINT32(save->p); - ht->roverpusher = READUINT8(save->p); - ht->referrer = READINT32(save->p); - ht->exclusive = READINT32(save->p); - ht->slider = READINT32(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadLaserThinker(savebuffer_t *save, actionf_p1 thinker) -{ - laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save->p); - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->nobosses = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadLightlevelThinker(savebuffer_t *save, actionf_p1 thinker) -{ - lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->sourcelevel = READINT16(save->p); - ht->destlevel = READINT16(save->p); - ht->fixedcurlevel = READFIXED(save->p); - ht->fixedpertic = READFIXED(save->p); - ht->timer = READINT32(save->p); - if (ht->sector) - ht->sector->lightingdata = ht; - return &ht->thinker; -} - -static inline thinker_t* LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) -{ - executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->line = LoadLine(READUINT32(save->p)); - ht->caller = LoadMobj(READUINT32(save->p)); - ht->sector = LoadSector(READUINT32(save->p)); - ht->timer = READINT32(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) -{ - disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->appeartime = READUINT32(save->p); - ht->disappeartime = READUINT32(save->p); - ht->offset = READUINT32(save->p); - ht->timer = READUINT32(save->p); - ht->affectee = READINT32(save->p); - ht->sourceline = READINT32(save->p); - ht->exists = READINT32(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadFadeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - sector_t *ss; - fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->dest_exc = GetNetColormapFromList(READUINT32(save->p)); - ht->sectornum = READUINT32(save->p); - ht->ffloornum = READUINT32(save->p); - ht->alpha = READINT32(save->p); - ht->sourcevalue = READINT16(save->p); - ht->destvalue = READINT16(save->p); - ht->destlightlevel = READINT16(save->p); - ht->speed = READINT16(save->p); - ht->ticbased = (boolean)READUINT8(save->p); - ht->timer = READINT32(save->p); - ht->doexists = READUINT8(save->p); - ht->dotranslucent = READUINT8(save->p); - ht->dolighting = READUINT8(save->p); - ht->docolormap = READUINT8(save->p); - ht->docollision = READUINT8(save->p); - ht->doghostfade = READUINT8(save->p); - ht->exactalpha = READUINT8(save->p); - - ss = LoadSector(ht->sectornum); - if (ss) - { - size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - ffloor_t *rover; - for (rover = ss->ffloors; rover; rover = rover->next) - { - if (j == ht->ffloornum) - { - ht->rover = rover; - rover->fadingdata = ht; - break; - } - j++; - } - } - return &ht->thinker; -} - -static inline thinker_t* LoadFadeColormapThinker(savebuffer_t *save, actionf_p1 thinker) -{ - fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save->p)); - ht->source_exc = GetNetColormapFromList(READUINT32(save->p)); - ht->dest_exc = GetNetColormapFromList(READUINT32(save->p)); - ht->ticbased = (boolean)READUINT8(save->p); - ht->duration = READINT32(save->p); - ht->timer = READINT32(save->p); - if (ht->sector) - ht->sector->fadecolormapdata = ht; - return &ht->thinker; -} - -static inline thinker_t* LoadPlaneDisplaceThinker(savebuffer_t *save, actionf_p1 thinker) -{ - planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - - ht->affectee = READINT32(save->p); - ht->control = READINT32(save->p); - ht->last_height = READFIXED(save->p); - ht->speed = READFIXED(save->p); - ht->type = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadDynamicLineSlopeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - - ht->type = READUINT8(save->p); - ht->slope = LoadSlope(READUINT32(save->p)); - ht->sourceline = LoadLine(READUINT32(save->p)); - ht->extent = READFIXED(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadDynamicVertexSlopeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - size_t i; - dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - - ht->slope = LoadSlope(READUINT32(save->p)); - for (i = 0; i < 3; i++) - ht->secs[i] = LoadSector(READUINT32(save->p)); - READMEM(save->p, ht->vex, sizeof(ht->vex)); - READMEM(save->p, ht->origsecheights, sizeof(ht->origsecheights)); - READMEM(save->p, ht->origvecheights, sizeof(ht->origvecheights)); - ht->relative = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->speed = READINT32(save->p); - ht->distance = READINT32(save->p); - ht->turnobjs = READUINT8(save->p); - return &ht->thinker; -} - -static thinker_t* LoadPolymoveThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->speed = READINT32(save->p); - ht->momx = READFIXED(save->p); - ht->momy = READFIXED(save->p); - ht->distance = READINT32(save->p); - ht->angle = READANGLE(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->speed = READINT32(save->p); - ht->sequence = READINT32(save->p); - ht->pointnum = READINT32(save->p); - ht->direction = READINT32(save->p); - ht->returnbehavior = READUINT8(save->p); - ht->continuous = READUINT8(save->p); - ht->stophere = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->delay = READINT32(save->p); - ht->delayCount = READINT32(save->p); - ht->initSpeed = READINT32(save->p); - ht->speed = READINT32(save->p); - ht->initDistance = READINT32(save->p); - ht->distance = READINT32(save->p); - ht->initAngle = READUINT32(save->p); - ht->angle = READUINT32(save->p); - ht->revAngle = READUINT32(save->p); - ht->momx = READFIXED(save->p); - ht->momy = READFIXED(save->p); - ht->closing = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->delay = READINT32(save->p); - ht->delayCount = READINT32(save->p); - ht->initSpeed = READINT32(save->p); - ht->speed = READINT32(save->p); - ht->initDistance = READINT32(save->p); - ht->distance = READINT32(save->p); - ht->closing = READUINT8(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->controlSector = LoadSector(READUINT32(save->p)); - ht->dx = READFIXED(save->p); - ht->dy = READFIXED(save->p); - ht->oldHeights = READFIXED(save->p); - return &ht->thinker; -} - -static inline thinker_t* LoadPolyrotdisplaceThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->controlSector = LoadSector(READUINT32(save->p)); - ht->rotscale = READFIXED(save->p); - ht->turnobjs = READUINT8(save->p); - ht->oldHeights = READFIXED(save->p); - return &ht->thinker; -} - -static thinker_t* LoadPolyfadeThinker(savebuffer_t *save, actionf_p1 thinker) -{ - polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save->p); - ht->sourcevalue = READINT32(save->p); - ht->destvalue = READINT32(save->p); - ht->docollision = (boolean)READUINT8(save->p); - ht->doghostfade = (boolean)READUINT8(save->p); - ht->ticbased = (boolean)READUINT8(save->p); - ht->duration = READINT32(save->p); - ht->timer = READINT32(save->p); - return &ht->thinker; -} - -static void P_NetUnArchiveThinkers(savebuffer_t *save) -{ - TracyCZone(__zone, true); - - thinker_t *currentthinker; - thinker_t *next; - UINT8 tclass; - UINT8 restoreNum = false; - UINT32 i; - UINT32 numloaded = 0; - - 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++) - { - for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = next) - { - next = currentthinker->next; - - currentthinker->references = 0; // Heinous but this is the only place the assertion in P_UnlinkThinkers is wrong - - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker || currentthinker->function.acp1 == (actionf_p1)P_NullPrecipThinker) - P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it - else - { - (next->prev = currentthinker->prev)->next = next; - R_DestroyLevelInterpolators(currentthinker); - Z_Free(currentthinker); - } - } - } - - // we don't want the removed mobjs to come back - P_InitThinkers(); - - // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity - for (i = 0; i < numsectors; i++) - { - sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL; - } - - // read in saved thinkers - for (i = 0; i < NUM_THINKERLISTS; i++) - { - for (;;) - { - thinker_t* th = NULL; - tclass = READUINT8(save->p); - - if (tclass == tc_end) - break; // leave the saved thinker reading loop - numloaded++; - - switch (tclass) - { - case tc_mobj: - th = LoadMobjThinker(save, (actionf_p1)P_MobjThinker, i); - break; - - case tc_ceiling: - th = LoadCeilingThinker(save, (actionf_p1)T_MoveCeiling); - break; - - case tc_crushceiling: - th = LoadCeilingThinker(save, (actionf_p1)T_CrushCeiling); - break; - - case tc_floor: - th = LoadFloormoveThinker(save, (actionf_p1)T_MoveFloor); - break; - - case tc_flash: - th = LoadLightflashThinker(save, (actionf_p1)T_LightningFlash); - break; - - case tc_strobe: - th = LoadStrobeThinker(save, (actionf_p1)T_StrobeFlash); - break; - - case tc_glow: - th = LoadGlowThinker(save, (actionf_p1)T_Glow); - break; - - case tc_fireflicker: - th = LoadFireflickerThinker(save, (actionf_p1)T_FireFlicker); - break; - - case tc_elevator: - th = LoadElevatorThinker(save, (actionf_p1)T_MoveElevator, true); - break; - - case tc_continuousfalling: - th = LoadContinuousFallThinker(save, (actionf_p1)T_ContinuousFalling); - break; - - case tc_thwomp: - th = LoadThwompThinker(save, (actionf_p1)T_ThwompSector); - break; - - case tc_noenemies: - th = LoadNoEnemiesThinker(save, (actionf_p1)T_NoEnemiesSector); - break; - - case tc_eachtime: - th = LoadEachTimeThinker(save, (actionf_p1)T_EachTimeThinker); - break; - - case tc_raisesector: - th = LoadRaiseThinker(save, (actionf_p1)T_RaiseSector); - break; - - case tc_camerascanner: - th = LoadElevatorThinker(save, (actionf_p1)T_CameraScanner, false); - break; - - case tc_bouncecheese: - th = LoadBounceCheeseThinker(save, (actionf_p1)T_BounceCheese); - break; - - case tc_startcrumble: - th = LoadCrumbleThinker(save, (actionf_p1)T_StartCrumble); - break; - - case tc_marioblock: - th = LoadMarioBlockThinker(save, (actionf_p1)T_MarioBlock); - break; - - case tc_marioblockchecker: - th = LoadMarioCheckThinker(save, (actionf_p1)T_MarioBlockChecker); - break; - - case tc_floatsector: - th = LoadFloatThinker(save, (actionf_p1)T_FloatSector); - break; - - case tc_laserflash: - th = LoadLaserThinker(save, (actionf_p1)T_LaserFlash); - break; - - case tc_lightfade: - th = LoadLightlevelThinker(save, (actionf_p1)T_LightFade); - break; - - case tc_executor: - th = LoadExecutorThinker(save, (actionf_p1)T_ExecutorDelay); - restoreNum = true; - break; - - case tc_disappear: - th = LoadDisappearThinker(save, (actionf_p1)T_Disappear); - break; - - case tc_fade: - th = LoadFadeThinker(save, (actionf_p1)T_Fade); - break; - - case tc_fadecolormap: - th = LoadFadeColormapThinker(save, (actionf_p1)T_FadeColormap); - break; - - case tc_planedisplace: - th = LoadPlaneDisplaceThinker(save, (actionf_p1)T_PlaneDisplace); - break; - case tc_polyrotate: - th = LoadPolyrotatetThinker(save, (actionf_p1)T_PolyObjRotate); - break; - - case tc_polymove: - th = LoadPolymoveThinker(save, (actionf_p1)T_PolyObjMove); - break; - - case tc_polywaypoint: - th = LoadPolywaypointThinker(save, (actionf_p1)T_PolyObjWaypoint); - break; - - case tc_polyslidedoor: - th = LoadPolyslidedoorThinker(save, (actionf_p1)T_PolyDoorSlide); - break; - - case tc_polyswingdoor: - th = LoadPolyswingdoorThinker(save, (actionf_p1)T_PolyDoorSwing); - break; - - case tc_polyflag: - th = LoadPolymoveThinker(save, (actionf_p1)T_PolyObjFlag); - break; - - case tc_polydisplace: - th = LoadPolydisplaceThinker(save, (actionf_p1)T_PolyObjDisplace); - break; - - case tc_polyrotdisplace: - th = LoadPolyrotdisplaceThinker(save, (actionf_p1)T_PolyObjRotDisplace); - break; - - case tc_polyfade: - th = LoadPolyfadeThinker(save, (actionf_p1)T_PolyObjFade); - break; - - case tc_dynslopeline: - th = LoadDynamicLineSlopeThinker(save, (actionf_p1)T_DynamicSlopeLine); - break; - - case tc_dynslopevert: - th = LoadDynamicVertexSlopeThinker(save, (actionf_p1)T_DynamicSlopeVert); - break; - - case tc_scroll: - th = LoadScrollThinker(save, (actionf_p1)T_Scroll); - break; - - case tc_friction: - th = LoadFrictionThinker(save, (actionf_p1)T_Friction); - break; - - case tc_pusher: - th = LoadPusherThinker(save, (actionf_p1)T_Pusher); - break; - - default: - I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); - } - if (th) - P_AddThinker(i, th); - } - - CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i); - } - - // Set each skyboxmo to the first skybox (or NULL) - skyboxmo[0] = skyboxviewpnts[0]; - skyboxmo[1] = skyboxcenterpnts[0]; - - if (restoreNum) - { - executor_t *delay = NULL; - UINT32 mobjnum; - for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) - { - if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) - continue; - delay = (void *)currentthinker; - if (!(mobjnum = (UINT32)(size_t)delay->caller)) - continue; - delay->caller = P_FindNewPosition(mobjnum); - } - } - TracyCZoneEnd(__zone); -} - /////////////////////////////////////////////////////////////////////////////// // // haleyjd 03/26/06: PolyObject saving code @@ -5387,7 +4687,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) { P_NetSyncWorld(save); P_ArchivePolyObjects(save); - P_NetArchiveThinkers(save); + P_NetSyncThinkers(save); P_NetSyncSpecials(save); P_NetSyncColormaps(save); P_NetSyncTubeWaypoints(save); @@ -5439,7 +4739,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) { P_NetSyncWorld(save); P_UnArchivePolyObjects(save); - P_NetUnArchiveThinkers(save); + P_NetSyncThinkers(save); P_NetSyncSpecials(save); P_NetSyncColormaps(save); P_NetSyncTubeWaypoints(save); From fa9c99ff45b81496957ef61ff7e148a857a42a7d Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 5 Oct 2025 22:09:17 +0200 Subject: [PATCH 18/24] Macro the shit out of the thinker tables These were all out of sync lmao Now you can join without crashing, but mobjs are fucked --- src/p_saveg.c | 348 ++++++++++++-------------------------------------- 1 file changed, 81 insertions(+), 267 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 03cab0182..96645502b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1688,99 +1688,6 @@ enum mobj_diff_t MD__MAX }; -typedef enum -{ - tc_mobj, - tc_ceiling, - tc_floor, - tc_flash, - tc_strobe, - tc_glow, - tc_fireflicker, - tc_thwomp, - tc_camerascanner, - tc_elevator, - tc_continuousfalling, - tc_bouncecheese, - tc_startcrumble, - tc_marioblock, - tc_marioblockchecker, - tc_floatsector, - tc_crushceiling, - tc_scroll, - tc_friction, - tc_pusher, - tc_laserflash, - tc_lightfade, - tc_executor, - tc_raisesector, - tc_noenemies, - tc_eachtime, - tc_disappear, - tc_fade, - tc_fadecolormap, - tc_planedisplace, - tc_dynslopeline, - tc_dynslopevert, - tc_polyrotate, // haleyjd 03/26/06: polyobjects - tc_polymove, - tc_polywaypoint, - tc_polyslidedoor, - tc_polyswingdoor, - tc_polyflag, - tc_polydisplace, - tc_polyrotdisplace, - tc_polyfade, - tc_end -} specials_e; - -const actionf_p1 actionspecials[tc_end] = -{ - (actionf_p1)P_MobjThinker, - (actionf_p1)T_MoveCeiling, - (actionf_p1)T_CrushCeiling, - (actionf_p1)T_MoveFloor, - (actionf_p1)T_LightningFlash, - (actionf_p1)T_StrobeFlash, - (actionf_p1)T_Glow, - (actionf_p1)T_FireFlicker, - (actionf_p1)T_MoveElevator, - (actionf_p1)T_ContinuousFalling, - (actionf_p1)T_ThwompSector, - (actionf_p1)T_NoEnemiesSector, - (actionf_p1)T_EachTimeThinker, - (actionf_p1)T_RaiseSector, - (actionf_p1)T_CameraScanner, - (actionf_p1)T_Scroll, - (actionf_p1)T_Friction, - (actionf_p1)T_Pusher, - (actionf_p1)T_BounceCheese, - (actionf_p1)T_StartCrumble, - (actionf_p1)T_MarioBlock, - (actionf_p1)T_MarioBlockChecker, - (actionf_p1)T_FloatSector, - (actionf_p1)T_LaserFlash, - (actionf_p1)T_LightFade, - (actionf_p1)T_ExecutorDelay, - (actionf_p1)T_Disappear, - (actionf_p1)T_Fade, - (actionf_p1)T_FadeColormap, - (actionf_p1)T_PlaneDisplace, - (actionf_p1)T_PolyObjRotate, - (actionf_p1)T_PolyObjMove, - (actionf_p1)T_PolyObjWaypoint, - (actionf_p1)T_PolyDoorSlide, - (actionf_p1)T_PolyDoorSwing, - (actionf_p1)T_PolyObjFlag, - (actionf_p1)T_PolyObjDisplace, - (actionf_p1)T_PolyObjRotDisplace, - (actionf_p1)T_PolyObjFade, - (actionf_p1)T_DynamicSlopeLine, - (actionf_p1)T_DynamicSlopeVert, -}; - -I_StaticAssert(sizeof(actionspecials) / sizeof(actionspecials[0]) == tc_end); - static inline UINT32 SaveMobjnum(const mobj_t *mobj) { if (mobj) return mobj->mobjnum; @@ -2093,6 +2000,10 @@ static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinke else DiffMobj(mobj, diff); + for (j = sizeof(diff)/sizeof(*diff)-1; j > 0; j--) + if (diff[j]) + diff[j-1] |= 0x80000000; + // already read by the client WRITEUINT8(save->p, type); } @@ -2144,7 +2055,7 @@ static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinke // manually link to thinkerlist, since the thinker isn't returned anymore if (!save->write) - P_AddThinker(type, &mobj->thinker); + P_AddThinker(THINK_MOBJ, &mobj->thinker); SYNC(mobj->z); // Force this so 3dfloor problems don't arise. SYNC(mobj->floorz); @@ -2854,8 +2765,9 @@ static thinker_t *SyncFireflickerThinker(savebuffer_t *save, actionf_p1 thinker, return &ht->thinker; } -static thinker_t *SyncElevatorThinker(savebuffer_t *save, actionf_p1 thinker, boolean setplanedata, thinker_t *th, UINT8 type) +static thinker_t *SyncElevatorThinker(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type) { + boolean setplanedata = thinker == (actionf_p1)T_MoveElevator; elevator_t *ht = (void *)th; if (save->write) { @@ -3407,6 +3319,66 @@ static thinker_t *SyncPolyfadeThinker(savebuffer_t *save, actionf_p1 thinker, th return &ht->thinker; } +typedef thinker_t *thinkersync_f(savebuffer_t *save, actionf_p1 thinker, thinker_t *th, UINT8 type); + +#define ITER_THINKERS \ + _(P_MobjThinker, SyncMobjThinker, tc_mobj) \ + _(T_MoveCeiling, SyncCeilingThinker, tc_ceiling) \ + _(T_MoveFloor, SyncCeilingThinker, tc_floor) \ + _(T_LightningFlash, SyncLightflashThinker, tc_flash) \ + _(T_StrobeFlash, SyncStrobeThinker, tc_strobe) \ + _(T_Glow, SyncGlowThinker, tc_glow) \ + _(T_FireFlicker, SyncFireflickerThinker, tc_fireflicker) \ + _(T_ThwompSector, SyncThwompThinker, tc_thwomp) \ + _(T_CameraScanner, SyncElevatorThinker, tc_camerascanner) \ + _(T_MoveElevator, SyncElevatorThinker, tc_elevator) \ + _(T_ContinuousFalling, SyncContinuousFallThinker, tc_continuousfalling) \ + _(T_BounceCheese, SyncBounceCheeseThinker, tc_bouncecheese) \ + _(T_StartCrumble, SyncCrumbleThinker, tc_startcrumble) \ + _(T_MarioBlock, SyncMarioBlockThinker, tc_marioblock) \ + _(T_MarioBlockChecker, SyncMarioCheckThinker, tc_marioblockchecker) \ + _(T_FloatSector, SyncFloatThinker, tc_floatsector) \ + _(T_CrushCeiling, SyncCeilingThinker, tc_crushceiling) \ + _(T_Scroll, SyncScrollThinker, tc_scroll) \ + _(T_Friction, SyncFrictionThinker, tc_friction) \ + _(T_Pusher, SyncPusherThinker, tc_pusher) \ + _(T_LaserFlash, SyncLaserThinker, tc_laserflash) \ + _(T_LightFade, SyncLightlevelThinker, tc_lightfade) \ + _(T_ExecutorDelay, SyncExecutorThinker, tc_executor) \ + _(T_RaiseSector, SyncRaiseThinker, tc_raisesector) \ + _(T_NoEnemiesSector, SyncNoEnemiesThinker, tc_noenemies) \ + _(T_EachTimeThinker, SyncEachTimeThinker, tc_eachtime) \ + _(T_Disappear, SyncDisappearThinker, tc_disappear) \ + _(T_Fade, SyncFadeThinker, tc_fade) \ + _(T_FadeColormap, SyncFadeColormapThinker, tc_fadecolormap) \ + _(T_PlaneDisplace, SyncPlaneDisplaceThinker, tc_planedisplace) \ + _(T_DynamicSlopeLine, SyncDynamicLineSlopeThinker, tc_dynslopeline) \ + _(T_DynamicSlopeVert, SyncDynamicVertexSlopeThinker, tc_dynslopevert) \ + _(T_PolyObjRotate, SyncPolyrotatetThinker, tc_polyrotate) \ + _(T_PolyObjMove, SyncPolymoveThinker, tc_polymove) \ + _(T_PolyObjWaypoint, SyncPolywaypointThinker, tc_polywaypoint) \ + _(T_PolyDoorSlide, SyncPolyslidedoorThinker, tc_polyslidedoor) \ + _(T_PolyDoorSwing, SyncPolyswingdoorThinker, tc_polyswingdoor) \ + _(T_PolyObjFlag, SyncPolymoveThinker, tc_polyflag) \ + _(T_PolyObjDisplace, SyncPolydisplaceThinker, tc_polydisplace) \ + _(T_PolyObjRotDisplace, SyncPolyrotdisplaceThinker, tc_polyrotdisplace) \ + _(T_PolyObjFade, SyncPolyfadeThinker, tc_polyfade ) \ + +typedef enum +{ +#define _(think, sync, tc) tc, + ITER_THINKERS +#undef _ + tc_end +} specials_e; + +static const actionf_p1 actionspecials[tc_end] = +{ +#define _(think, sync, tc) (actionf_p1)think, + ITER_THINKERS +#undef _ +}; + static void P_NetSyncThinkers(savebuffer_t *save) { TracyCZone(__zone, true); @@ -3414,7 +3386,7 @@ static void P_NetSyncThinkers(savebuffer_t *save) thinker_t *currentthinker; thinker_t *next; UINT8 tclass; - UINT8 restoreNum = false; + boolean restoreNum = false; UINT32 i; UINT32 numloaded = 0; @@ -3483,178 +3455,20 @@ static void P_NetSyncThinkers(savebuffer_t *save) } numloaded++; - if (acp == (actionf_p1)P_MobjThinker) - { - th = SyncMobjThinker(save, (actionf_p1)P_MobjThinker, th, tc_mobj); - } -#ifdef PARANOIA - else if (acp == (actionf_p1)P_NullPrecipThinker); -#endif - else if (acp == (actionf_p1)T_MoveCeiling) - { - th = SyncCeilingThinker(save, (actionf_p1)T_MoveCeiling, th, tc_ceiling); - } - else if (acp == (actionf_p1)T_CrushCeiling) - { - th = SyncCeilingThinker(save, (actionf_p1)T_CrushCeiling, th, tc_crushceiling); - } - else if (acp == (actionf_p1)T_MoveFloor) - { - th = SyncFloormoveThinker(save, (actionf_p1)T_MoveFloor, th, tc_floor); - } - else if (acp == (actionf_p1)T_LightningFlash) - { - th = SyncLightflashThinker(save, (actionf_p1)T_LightningFlash, th, tc_flash); - } - else if (acp == (actionf_p1)T_StrobeFlash) - { - th = SyncStrobeThinker(save, (actionf_p1)T_StrobeFlash, th, tc_strobe); - } - else if (acp == (actionf_p1)T_Glow) - { - th = SyncGlowThinker(save, (actionf_p1)T_Glow, th, tc_glow); - } - else if (acp == (actionf_p1)T_FireFlicker) - { - th = SyncFireflickerThinker(save, (actionf_p1)T_FireFlicker, th, tc_fireflicker); - } - else if (acp == (actionf_p1)T_MoveElevator) - { - th = SyncElevatorThinker(save, (actionf_p1)T_MoveElevator, true, th, tc_elevator); - } - else if (acp == (actionf_p1)T_ContinuousFalling) - { - th = SyncContinuousFallThinker(save, (actionf_p1)T_ContinuousFalling, th, tc_continuousfalling); - } - else if (acp == (actionf_p1)T_ThwompSector) - { - th = SyncThwompThinker(save, (actionf_p1)T_ThwompSector, th, tc_thwomp); - } - else if (acp == (actionf_p1)T_NoEnemiesSector) - { - th = SyncNoEnemiesThinker(save, (actionf_p1)T_NoEnemiesSector, th, tc_noenemies); - } - else if (acp == (actionf_p1)T_EachTimeThinker) - { - th = SyncEachTimeThinker(save, (actionf_p1)T_EachTimeThinker, th, tc_eachtime); - } - else if (acp == (actionf_p1)T_RaiseSector) - { - th = SyncRaiseThinker(save, (actionf_p1)T_RaiseSector, th, tc_raisesector); - } - else if (acp == (actionf_p1)T_CameraScanner) - { - th = SyncElevatorThinker(save, (actionf_p1)T_CameraScanner, false, th, tc_camerascanner); - } - else if (acp == (actionf_p1)T_Scroll) - { - th = SyncScrollThinker(save, (actionf_p1)T_Scroll, th, tc_scroll); - } - else if (acp == (actionf_p1)T_Friction) - { - th = SyncFrictionThinker(save, (actionf_p1)T_Friction, th, tc_friction); - } - else if (acp == (actionf_p1)T_Pusher) - { - th = SyncPusherThinker(save, (actionf_p1)T_Pusher, th, tc_pusher); - } - else if (acp == (actionf_p1)T_BounceCheese) - { - th = SyncBounceCheeseThinker(save, (actionf_p1)T_BounceCheese, th, tc_bouncecheese); - } - else if (acp == (actionf_p1)T_StartCrumble) - { - th = SyncCrumbleThinker(save, (actionf_p1)T_StartCrumble, th, tc_startcrumble); - } - else if (acp == (actionf_p1)T_MarioBlock) - { - th = SyncMarioBlockThinker(save, (actionf_p1)T_MarioBlock, th, tc_marioblock); - } - else if (acp == (actionf_p1)T_MarioBlockChecker) - { - th = SyncMarioCheckThinker(save, (actionf_p1)T_MarioBlockChecker, th, tc_marioblockchecker); - } - else if (acp == (actionf_p1)T_FloatSector) - { - th = SyncFloatThinker(save, (actionf_p1)T_FloatSector, th, tc_floatsector); - } - else if (acp == (actionf_p1)T_LaserFlash) - { - th = SyncLaserThinker(save, (actionf_p1)T_LaserFlash, th, tc_laserflash); - } - else if (acp == (actionf_p1)T_LightFade) - { - th = SyncLightlevelThinker(save, (actionf_p1)T_LightFade, th, tc_lightfade); - } - else if (acp == (actionf_p1)T_ExecutorDelay) - { - th = SyncExecutorThinker(save, (actionf_p1)T_ExecutorDelay, th, tc_executor); + + if (acp == (actionf_p1)P_MobjThinker && i != THINK_MOBJ) + I_Error("mobj in non-THINK_MOBJ list"); + + if (acp == (actionf_p1)T_ExecutorDelay) restoreNum = true; - } - else if (acp == (actionf_p1)T_Disappear) - { - th = SyncDisappearThinker(save, (actionf_p1)T_Disappear, th, tc_disappear); - } - else if (acp == (actionf_p1)T_Fade) - { - th = SyncFadeThinker(save, (actionf_p1)T_Fade, th, tc_fade); - } - else if (acp == (actionf_p1)T_FadeColormap) - { - th = SyncFadeColormapThinker(save, (actionf_p1)T_FadeColormap, th, tc_fadecolormap); - } - else if (acp == (actionf_p1)T_PlaneDisplace) - { - th = SyncPlaneDisplaceThinker(save, (actionf_p1)T_PlaneDisplace, th, tc_planedisplace); - } - else if (acp == (actionf_p1)T_PolyObjRotate) - { - th = SyncPolyrotatetThinker(save, (actionf_p1)T_PolyObjRotate, th, tc_polyrotate); - } - else if (acp == (actionf_p1)T_PolyObjMove) - { - th = SyncPolymoveThinker(save, (actionf_p1)T_PolyObjFlag, th, tc_polyflag); - } - else if (acp == (actionf_p1)T_PolyObjWaypoint) - { - th = SyncPolywaypointThinker(save, (actionf_p1)T_PolyObjWaypoint, th, tc_polywaypoint); - } - else if (acp == (actionf_p1)T_PolyDoorSlide) - { - th = SyncPolyslidedoorThinker(save, (actionf_p1)T_PolyDoorSlide, th, tc_polyslidedoor); - } - else if (acp == (actionf_p1)T_PolyDoorSwing) - { - th = SyncPolyswingdoorThinker(save, (actionf_p1)T_PolyDoorSwing, th, tc_polyswingdoor); - } - else if (acp == (actionf_p1)T_PolyObjFlag) - { - th = SyncPolymoveThinker(save, (actionf_p1)T_PolyObjFlag, th, tc_polyflag); - } - else if (acp == (actionf_p1)T_PolyObjDisplace) - { - th = SyncPolydisplaceThinker(save, (actionf_p1)T_PolyObjDisplace, th, tc_polydisplace); - } - else if (acp == (actionf_p1)T_PolyObjRotDisplace) - { - th = SyncPolyrotdisplaceThinker(save, (actionf_p1)T_PolyObjRotDisplace, th, tc_polyrotdisplace); - } - else if (acp == (actionf_p1)T_PolyObjFade) - { - th = SyncPolyfadeThinker(save, (actionf_p1)T_PolyObjFade, th, tc_polyfade); - } - else if (acp == (actionf_p1)T_DynamicSlopeLine) - { - th = SyncDynamicLineSlopeThinker(save, (actionf_p1)T_DynamicSlopeLine, th, tc_dynslopeline); - } - else if (acp == (actionf_p1)T_DynamicSlopeVert) - { - th = SyncDynamicVertexSlopeThinker(save, (actionf_p1)T_DynamicSlopeVert, th, tc_dynslopevert); - } -#ifdef PARANOIA - else - I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection -#endif + + + if (false); +#define _(think, sync, tc) else if (acp == (actionf_p1)think) th = sync(save, acp, th, tc); + ITER_THINKERS +#undef _ + + if (!save->write && th && tclass != tc_mobj) P_AddThinker(i, th); } From 99760c1cc7e8e3ab35e59a52bae51bf1b831e349 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 5 Oct 2025 22:19:01 +0200 Subject: [PATCH 19/24] Cleanup and some fixes --- src/p_saveg.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 96645502b..14e2885dc 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3324,7 +3324,7 @@ typedef thinker_t *thinkersync_f(savebuffer_t *save, actionf_p1 thinker, thinker #define ITER_THINKERS \ _(P_MobjThinker, SyncMobjThinker, tc_mobj) \ _(T_MoveCeiling, SyncCeilingThinker, tc_ceiling) \ - _(T_MoveFloor, SyncCeilingThinker, tc_floor) \ + _(T_MoveFloor, SyncFloormoveThinker, tc_floor) \ _(T_LightningFlash, SyncLightflashThinker, tc_flash) \ _(T_StrobeFlash, SyncStrobeThinker, tc_strobe) \ _(T_Glow, SyncGlowThinker, tc_glow) \ @@ -3385,10 +3385,8 @@ static void P_NetSyncThinkers(savebuffer_t *save) thinker_t *currentthinker; thinker_t *next; - UINT8 tclass; boolean restoreNum = false; UINT32 i; - UINT32 numloaded = 0; if (P_SyncUINT32(save, ARCHIVEBLOCK_THINKERS) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); @@ -3432,6 +3430,7 @@ static void P_NetSyncThinkers(savebuffer_t *save) for (i = 0; i < NUM_THINKERLISTS; i++) { thinker_t* th = &thlist[i]; + UINT32 numloaded = 0; for (;;) { actionf_p1 acp; @@ -3443,33 +3442,37 @@ static void P_NetSyncThinkers(savebuffer_t *save) WRITEUINT8(save->p, tc_end); break; } + acp = th->function.acp1; + if (acp == (actionf_p1)P_NullPrecipThinker || acp == (actionf_p1)P_RemoveThinkerDelayed) + continue; } else { - th = NULL; - tclass = READUINT8(save->p); // NOTE: this is normally written within the sync functions + UINT8 tclass = READUINT8(save->p); // NOTE: this is normally written within the sync functions if (tclass == tc_end) break; + else if (tclass > tc_end) + I_Error("Invalid thinker class %d", tclass); + + th = NULL; acp = actionspecials[tclass]; + if (acp == (actionf_p1)T_ExecutorDelay) + restoreNum = true; + else if (acp == (actionf_p1)P_MobjThinker && i != THINK_MOBJ) + I_Error("P_MobjThinker in non-THINK_MOBJ list"); } - numloaded++; - - if (acp == (actionf_p1)P_MobjThinker && i != THINK_MOBJ) - I_Error("mobj in non-THINK_MOBJ list"); - - if (acp == (actionf_p1)T_ExecutorDelay) - restoreNum = true; - - if (false); #define _(think, sync, tc) else if (acp == (actionf_p1)think) th = sync(save, acp, th, tc); ITER_THINKERS #undef _ + else + I_Error("Unknown thinker type"); + numloaded++; - if (!save->write && th && tclass != tc_mobj) + if (!save->write && th && acp != (actionf_p1)P_MobjThinker) P_AddThinker(i, th); } From 38898596deec8645f56c620ec1e30245c81dd746 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sun, 5 Oct 2025 22:55:08 +0200 Subject: [PATCH 20/24] Forgot to set a default gravity --- src/p_saveg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 14e2885dc..7c2377593 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2337,7 +2337,7 @@ static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinke mobj->terrainOverlay = (mobj_t *)(size_t)READUINT32(save->p); } } - SYNCF(MD3_GRAVITY, mobj->gravity); + SYNCDEF(MD3_GRAVITY, mobj->gravity, FRACUNIT); SYNCF(MD3_BAKEDOFFSET, mobj->bakexoff); SYNCF(MD3_BAKEDOFFSET, mobj->bakeyoff); SYNCF(MD3_BAKEDOFFSET, mobj->bakezoff); From 36a01ba0af51239fa5ff24ed1e4ceb021eeb108a Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 7 Oct 2025 11:45:58 -0400 Subject: [PATCH 21/24] Refactor polyobjects --- src/p_saveg.c | 128 ++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 83 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7c2377593..9bad2405b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2008,8 +2008,6 @@ static thinker_t *SyncMobjThinker(savebuffer_t *save, actionf_p1 thinker, thinke WRITEUINT8(save->p, type); } - // diff is somehow not being sent correctly over the wire. - // client has a diff of 16 instead its intended value j = 0; do SYNC(diff[j]); @@ -3612,109 +3610,73 @@ static inline pslope_t *LoadSlope(UINT32 slopeid) // // haleyjd 03/26/06: PolyObject saving code // -#define PD_FLAGS 0x01 -#define PD_TRANS 0x02 -static inline void P_ArchivePolyObj(savebuffer_t *save, polyobj_t *po) +enum pobj_diff_t { - TracyCZone(__zone, true); + PD_FLAGS, + PD_TRANS, + PD__MAX +}; - UINT8 diff = 0; - WRITEINT32(save->p, po->id); - WRITEANGLE(save->p, po->angle); - - WRITEFIXED(save->p, po->spawnSpot.x); - WRITEFIXED(save->p, po->spawnSpot.y); - - if (po->flags != po->spawnflags) - diff |= PD_FLAGS; - if (po->translucency != po->spawntrans) - diff |= PD_TRANS; - - WRITEUINT8(save->p, diff); - - if (diff & PD_FLAGS) - WRITEINT32(save->p, po->flags); - if (diff & PD_TRANS) - WRITEINT32(save->p, po->translucency); - - TracyCZoneEnd(__zone); -} - -static inline void P_UnArchivePolyObj(savebuffer_t *save, polyobj_t *po) +static inline void P_SynchPolyObj(savebuffer_t *save, polyobj_t *po) { - TracyCZone(__zone, true); - INT32 id; - UINT32 angle; - fixed_t x, y; - UINT8 diff; + UINT8 diff[(PD__MAX>>3) + 1] = {0}; + INT32 j = 0; - // nullify all polyobject thinker pointers; - // the thinkers themselves will fight over who gets the field - // when they first start to run. - po->thinker = NULL; + if (save->write) + { + DIFF(po->flags != po->spawnflags, PD_FLAGS); + DIFF(po->translucency != po->spawntrans, PD_FLAGS); + } + else + { + // nullify all polyobject thinker pointers; + // the thinkers themselves will fight over who gets the field + // when they first start to run. + po->thinker = NULL; + } - id = READINT32(save->p); + id = P_SyncINT32(save, po->id); - angle = READANGLE(save->p); + SYNC(po->angle); - x = READFIXED(save->p); - y = READFIXED(save->p); + SYNC(po->spawnSpot.x); + SYNC(po->spawnSpot.y); - diff = READUINT8(save->p); + do + SYNC(diff[j]); + while (diff[j++] & 0x80); - if (diff & PD_FLAGS) - po->flags = READINT32(save->p); - if (diff & PD_TRANS) - po->translucency = READINT32(save->p); + SYNCF(PD_FLAGS, po->flags); + SYNCF(PD_TRANS, po->translucency); - // if the object is bad or isn't in the id hash, we can do nothing more - // with it, so return now - if (po->isBad || po != Polyobj_GetForNum(id)) - return; + if (!save->write) + { + // if the object is bad or isn't in the id hash, we can do nothing more + // with it, so return now + if (po->isBad || po != Polyobj_GetForNum(id)) + return; - // rotate and translate polyobject - Polyobj_MoveOnLoad(po, angle, x, y); - - TracyCZoneEnd(__zone); + // rotate and translate polyobject + Polyobj_MoveOnLoad(po, po->angle, po->spawnSpot.x, po->spawnSpot.y); + } } -static inline void P_ArchivePolyObjects(savebuffer_t *save) +static inline void P_SyncPolyObjects(savebuffer_t *save) { - TracyCZone(__zone, true); - - INT32 i; - - WRITEUINT32(save->p, ARCHIVEBLOCK_POBJS); - - // save number of polyobjects - WRITEINT32(save->p, numPolyObjects); - - for (i = 0; i < numPolyObjects; ++i) - P_ArchivePolyObj(save, &PolyObjects[i]); - - TracyCZoneEnd(__zone); -} - -static inline void P_UnArchivePolyObjects(savebuffer_t *save) -{ - TracyCZone(__zone, true); - INT32 i, numSavedPolys; - if (READUINT32(save->p) != ARCHIVEBLOCK_POBJS) + if (P_SyncUINT32(save, ARCHIVEBLOCK_POBJS) != ARCHIVEBLOCK_POBJS) I_Error("Bad $$$.sav at archive block Pobjs"); - numSavedPolys = READINT32(save->p); + numSavedPolys = P_SyncINT32(save, numPolyObjects); if (numSavedPolys != numPolyObjects) - I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n"); + I_Error("P_SynchronizePolyObjects: polyobj count inconsistency\n"); for (i = 0; i < numSavedPolys; ++i) - P_UnArchivePolyObj(save, &PolyObjects[i]); - - TracyCZoneEnd(__zone); + P_SynchPolyObj(save, &PolyObjects[i]); } static mobj_t *RelinkMobj(mobj_t **ptr) @@ -4503,7 +4465,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) if (gamestate == GS_LEVEL) { P_NetSyncWorld(save); - P_ArchivePolyObjects(save); + P_SyncPolyObjects(save); P_NetSyncThinkers(save); P_NetSyncSpecials(save); P_NetSyncColormaps(save); @@ -4555,7 +4517,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) if (gamestate == GS_LEVEL) { P_NetSyncWorld(save); - P_UnArchivePolyObjects(save); + P_SyncPolyObjects(save); P_NetSyncThinkers(save); P_NetSyncSpecials(save); P_NetSyncColormaps(save); From 0d7d460cb8b0b11c6fa025dfd893e4f377075519 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 7 Oct 2025 12:09:24 -0400 Subject: [PATCH 22/24] Fix polyobject resyncs --- src/p_saveg.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 9bad2405b..cfe2e3d17 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3621,6 +3621,8 @@ enum pobj_diff_t static inline void P_SynchPolyObj(savebuffer_t *save, polyobj_t *po) { INT32 id; + UINT32 angle; + fixed_t x, y; UINT8 diff[(PD__MAX>>3) + 1] = {0}; INT32 j = 0; @@ -3639,10 +3641,10 @@ static inline void P_SynchPolyObj(savebuffer_t *save, polyobj_t *po) id = P_SyncINT32(save, po->id); - SYNC(po->angle); + angle = P_SyncAngle(save, po->angle); - SYNC(po->spawnSpot.x); - SYNC(po->spawnSpot.y); + x = P_SyncFixed(save, po->spawnSpot.x); + y = P_SyncFixed(save, po->spawnSpot.y); do SYNC(diff[j]); @@ -3659,7 +3661,7 @@ static inline void P_SynchPolyObj(savebuffer_t *save, polyobj_t *po) return; // rotate and translate polyobject - Polyobj_MoveOnLoad(po, po->angle, po->spawnSpot.x, po->spawnSpot.y); + Polyobj_MoveOnLoad(po, angle, x, y); } } From 151bb79d85550adfd8c29d42f7e29bd550dc678e Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 7 Oct 2025 12:35:33 -0400 Subject: [PATCH 23/24] Combine LUA_Archive and LUA_Unarchive --- src/d_netcmd.c | 10 +++--- src/g_demo.c | 6 ++-- src/lua_script.c | 94 ++++++++++++++++++++++-------------------------- src/lua_script.h | 3 +- src/p_saveg.c | 4 +-- 5 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 21fd66e97..8ad22558e 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -6441,8 +6441,9 @@ static void Command_Archivetest_f(void) } // test archive - CONS_Printf("LUA_Archive...\n"); - LUA_Archive(&save, true); + CONS_Printf("LUA_Sync Archive...\n"); + save.write = true; + LUA_Sync(&save, true, false); WRITEUINT8(save.p, 0x7F); wrote = (UINT32)(save.p - save.buffer); @@ -6452,8 +6453,9 @@ static void Command_Archivetest_f(void) // test unarchive save.p = save.buffer; - CONS_Printf("LUA_UnArchive...\n"); - LUA_UnArchive(&save, true, false); + save.write = false; + CONS_Printf("LUA_Sync Unarchive...\n"); + LUA_Sync(&save, true, false); i = READUINT8(save.p); if (i != 0x7F || wrote != (UINT32)(save.p - save.buffer)) { diff --git a/src/g_demo.c b/src/g_demo.c index 388142013..141916b44 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -45,7 +45,7 @@ // SRB2Kart #include "d_netfil.h" // nameonly -#include "lua_script.h" // LUA_ArchiveDemo and LUA_UnArchiveDemo +#include "lua_script.h" // LUA_Sync #include "lua_libs.h" // gL (Lua state) #include "k_kart.h" @@ -2940,7 +2940,7 @@ void G_BeginRecording(void) // player lua vars, always saved even if empty if (demoflags & DF_LUAVARS) - LUA_Archive(&demobuf, false); + LUA_Sync(&demobuf, false, false); memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); @@ -3793,7 +3793,7 @@ void G_DoPlayDemo(char *defdemoname) LUA_ClearState(); // No modeattacking check, DF_LUAVARS won't be present here. - LUA_UnArchive(&demobuf, false, G_CompatLevel(0x0002)); + LUA_Sync(&demobuf, false, G_CompatLevel(0x0002)); } splitscreen = 0; diff --git a/src/lua_script.c b/src/lua_script.c index 6d32162ac..ed719bcbb 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1846,8 +1846,9 @@ void LUA_Step(void) } } -void LUA_Archive(savebuffer_t *save, boolean network) +void LUA_Sync(savebuffer_t *save, boolean network, boolean compat) { + UINT32 mobjnum; INT32 i; thinker_t *th; @@ -1858,71 +1859,60 @@ void LUA_Archive(savebuffer_t *save, boolean network) { if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs. continue; + // all players in game will be archived, even if they just add a 0. - ArchiveExtVars(&save->p, &players[i], "player"); + if (save->write) + ArchiveExtVars(&save->p, &players[i], "player"); + else + UnArchiveExtVars(&save->p, &players[i], compat); } - if (network == true) + if (save->write) { - if (gamestate == GS_LEVEL) + if (network == true) { - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + if (gamestate == GS_LEVEL) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; - // archive function will determine when to skip mobjs, - // and write mobjnum in otherwise. - ArchiveExtVars(&save->p, th, "mobj"); + // archive function will determine when to skip mobjs, + // and write mobjnum in otherwise. + ArchiveExtVars(&save->p, th, "mobj"); + } } + + WRITEUINT32(save->p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + + LUA_HookNetArchive(NetArchive, save); // call the NetArchive hook in archive mode } - - WRITEUINT32(save->p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. - LUA_HookNetArchive(NetArchive, save); // call the NetArchive hook in archive mode + ArchiveTables(&save->p); } - - ArchiveTables(&save->p); - - if (gL) - lua_pop(gL, 1); // pop tables -} - -void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat) -{ - UINT32 mobjnum; - INT32 i; - thinker_t *th; - - if (gL) - lua_newtable(gL); // tables to be read - - for (i = 0; i < MAXPLAYERS; i++) + else { - if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly. - continue; - UnArchiveExtVars(&save->p, &players[i], compat); + if (network == true) + { + do { + mobjnum = READUINT32(save->p); // read a mobjnum + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj + continue; + UnArchiveExtVars(&save->p, th, false); // apply variables + } + } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. + + LUA_HookNetArchive(NetUnArchive, save); // call the NetArchive hook in unarchive mode + } + + UnArchiveTables(&save->p, compat); } - if (network == true) - { - do { - mobjnum = READUINT32(save->p); // read a mobjnum - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj - continue; - UnArchiveExtVars(&save->p, th, false); // apply variables - } - } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. - - LUA_HookNetArchive(NetUnArchive, save); // call the NetArchive hook in unarchive mode - } - - UnArchiveTables(&save->p, compat); - if (gL) lua_pop(gL, 1); // pop tables } diff --git a/src/lua_script.h b/src/lua_script.h index 084333f8d..41b9ee590 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -61,8 +61,7 @@ void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); void LUA_Step(void); -void LUA_Archive(savebuffer_t *save, boolean network); -void LUA_UnArchive(savebuffer_t *save, boolean network, boolean compat); +void LUA_Sync(savebuffer_t *save, boolean network, boolean compat); void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value); diff --git a/src/p_saveg.c b/src/p_saveg.c index cfe2e3d17..edd0ce146 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4476,7 +4476,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) } ACS_Archive(save); - LUA_Archive(save, true); + LUA_Sync(save, true, false); P_ArchiveLuabanksAndConsistency(save); @@ -4529,7 +4529,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) } ACS_UnArchive(save); - LUA_UnArchive(save, true, false); + LUA_Sync(save, true, false); // This is stupid and hacky, but maybe it'll work! P_SetRandSeed(P_GetInitSeed()); From 028d36876560afe1727034f62ce04e2ba2c2f9ba Mon Sep 17 00:00:00 2001 From: NepDisk Date: Tue, 7 Oct 2025 13:03:05 -0400 Subject: [PATCH 24/24] Remove unused functions --- src/p_saveg.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index edd0ce146..e848841e4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1738,18 +1738,6 @@ static sector_t *SyncSector(savebuffer_t *save, sector_t *sector) } } -static line_t *LoadLine(UINT32 line) -{ - if (line >= numlines) return NULL; - return &lines[line]; -} - -static UINT32 SaveLine(const line_t *line) -{ - if (line) return (UINT32)(line - lines); - return 0xFFFFFFFF; -} - static line_t *SyncLine(savebuffer_t *save, line_t *line) { if (save->write) @@ -1778,12 +1766,6 @@ static inline UINT32 SavePlayer(const player_t *player) return 0xFFFFFFFF; } -static UINT32 SaveSlope(const pslope_t *slope) -{ - if (slope) return (UINT32)(slope->id); - return 0xFFFFFFFF; -} - static pslope_t *SyncSlope(savebuffer_t *save, pslope_t *slope) { if (save->write) @@ -3588,24 +3570,6 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) return NULL; } -static inline mobj_t *LoadMobj(UINT32 mobjnum) -{ - if (mobjnum == 0) return NULL; - return (mobj_t *)(size_t)mobjnum; -} - -static inline pslope_t *LoadSlope(UINT32 slopeid) -{ - pslope_t *p = slopelist; - if (slopeid > slopecount) return NULL; - do - { - if (p->id == slopeid) - return p; - } while ((p = p->next)); - return NULL; -} - /////////////////////////////////////////////////////////////////////////////// // // haleyjd 03/26/06: PolyObject saving code