- cleaned up the PointerSubstitution code

Since the only thing it gets used for is swapping out PlayerPawns it can safely skip all global variables that never point to a live player, which allowed to remove quite a bit of code here that stood in the way of scriptifying more content
This commit is contained in:
Christoph Oelckers 2018-11-19 17:05:00 +01:00
parent 108874f379
commit 02de10f657
7 changed files with 23 additions and 96 deletions

View File

@ -116,7 +116,7 @@ public:
botinfo_t *botinfo;
int spawn_tries;
int wanted_botnum;
TObjPtr<AActor*> firstthing;
TObjPtr<AInventory*> firstthing;
TObjPtr<AActor*> body1;
TObjPtr<AActor*> body2;

View File

@ -372,7 +372,6 @@ public:
player_t &operator= (const player_t &p);
void Serialize(FSerializer &arc);
size_t FixPointers (const DObject *obj, DObject *replacement);
size_t PropagateMark();
void SetLogNumber (int num);

View File

@ -307,7 +307,6 @@ DObject::~DObject ()
if (!(ObjectFlags & OF_Released))
{
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
Release();
}
}
@ -478,11 +477,15 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
//==========================================================================
//
//
// This once was the main method for pointer cleanup, but
// nowadays its only use is swapping out PlayerPawns.
// This requires pointer fixing throughout all objects and a few
// global variables, but it only needs to look at pointers that
// can point to a player.
//
//==========================================================================
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults)
size_t DObject::StaticPointerSubstitution (AActor *old, AActor *notOld)
{
DObject *probe;
size_t changed = 0;
@ -497,24 +500,12 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool s
last = probe;
}
if (scandefaults)
{
for (auto p : PClassActor::AllActorClasses)
{
auto def = GetDefaultByType(p);
if (def != nullptr)
{
def->DObject::PointerSubstitution(old, notOld);
}
}
}
// Go through the bodyque.
for (i = 0; i < BODYQUESIZE; ++i)
{
if (bodyque[i] == old)
{
bodyque[i] = static_cast<AActor *>(notOld);
bodyque[i] = notOld;
changed++;
}
}
@ -523,36 +514,25 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool s
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
changed += players[i].FixPointers (old, notOld);
}
for (auto &s : level.sectorPortals)
{
if (s.mSkybox == old)
{
s.mSkybox = static_cast<AActor*>(notOld);
changed++;
APlayerPawn *replacement = static_cast<APlayerPawn *>(notOld);
auto &p = players[i];
if (p.mo == old) p.mo = replacement, changed++;
if (p.poisoner.pp == old) p.poisoner = replacement, changed++;
if (p.attacker.pp == old) p.attacker = replacement, changed++;
if (p.camera.pp == old) p.camera = replacement, changed++;
if (p.ConversationNPC.pp == old) p.ConversationNPC = replacement, changed++;
if (p.ConversationPC == old) p.ConversationPC = replacement, changed++;
}
}
// Go through sectors.
for (auto &sec : level.sectors)
{
#define SECTOR_CHECK(f,t) \
if (sec.f.pp == static_cast<t *>(old)) { sec.f = static_cast<t *>(notOld); changed++; }
SECTOR_CHECK( SoundTarget, AActor );
SECTOR_CHECK( SecActTarget, AActor );
SECTOR_CHECK( floordata, DSectorEffect );
SECTOR_CHECK( ceilingdata, DSectorEffect );
SECTOR_CHECK( lightingdata, DSectorEffect );
#undef SECTOR_CHECK
if (sec.SoundTarget == old) sec.SoundTarget = notOld;
}
// Go through bot stuff.
if (bglobal.firstthing.pp == (AActor *)old) bglobal.firstthing = (AActor *)notOld, ++changed;
if (bglobal.body1.pp == (AActor *)old) bglobal.body1 = (AActor *)notOld, ++changed;
if (bglobal.body2.pp == (AActor *)old) bglobal.body2 = (AActor *)notOld, ++changed;
return changed;
}

View File

@ -185,6 +185,8 @@ protected: \
#include "dobjgc.h"
class AActor;
class DObject
{
public:
@ -249,11 +251,9 @@ public:
inline FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field);
// If you need to replace one object with another and want to
// change any pointers from the old object to the new object,
// use this method.
// This is only needed for swapping out PlayerPawns and absolutely nothing else!
virtual size_t PointerSubstitution (DObject *old, DObject *notOld);
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false);
static size_t StaticPointerSubstitution (AActor *old, AActor *notOld);
PClass *GetClass() const
{

View File

@ -396,38 +396,6 @@ player_t &player_t::operator=(const player_t &p)
return *this;
}
// This function supplements the pointer cleanup in dobject.cpp, because
// player_t is not derived from DObject. (I tried it, and DestroyScan was
// unable to properly determine the player object's type--possibly
// because it gets staticly allocated in an array.)
//
// This function checks all the DObject pointers in a player_t and NULLs any
// that match the pointer passed in. If you add any pointers that point to
// DObject (or a subclass), add them here too.
size_t player_t::FixPointers (const DObject *old, DObject *rep)
{
APlayerPawn *replacement = static_cast<APlayerPawn *>(rep);
size_t changed = 0;
// The construct *& is used in several of these to avoid the read barriers
// that would turn the pointer we want to check to NULL if the old object
// is pending deletion.
if (mo == old) mo = replacement, changed++;
if (*&poisoner == old) poisoner = replacement, changed++;
if (*&attacker == old) attacker = replacement, changed++;
if (*&camera == old) camera = replacement, changed++;
if (*&Bot == old) Bot = static_cast<DBot *>(rep), changed++;
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
if (psprites == old) psprites = static_cast<DPSprite *>(rep), changed++;
if (*&ConversationNPC == old) ConversationNPC = replacement, changed++;
if (*&ConversationPC == old) ConversationPC = replacement, changed++;
if (*&MUSINFOactor == old) MUSINFOactor = replacement, changed++;
return changed;
}
size_t player_t::PropagateMark()
{
GC::Mark(mo);

View File

@ -67,7 +67,6 @@ public:
void Interpolate(double smoothratio);
virtual void Serialize(FSerializer &arc);
size_t PointerSubstitution (DObject *old, DObject *notOld);
size_t PropagateMark();
};
@ -535,25 +534,6 @@ void DSectorPlaneInterpolation::Serialize(FSerializer &arc)
("attached", attached);
}
//==========================================================================
//
//
//
//==========================================================================
size_t DSectorPlaneInterpolation::PointerSubstitution (DObject *old, DObject *notOld)
{
int subst = 0;
for(unsigned i=0; i<attached.Size(); i++)
{
if (attached[i] == old)
{
attached[i] = (DInterpolation*)notOld;
subst++;
}
}
return subst;
}
//==========================================================================
//

View File

@ -1048,7 +1048,7 @@ void FunctionCallEmitter::AddParameterStringConst(const FString &konst)
ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray<ExpEmit> *ReturnRegs)
{
int paramcount = 0;
unsigned paramcount = 0;
for (auto &func : emitters)
{
paramcount += func(build);