- took InitializeDefaults out of PClass and moved it to PClassActor.

Like so many other parts, this created a hard dependency of the low level code on very invasive game content.
This commit is contained in:
Christoph Oelckers 2020-04-11 19:25:32 +02:00
parent 74c5f83658
commit f02c5c0a56
8 changed files with 120 additions and 120 deletions

View file

@ -39,17 +39,12 @@
#include "dobject.h"
#include "serializer.h"
#include "actor.h"
#include "autosegs.h"
#include "v_text.h"
#include "a_pickups.h"
#include "d_player.h"
#include "fragglescript/t_fs.h"
#include "a_keys.h"
#include "c_cvars.h"
#include "vm.h"
#include "symbols.h"
#include "types.h"
#include "scriptutil.h"
#include "i_system.h"
// MACROS ------------------------------------------------------------------
@ -217,13 +212,6 @@ void PClass::StaticInit ()
((ClassReg *)*probe)->RegisterClass ();
}
probe.Reset();
for(auto cls : AllClasses)
{
if (cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
PClassActor::AllActorClasses.Push(static_cast<PClassActor*>(cls));
}
}
// Keep built-in classes in consistant order. I did this before, though
// I'm not sure if this is really necessary to maintain any sort of sync.
@ -255,7 +243,6 @@ void PClass::StaticShutdown ()
{
*p = nullptr;
}
ScriptUtil::Clear();
FunctionPtrList.Clear();
VMFunction::DeleteAll();
@ -267,10 +254,6 @@ void PClass::StaticShutdown ()
// This flags DObject::Destroy not to call any scripted OnDestroy methods anymore.
bVMOperational = false;
for (auto &p : players)
{
p.PendingWeapon = nullptr;
}
Namespaces.ReleaseSymbols();
// This must be done in two steps because the native classes are not ordered by inheritance,
@ -282,7 +265,6 @@ void PClass::StaticShutdown ()
TypeTable.Clear();
ClassDataAllocator.FreeAllBlocks();
AllClasses.Clear();
PClassActor::AllActorClasses.Clear();
ClassMap.Clear();
FAutoSegIterator probe(CRegHead, CRegTail);
@ -393,10 +375,6 @@ void PClass::InsertIntoHash (bool native)
{
ClassMap[TypeName] = this;
}
if (!native && IsDescendantOf(RUNTIME_CLASS(AActor)))
{
PClassActor::AllActorClasses.Push(static_cast<PClassActor*>(this));
}
}
//==========================================================================
@ -548,90 +526,6 @@ void PClass::Derive(PClass *newclass, FName name)
}
//==========================================================================
//
// PClassActor :: InitializeNativeDefaults
//
//==========================================================================
void PClass::InitializeDefaults()
{
if (IsDescendantOf(RUNTIME_CLASS(AActor)))
{
assert(Defaults == nullptr);
Defaults = (uint8_t *)M_Malloc(Size);
ConstructNative(Defaults);
// 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 != nullptr)
{
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));
}
assert(MetaSize >= ParentClass->MetaSize);
if (MetaSize != 0)
{
Meta = (uint8_t*)M_Malloc(MetaSize);
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
if (ParentClass->Meta != nullptr)
{
memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
if (MetaSize > ParentClass->MetaSize)
{
memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize);
}
}
else
{
memset(Meta, 0, MetaSize);
}
if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
else memset(Meta, 0, MetaSize);
}
}
if (VMType != nullptr) // purely internal classes have no symbol table
{
if (bRuntimeClass)
{
// Copy parent values from the parent defaults.
assert(ParentClass != nullptr);
if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits);
for (const PField *field : Fields)
{
if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta))
{
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
}
}
}
if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits);
for (const PField *field : Fields)
{
if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta))
{
field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits);
}
}
}
}
//==========================================================================
//
// PClass :: CreateDerivedClass
@ -640,7 +534,7 @@ void PClass::InitializeDefaults()
//
//==========================================================================
PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycreated)
{
assert(size >= Size);
PClass *type;
@ -648,6 +542,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
const PClass *existclass = FindClass(name);
if (newlycreated) *newlycreated = false;
if (existclass != nullptr)
{
// This is a placeholder so fill it in
@ -680,7 +575,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
if (size != TentativeClass)
{
NewClassType(type);
type->InitializeDefaults();
if (newlycreated) *newlycreated = true;
type->Virtuals = Virtuals;
}
else

View file

@ -36,12 +36,11 @@ class PClass
{
protected:
void Derive(PClass *newclass, FName name);
void InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffset> PClass::*Inits);
void SetSuper();
public:
void InitializeSpecials(void* addr, void* defaults, TArray<FTypeAndOffset> PClass::* Inits);
void WriteAllFields(FSerializer &ar, const void *addr) const;
bool ReadAllFields(FSerializer &ar, void *addr) const;
void InitializeDefaults();
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc);
PSymbol *FindSymbol(FName symname, bool searchparents) const;
PField *AddField(FName name, PType *type, uint32_t flags);
@ -77,7 +76,7 @@ public:
~PClass();
void InsertIntoHash(bool native);
DObject *CreateNew();
PClass *CreateDerivedClass(FName name, unsigned int size);
PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr);
void InitializeActorInfo();
void BuildFlatPointers();

View file

@ -110,6 +110,7 @@
#include "animations.h"
#include "texturemanager.h"
#include "formats/multipatchtexture.h"
#include "scriptutil.h"
EXTERN_CVAR(Bool, hud_althud)
EXTERN_CVAR(Int, vr_mode)
@ -3443,6 +3444,12 @@ void D_Cleanup()
GC::DelSoftRootHead();
for (auto& p : players)
{
p.PendingWeapon = nullptr;
}
PClassActor::AllActorClasses.Clear();
ScriptUtil::Clear();
PClass::StaticShutdown();
GC::FullGC(); // perform one final garbage collection after shutdown

View file

@ -3029,7 +3029,9 @@ void FinishDehPatch ()
{
// Retry until we find a free name. This is unlikely to happen but not impossible.
mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++);
subclass = static_cast<PClassActor *>(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size));
bool newlycreated;
subclass = static_cast<PClassActor *>(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated));
if (newlycreated) subclass->InitializeDefaults();
}
while (subclass == nullptr);
NewClassType(subclass); // This needs a VM type to work as intended.

View file

@ -392,6 +392,15 @@ void PClassActor::StaticInit()
if (!batchrun) Printf ("LoadActors: Load actor definitions.\n");
ClearStrifeTypes();
LoadActors ();
for (auto cls : AllClasses)
{
if (cls->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
AllActorClasses.Push(static_cast<PClassActor*>(cls));
}
}
LoadAltHudStuff();
InitBotStuff();
@ -444,6 +453,90 @@ bool PClassActor::SetReplacement(FName replaceName)
return true;
}
//==========================================================================
//
// PClassActor :: InitializeNativeDefaults
//
//==========================================================================
void PClassActor::InitializeDefaults()
{
if (IsDescendantOf(RUNTIME_CLASS(AActor)))
{
assert(Defaults == nullptr);
Defaults = (uint8_t*)M_Malloc(Size);
ConstructNative(Defaults);
// 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 != nullptr)
{
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));
}
assert(MetaSize >= ParentClass->MetaSize);
if (MetaSize != 0)
{
Meta = (uint8_t*)M_Malloc(MetaSize);
// Copy the defaults from the parent but leave the DObject part alone because it contains important data.
if (ParentClass->Meta != nullptr)
{
memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
if (MetaSize > ParentClass->MetaSize)
{
memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize);
}
}
else
{
memset(Meta, 0, MetaSize);
}
if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
else memset(Meta, 0, MetaSize);
}
}
if (VMType != nullptr) // purely internal classes have no symbol table
{
if (bRuntimeClass)
{
// Copy parent values from the parent defaults.
assert(ParentClass != nullptr);
if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits);
for (const PField* field : Fields)
{
if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta))
{
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
}
}
}
if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits);
for (const PField* field : Fields)
{
if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta))
{
field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits);
}
}
}
}
//==========================================================================
//
// PClassActor :: RegisterIDs

View file

@ -307,6 +307,7 @@ public:
void SetDamageFactor(FName type, double factor);
void SetPainChance(FName type, int chance);
bool SetReplacement(FName replaceName);
void InitializeDefaults();
FActorInfo *ActorInfo() const
{

View file

@ -77,7 +77,8 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN
{
sc.Message(MSG_ERROR, "Parent class %s of %s not accessible to DECORATE", parent->TypeName.GetChars(), typeName.GetChars());
}
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
bool newlycreated;
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size, &newlycreated));
if (type == nullptr)
{
FString newname = typeName.GetChars();
@ -94,14 +95,15 @@ PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FN
// Due to backwards compatibility issues this cannot be an unconditional error.
sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars());
}
type = static_cast<PClassActor *>(parent->CreateDerivedClass(newname, parent->Size));
type = static_cast<PClassActor *>(parent->CreateDerivedClass(newname, parent->Size, &newlycreated));
if (type == nullptr)
{
// This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless.
sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars());
}
}
if (newlycreated) type->InitializeDefaults();
if (type != nullptr)
{
// [ZZ] DECORATE classes are always play

View file

@ -474,10 +474,11 @@ void LoadActors()
I_Error("%d errors while parsing DECORATE scripts", FScriptPosition::ErrorCounter);
}
FScriptPosition::ResetErrorCounter();
for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--)
// AllActorClasses hasn'T been set up yet.
for (int i = PClass::AllClasses.Size() - 1; i >= 0; i--)
{
auto ti = PClassActor::AllActorClasses[i];
auto ti = (PClassActor*)PClass::AllClasses[i];
if (!ti->IsDescendantOf(RUNTIME_CLASS(AActor))) continue;
if (ti->Size == TentativeClass)
{
if (ti->bOptional)