From 311ce2362ac73b0a801948fa663fe31a50088629 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 11 Apr 2017 19:37:56 +0200 Subject: [PATCH] - started moving stuff out of PClassActor into meta data. This reinstates the old FActorInfo as part of the meta data a class can have so that the class descriptor itself can be freed from any data not directly relevant for managing the class's type information. --- src/actor.h | 6 ++ src/d_dehacked.cpp | 8 +-- src/g_inventory/a_weapons.cpp | 2 +- src/g_shared/a_dynlightdata.cpp | 4 +- src/info.cpp | 80 +++++++++++++++++++---- src/info.h | 21 +++++- src/scripting/decorate/thingdef_parse.cpp | 1 - src/scripting/zscript/zcc_compile.cpp | 9 ++- 8 files changed, 106 insertions(+), 25 deletions(-) diff --git a/src/actor.h b/src/actor.h index 631d854d0..a856103dd 100644 --- a/src/actor.h +++ b/src/actor.h @@ -612,6 +612,12 @@ public: return (AActor *)(this->GetClass()->Defaults); } + FActorInfo *GetInfo() const + { + return ((PClassActor*)GetClass())->ActorInfo(); + } + + FDropItem *GetDropItems() const; // Return true if the monster should use a missile attack, false for melee diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 411564851..b050bd48c 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3051,15 +3051,15 @@ void FinishDehPatch () // Use the DECORATE replacement feature to redirect all spawns // of the original class to the new one. - PClassActor *old_replacement = type->Replacement; + PClassActor *old_replacement = type->ActorInfo()->Replacement; - type->Replacement = subclass; - subclass->Replacee = type; + type->ActorInfo()->Replacement = subclass; + subclass->ActorInfo()->Replacee = type; // If this actor was already replaced by another actor, copy that // replacement over to this item. if (old_replacement != NULL) { - subclass->Replacement = old_replacement; + subclass->ActorInfo()->Replacement = old_replacement; } DPrintf (DMSG_NOTIFY, "%s replaces %s\n", subclass->TypeName.GetChars(), type->TypeName.GetChars()); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index af9634846..89c1f00e5 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -986,7 +986,7 @@ void FWeaponSlots::AddExtraWeapons() } auto weapdef = ((AWeapon*)GetDefaultByType(cls)); if ((cls->GameFilter == GAME_Any || (cls->GameFilter & gameinfo.gametype)) && - cls->Replacement == nullptr && // Replaced weapons don't get slotted. + cls->ActorInfo()->Replacement == nullptr && // Replaced weapons don't get slotted. !(weapdef->WeaponFlags & WIF_POWERED_UP) && !LocateWeapon(cls, nullptr, nullptr) // Don't duplicate it if it's already present. ) diff --git a/src/g_shared/a_dynlightdata.cpp b/src/g_shared/a_dynlightdata.cpp index 7db1f8f7c..757d26bf3 100644 --- a/src/g_shared/a_dynlightdata.cpp +++ b/src/g_shared/a_dynlightdata.cpp @@ -1058,7 +1058,7 @@ void InitializeActorLights() void *mem = ClassDataAllocator.Alloc(sizeof(FInternalLightAssociation)); FInternalLightAssociation * iasso = new(mem) FInternalLightAssociation(&LightAssociations[i]); if (iasso->Light() != nullptr) - ti->LightAssociations.Push(iasso); + ti->ActorInfo()->LightAssociations.Push(iasso); } } // we don't need the parser data for the light associations anymore @@ -1124,7 +1124,7 @@ void AActor::AttachLight(unsigned int count, const FLightDefaults *lightdef) void AActor::SetDynamicLights() { - TArray & LightAssociations = GetClass()->LightAssociations; + TArray & LightAssociations = GetInfo()->LightAssociations; unsigned int count = 0; if (state == NULL) return; diff --git a/src/info.cpp b/src/info.cpp index b8f7db995..f32baebc7 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -65,6 +65,62 @@ FRandom FState::pr_statetics("StateTics"); cycle_t ActionCycles; + +//========================================================================== +// +// special type for the native ActorInfo. This allows to let this struct +// be handled by the generic object constructors for the VM. +// +//========================================================================== + +class PActorInfo : public PBasicType +{ + DECLARE_CLASS(PActorInfo, PBasicType); +public: + PActorInfo() + :PBasicType(sizeof(FActorInfo), alignof(FActorInfo)) + { + } + + void SetDefaultValue(void *base, unsigned offset, TArray *special) const override + { + if (base != nullptr) new((uint8_t *)base + offset) FActorInfo; + if (special != nullptr) + { + special->Push(std::make_pair(this, offset)); + } + } + + void InitializeValue(void *addr, const void *def) const override + { + if (def == nullptr) + { + new(addr) FActorInfo; + } + else + { + new(addr) FActorInfo(*(const FActorInfo*)def); + } + } + + void DestroyValue(void *addr) const override + { + FActorInfo *self = (FActorInfo*)addr; + self->~FActorInfo(); + } + +}; + +IMPLEMENT_CLASS(PActorInfo, false, false) + +void AddActorInfo(PClass *cls) +{ + auto type = new PActorInfo; + TypeTable.AddType(type); + cls->AddField("*", type, VARF_Meta); +} + + void FState::SetAction(const char *name) { ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name); @@ -245,8 +301,6 @@ PClassActor::PClassActor() DoomEdNum = -1; OwnedStates = NULL; NumOwnedStates = 0; - Replacement = NULL; - Replacee = NULL; StateList = NULL; DamageFactors = NULL; PainChances = NULL; @@ -339,8 +393,8 @@ bool PClassActor::SetReplacement(FName replaceName) } if (replacee != nullptr) { - replacee->Replacement = this; - Replacee = replacee; + replacee->ActorInfo()->Replacement = this; + ActorInfo()->Replacee = replacee; } } return true; @@ -467,15 +521,15 @@ PClassActor *PClassActor::GetReplacement(bool lookskill) lookskill = false; skillrepname = NAME_None; } } - if (Replacement == NULL && (!lookskill || skillrepname == NAME_None)) + auto Replacement = ActorInfo()->Replacement; + if (Replacement == nullptr && (!lookskill || skillrepname == NAME_None)) { return this; } // The Replacement field is temporarily NULLed to prevent // potential infinite recursion. - PClassActor *savedrep = Replacement; - Replacement = NULL; - PClassActor *rep = savedrep; + ActorInfo()->Replacement = nullptr; + PClassActor *rep = Replacement; // Handle skill-based replacement here. It has precedence on DECORATE replacement // in that the skill replacement is applied first, followed by DECORATE replacement // on the actor indicated by the skill replacement. @@ -487,7 +541,7 @@ PClassActor *PClassActor::GetReplacement(bool lookskill) // Skill replacements are not recursive, contrarily to DECORATE replacements rep = rep->GetReplacement(false); // Reset the temporarily NULLed field - Replacement = savedrep; + ActorInfo()->Replacement = Replacement; return rep; } @@ -523,21 +577,21 @@ PClassActor *PClassActor::GetReplacee(bool lookskill) lookskill = false; } } - if (Replacee == NULL && (!lookskill || skillrepname == NAME_None)) + PClassActor *savedrep = ActorInfo()->Replacee; + if (savedrep == nullptr && (!lookskill || skillrepname == NAME_None)) { return this; } // The Replacee field is temporarily NULLed to prevent // potential infinite recursion. - PClassActor *savedrep = Replacee; - Replacee = NULL; + ActorInfo()->Replacee = nullptr; PClassActor *rep = savedrep; if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL)) { rep = PClass::FindActor(skillrepname); } rep = rep->GetReplacee(false); - Replacee = savedrep; + ActorInfo()->Replacee = savedrep; return rep; } diff --git a/src/info.h b/src/info.h index 5af8ac5f5..575f9318d 100644 --- a/src/info.h +++ b/src/info.h @@ -236,6 +236,19 @@ private: struct FDropItem; +struct FActorInfo +{ + TArray LightAssociations; + PClassActor *Replacement = nullptr; + PClassActor *Replacee = nullptr; + + FActorInfo() {} + FActorInfo(const FActorInfo & other) + { + LightAssociations = other.LightAssociations; + } +}; + class PClassActor : public PClass { DECLARE_CLASS(PClassActor, PClass); @@ -256,6 +269,11 @@ public: bool SetReplacement(FName replaceName); void SetDropItems(FDropItem *drops); + FActorInfo *ActorInfo() const + { + return (FActorInfo*)Meta; + } + FState *FindState(int numnames, FName *names, bool exact=false) const; FState *FindStateByString(const char *name, bool exact=false); FState *FindState(FName name) const @@ -271,10 +289,7 @@ public: PClassActor *GetReplacement(bool lookskill=true); PClassActor *GetReplacee(bool lookskill=true); - TArray LightAssociations; FState *OwnedStates; - PClassActor *Replacement; - PClassActor *Replacee; int NumOwnedStates; uint8_t GameFilter; uint8_t DefaultStateUsage; // state flag defaults for blocks without a qualifier. diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 0bf96e441..edf46d3a7 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -1016,7 +1016,6 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par ti = DecoDerivedClass(sc, parent, typeName); ti->bDecorateClass = true; // we only set this for 'modern' DECORATE. The original stuff is so limited that it cannot do anything that may require flagging. - ti->Replacee = ti->Replacement = NULL; ti->DoomEdNum = -1; return ti; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index fe93be7c9..454cab470 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1112,6 +1112,7 @@ ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expressio // builds the internal structure of all classes and structs // //========================================================================== +void AddActorInfo(PClass *cls); void ZCCCompiler::CompileAllFields() { @@ -1156,6 +1157,7 @@ void ZCCCompiler::CompileAllFields() for (unsigned i = 0; i < Classes.Size(); i++) { auto type = Classes[i]->Type(); + if (type->Size == TentativeClass) { if (type->ParentClass->Size == TentativeClass) @@ -1169,7 +1171,12 @@ void ZCCCompiler::CompileAllFields() type->Size = Classes[i]->Type()->ParentClass->Size; } } - if (Classes[i]->Type()->ParentClass) + if (type->TypeName == NAME_Actor) + { + assert(type->MetaSize == 0); + AddActorInfo(type); // AActor needs the actor info manually added to its meta data before adding any scripted fields. + } + else if (Classes[i]->Type()->ParentClass) type->MetaSize = Classes[i]->Type()->ParentClass->MetaSize; else type->MetaSize = 0;