From 78afb67c7feab89a2b9c4eaea22802dc368d2cee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Oct 2020 09:06:09 +0200 Subject: [PATCH] - setup for Duke actor data transition to something more scripting friendly. The main problem here is that there's two data arrays representing an actor - sprite and hittype and the engine only uses indices for reference. By setting up hittype to contain a sprite reference, the function and iterator interface can be rewritten to use a single pointer instead to represent an actor. The main objective is to reduce the number of accesses to the global arrays which constitute the biggest refactoring blocker. --- source/build/src/engine.cpp | 2 +- source/games/duke/src/global.cpp | 2 +- source/games/duke/src/global.h | 2 +- source/games/duke/src/premap.cpp | 2 +- source/games/duke/src/savegame.cpp | 44 +++++------------------------- source/games/duke/src/types.h | 27 ++++++++++++------ 6 files changed, 30 insertions(+), 49 deletions(-) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 7f6329d8f..b36c67ada 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -903,7 +903,7 @@ static spriteext_t spriteext_s[MAXSPRITES+MAXUNIQHUDID]; static spritesmooth_t spritesmooth_s[MAXSPRITES+MAXUNIQHUDID]; static sectortype sector_s[MAXSECTORS]; static walltype wall_s[MAXWALLS]; -static spritetype sprite_s[MAXSPRITES]; +spritetype sprite_s[MAXSPRITES]; static tspritetype tsprite_s[MAXSPRITESONSCREEN]; int32_t enginePreInit(void) diff --git a/source/games/duke/src/global.cpp b/source/games/duke/src/global.cpp index 4172e6cfd..d6c28f35f 100644 --- a/source/games/duke/src/global.cpp +++ b/source/games/duke/src/global.cpp @@ -73,7 +73,7 @@ uint8_t sectorextra[MAXSECTORS]; // move these back into the base structs! int rtsplaying; int tempwallptr; -weaponhit hittype[MAXSPRITES]; +weaponhit hittype[MAXSPRITES+1]; // +1 to have a blank entry for serialization. bool sound445done; // this was local state inside a function, but this must be maintained globally and serialized uint16_t frags[MAXPLAYERS][MAXPLAYERS]; player_struct ps[MAXPLAYERS]; diff --git a/source/games/duke/src/global.h b/source/games/duke/src/global.h index fa157b52e..b336e35b3 100644 --- a/source/games/duke/src/global.h +++ b/source/games/duke/src/global.h @@ -59,7 +59,7 @@ extern uint8_t sectorextra[MAXSECTORS]; // these hold fields that were formerly extern int rtsplaying; extern int tempwallptr; -extern weaponhit hittype[MAXSPRITES]; + extern bool sound445done; extern uint16_t frags[MAXPLAYERS][MAXPLAYERS]; extern player_struct ps[MAXPLAYERS]; diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp index de7247995..481e0ff91 100644 --- a/source/games/duke/src/premap.cpp +++ b/source/games/duke/src/premap.cpp @@ -684,7 +684,7 @@ void prelevel_common(int g) resetprestat(0, g); numclouds = 0; - memset(hittype, 0, sizeof(hittype)); + for (auto& h : hittype) h.clear(); memset(sectorextra, 0, sizeof(sectorextra)); memset(shadedsector, 0, sizeof(shadedsector)); memset(geosectorwarp, -1, sizeof(geosectorwarp)); diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index 5251c6ef2..40fef5eb5 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -31,6 +31,8 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms #include "duke3d.h" #include "gamestate.h" +extern FixedBitArray activeSprites; + BEGIN_DUKE_NS @@ -293,8 +295,10 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, player_struct& w, return arc; } + FSerializer& Serialize(FSerializer& arc, const char* keyname, weaponhit& w, weaponhit* def) { + if (!def) def = &hittype[MAXSPRITES]; if (arc.BeginObject(keyname)) { arc("cgg", w.cgg, def->cgg) @@ -327,7 +331,7 @@ void GameInterface::SerializeGameState(FSerializer& arc) { if (arc.isReading()) { - memset(hittype, 0, sizeof(hittype)); + for (auto& h : hittype) h.clear(); memset(sectorextra, 0, sizeof(sectorextra)); memset(shadedsector, 0, sizeof(shadedsector)); memset(geosectorwarp, -1, sizeof(geosectorwarp)); @@ -340,42 +344,8 @@ void GameInterface::SerializeGameState(FSerializer& arc) arc("multimode", ud.multimode); if (ud.multimode > 1) arc.Array("frags", &frags[0][0], MAXPLAYERS * MAXPLAYERS); - // Here we must only save the used entries, otherwise the savegame would get too large. - weaponhit def = {}; - if (arc.isWriting()) - { - if (arc.BeginArray("weaponhit")) - { - // Save this in a way that's easy to read out again. RapidJSON sucks at iterating over objects. :( - for (int i = 0; i < MAXSPRITES; i++) - { - if (sprite[i].statnum != MAXSTATUS) - { - arc(nullptr, i); - arc(nullptr, hittype[i], def); - } - } - } - arc.EndArray(); - } - else - { - if (arc.BeginArray("weaponhit")) - { - auto s = arc.ArraySize()/2; - for (unsigned i = 0; i < s; i++) - { - int ii; - arc(nullptr, ii); - arc(nullptr, hittype[ii], def); - } - arc.EndArray(); - } - } - - - arc("skill", ud.player_skill) - + arc.SparseArray("actors", hittype, MAXSPRITES, activeSprites) + ("skill", ud.player_skill) ("from_bonus", ud.from_bonus) ("secretlevel", ud.secretlevel) ("respawn_monsters", ud.respawn_monsters) diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 450f7cc4f..ed0c46ba8 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -4,6 +4,8 @@ #include "d_net.h" #include "gameinput.h" +extern spritetype sprite_s[]; + BEGIN_DUKE_NS // all the struct types from JFDuke's duke3d.h @@ -28,16 +30,25 @@ struct weaponhit short timetosleep; int floorz, ceilingz, lastvx, lastvy, bposx, bposy, bposz, aflags; int temp_data[6]; -}; + spritetype& s; // direct reference to the corresponding sprite. -// This is how a Duke actor should later be exposed to scripting. The object definition parts are disabled for now so that this can be used already to transition the code. -class DDukeActor //: public DBuildActor -{ -public: - //DECLARE_CLASS(DDukeActor, DBuildActor) - spritetype s; - weaponhit h; + static weaponhit* array(); // this is necessary to allow define inline functions referencing the global array inside the definition itself. + + weaponhit() : s(sprite_s[this - array()]) {} // little trick to initialize the reference automatically. ;) + weaponhit(const weaponhit& other) = delete; // we also do not want to allow copies. + weaponhit& operator=(const weaponhit& other) = delete; + void clear() + { + cgg = spriteextra = 0; + picnum = ang = extra = owner = movflag = tempang = actorstayput = dispicnum = timetosleep = 0; + floorz = ceilingz = lastvx = lastvy = bposx = bposy = bposz = aflags = 0; + memset(temp_data, 0, sizeof(temp_data)); + } }; +extern weaponhit hittype[MAXSPRITES + 1]; +inline weaponhit* weaponhit::array() { return hittype; } + +using DDukeActor = weaponhit; // we do not really want that stupid name in our interface (but also not rename the struct yet.) struct animwalltype {