mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-01-19 05:30:49 +00:00
- fixed: Non-actor classes never called InitializeDefaults to set up their special variables.
- fixed: DThinkerIterator and DBlockThingsIterator did not have a default constructor that was safe to call from an out-of-game context.
This commit is contained in:
parent
c0ef052d07
commit
eef91463ab
6 changed files with 52 additions and 28 deletions
|
@ -3194,34 +3194,37 @@ void PClass::Derive(PClass *newclass, FName name)
|
||||||
|
|
||||||
void PClass::InitializeDefaults()
|
void PClass::InitializeDefaults()
|
||||||
{
|
{
|
||||||
assert(Defaults == NULL);
|
if (IsKindOf(RUNTIME_CLASS(PClassActor)))
|
||||||
Defaults = (BYTE *)M_Malloc(Size);
|
|
||||||
|
|
||||||
// run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them.
|
|
||||||
// Temporarily setting bSerialOverride prevents linking into the thinker chains.
|
|
||||||
auto s = DThinker::bSerialOverride;
|
|
||||||
DThinker::bSerialOverride = true;
|
|
||||||
ConstructNative(Defaults);
|
|
||||||
DThinker::bSerialOverride = s;
|
|
||||||
// We must unlink the defaults from the class list because it's just a static block of data to the engine.
|
|
||||||
DObject *optr = (DObject*)Defaults;
|
|
||||||
GC::Root = optr->ObjNext;
|
|
||||||
optr->ObjNext = nullptr;
|
|
||||||
optr->SetClass(this);
|
|
||||||
|
|
||||||
|
|
||||||
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
|
|
||||||
if (ParentClass->Defaults != NULL)
|
|
||||||
{
|
{
|
||||||
memcpy(Defaults + sizeof(DObject), ParentClass->Defaults + sizeof(DObject), ParentClass->Size - sizeof(DObject));
|
assert(Defaults == NULL);
|
||||||
if (Size > ParentClass->Size)
|
Defaults = (BYTE *)M_Malloc(Size);
|
||||||
|
|
||||||
|
// run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them.
|
||||||
|
// Temporarily setting bSerialOverride prevents linking into the thinker chains.
|
||||||
|
auto s = DThinker::bSerialOverride;
|
||||||
|
DThinker::bSerialOverride = true;
|
||||||
|
ConstructNative(Defaults);
|
||||||
|
DThinker::bSerialOverride = s;
|
||||||
|
// We must unlink the defaults from the class list because it's just a static block of data to the engine.
|
||||||
|
DObject *optr = (DObject*)Defaults;
|
||||||
|
GC::Root = optr->ObjNext;
|
||||||
|
optr->ObjNext = nullptr;
|
||||||
|
optr->SetClass(this);
|
||||||
|
|
||||||
|
|
||||||
|
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
|
||||||
|
if (ParentClass->Defaults != NULL)
|
||||||
{
|
{
|
||||||
memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
|
memcpy(Defaults + sizeof(DObject), ParentClass->Defaults + sizeof(DObject), ParentClass->Size - sizeof(DObject));
|
||||||
|
if (Size > ParentClass->Size)
|
||||||
|
{
|
||||||
|
memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bRuntimeClass)
|
if (bRuntimeClass)
|
||||||
|
|
|
@ -710,8 +710,12 @@ class DThinkerIterator : public DObject, public FThinkerIterator
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(DThinkerIterator, DObject)
|
DECLARE_CLASS(DThinkerIterator, DObject)
|
||||||
|
|
||||||
|
DThinkerIterator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DThinkerIterator(PClass *cls = nullptr, int statnum = MAX_STATNUM + 1)
|
DThinkerIterator(PClass *cls, int statnum = MAX_STATNUM + 1)
|
||||||
: FThinkerIterator(cls, statnum)
|
: FThinkerIterator(cls, statnum)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,9 @@ public:
|
||||||
FThinkerIterator (const PClass *type, int statnum, DThinker *prev);
|
FThinkerIterator (const PClass *type, int statnum, DThinker *prev);
|
||||||
DThinker *Next (bool exact = false);
|
DThinker *Next (bool exact = false);
|
||||||
void Reinit ();
|
void Reinit ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FThinkerIterator() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T> class TThinkerIterator : public FThinkerIterator
|
template <class T> class TThinkerIterator : public FThinkerIterator
|
||||||
|
|
|
@ -1177,6 +1177,11 @@ class DBlockThingsIterator : public DObject, public FMultiBlockThingsIterator
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(DBlockThingsIterator, DObject);
|
DECLARE_CLASS(DBlockThingsIterator, DObject);
|
||||||
FPortalGroupArray check;
|
FPortalGroupArray check;
|
||||||
|
protected:
|
||||||
|
DBlockThingsIterator()
|
||||||
|
:FMultiBlockThingsIterator(check)
|
||||||
|
{
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
FMultiBlockThingsIterator::CheckResult cres;
|
FMultiBlockThingsIterator::CheckResult cres;
|
||||||
|
|
||||||
|
@ -1186,7 +1191,7 @@ public:
|
||||||
return FMultiBlockThingsIterator::Next(&cres);
|
return FMultiBlockThingsIterator::Next(&cres);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBlockThingsIterator(AActor *origin = nullptr, double checkradius = -1, bool ignorerestricted = false)
|
DBlockThingsIterator(AActor *origin, double checkradius = -1, bool ignorerestricted = false)
|
||||||
: FMultiBlockThingsIterator(check, origin, checkradius, ignorerestricted)
|
: FMultiBlockThingsIterator(check, origin, checkradius, ignorerestricted)
|
||||||
{
|
{
|
||||||
cres.thing = nullptr;
|
cres.thing = nullptr;
|
||||||
|
|
|
@ -327,6 +327,8 @@ class FMultiBlockThingsIterator
|
||||||
|
|
||||||
void startIteratorForGroup(int group);
|
void startIteratorForGroup(int group);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FMultiBlockThingsIterator(FPortalGroupArray &check) : checklist(check) {}
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct CheckResult
|
struct CheckResult
|
||||||
|
|
|
@ -1874,7 +1874,14 @@ void ZCCCompiler::InitDefaults()
|
||||||
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
if (!c->Type()->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||||
{
|
{
|
||||||
if (c->Defaults.Size()) Error(c->cls, "%s: Non-actor classes may not have defaults", c->Type()->TypeName.GetChars());
|
if (c->Defaults.Size()) Error(c->cls, "%s: Non-actor classes may not have defaults", c->Type()->TypeName.GetChars());
|
||||||
if (c->Type()->ParentClass) c->Type()->ParentClass->DeriveData(c->Type());
|
if (c->Type()->ParentClass)
|
||||||
|
{
|
||||||
|
auto ti = static_cast<PClassActor *>(c->Type());
|
||||||
|
FString mename = ti->TypeName.GetChars();
|
||||||
|
|
||||||
|
ti->InitializeDefaults();
|
||||||
|
ti->ParentClass->DeriveData(ti);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue