From f02c5c0a56f2e11693fe778640ae334e8e417712 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 19:25:32 +0200 Subject: [PATCH] - 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. --- src/common/objects/dobjtype.cpp | 115 +--------------------- src/common/objects/dobjtype.h | 5 +- src/d_main.cpp | 7 ++ src/gamedata/d_dehacked.cpp | 4 +- src/gamedata/info.cpp | 93 +++++++++++++++++ src/gamedata/info.h | 1 + src/scripting/decorate/thingdef_parse.cpp | 8 +- src/scripting/thingdef.cpp | 7 +- 8 files changed, 120 insertions(+), 120 deletions(-) diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index b0931297d..83653c20e 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -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(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(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 diff --git a/src/common/objects/dobjtype.h b/src/common/objects/dobjtype.h index bd6fe1e6d..db0893b14 100644 --- a/src/common/objects/dobjtype.h +++ b/src/common/objects/dobjtype.h @@ -36,12 +36,11 @@ class PClass { protected: void Derive(PClass *newclass, FName name); - void InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits); void SetSuper(); public: + void InitializeSpecials(void* addr, void* defaults, TArray 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(); diff --git a/src/d_main.cpp b/src/d_main.cpp index ee515f689..78ffbfa9d 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -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 diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index e8b5fa1ed..e76509508 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -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(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size)); + bool newlycreated; + subclass = static_cast(dehtype->CreateDerivedClass(typeNameBuilder, dehtype->Size, &newlycreated)); + if (newlycreated) subclass->InitializeDefaults(); } while (subclass == nullptr); NewClassType(subclass); // This needs a VM type to work as intended. diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index b7cc3531c..0530b7de3 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -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(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 diff --git a/src/gamedata/info.h b/src/gamedata/info.h index ad633f966..f8e37ab34 100644 --- a/src/gamedata/info.h +++ b/src/gamedata/info.h @@ -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 { diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e3c57b0ef..04f875ae5 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -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(parent->CreateDerivedClass(typeName, parent->Size)); + bool newlycreated; + PClassActor *type = static_cast(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(parent->CreateDerivedClass(newname, parent->Size)); + type = static_cast(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 diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index 1c7848684..7eaa78c7d 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -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)