From 7efd3018101d90816e014860a37756736dbb88b2 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 28 Jan 2025 07:38:52 -0500 Subject: [PATCH] Clean up for Behavior API Use TObjPtr to improve null checking. Add option to clear only specific kinds of Behaviors. Fixed removal checks while ticking. Don't stop at now-null behaviors when iterating. --- src/playsim/actor.h | 12 +-- src/playsim/p_mobj.cpp | 108 ++++++++++++++------------ src/scripting/vmiterators.cpp | 27 +++---- src/serializer_doom.cpp | 12 ++- src/serializer_doom.h | 2 +- wadsrc/static/zscript/actors/actor.zs | 2 +- 6 files changed, 88 insertions(+), 75 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index db069bc32..cbc2781de 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1386,7 +1386,7 @@ public: // landing speed from a jump with normal gravity (squats the player's view) // (note: this is put into AActor instead of the PlayerPawn because non-players also use the value) double LandingSpeed; - TMap Behaviors; + TMap> Behaviors; // ThingIDs @@ -1448,16 +1448,16 @@ public: return GetClass()->FindState(numnames, names, exact); } - DBehavior* FindBehavior(const PClass& type) const + DBehavior* FindBehavior(FName type) const { - auto b = Behaviors.CheckKey(type.TypeName); - return b != nullptr && *b != nullptr && !((*b)->ObjectFlags & OF_EuthanizeMe) ? *b : nullptr; + auto b = Behaviors.CheckKey(type); + return b != nullptr ? b->Get() : nullptr; } DBehavior* AddBehavior(PClass& type); - bool RemoveBehavior(const PClass& type); + bool RemoveBehavior(FName type); void TickBehaviors(); void MoveBehaviors(AActor& from); - void ClearBehaviors(); + void ClearBehaviors(PClass* type = nullptr); // Internal only, mostly for traveling. void UnlinkBehaviorsFromLevel(); void LinkBehaviorsToLevel(); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 5c7979c7c..c6ebe85e4 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -213,8 +213,8 @@ void AActor::EnableNetworking(const bool enable) size_t AActor::PropagateMark() { - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) GC::Mark(pair->Value); @@ -491,33 +491,34 @@ void DBehavior::OnDestroy() Super::OnDestroy(); } -bool AActor::RemoveBehavior(const PClass& type) +bool AActor::RemoveBehavior(FName type) { - if (Behaviors.CheckKey(type.TypeName)) + bool res = false; + auto b = Behaviors.CheckKey(type); + if (b != nullptr) { - auto b = Behaviors[type.TypeName]; - - Behaviors.Remove(type.TypeName); - if (b != nullptr && !(b->ObjectFlags & OF_EuthanizeMe)) + if (b->Get() != nullptr) { - b->Destroy(); - return true; + b->ForceGet()->Destroy(); + res = true; } + + Behaviors.Remove(type); } - return false; + return res; } static int RemoveBehavior(AActor* self, PClass* type) { - return self->RemoveBehavior(*type); + return self->RemoveBehavior(type->TypeName); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, RemoveBehavior, RemoveBehavior) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_NOT_NULL(type, DBehavior); - ACTION_RETURN_BOOL(self->RemoveBehavior(*type)); + ACTION_RETURN_BOOL(self->RemoveBehavior(type->TypeName)); } DBehavior* AActor::AddBehavior(PClass& type) @@ -525,7 +526,7 @@ DBehavior* AActor::AddBehavior(PClass& type) if (type.bAbstract || !type.IsDescendantOf(NAME_Behavior)) return nullptr; - auto b = FindBehavior(type); + auto b = FindBehavior(type.TypeName); if (b == nullptr) { b = dyn_cast(type.CreateNew()); @@ -542,7 +543,7 @@ DBehavior* AActor::AddBehavior(PClass& type) if (b->ObjectFlags & OF_EuthanizeMe) { - RemoveBehavior(type); + RemoveBehavior(type.TypeName); return nullptr; } } @@ -556,7 +557,7 @@ DBehavior* AActor::AddBehavior(PClass& type) if (b->ObjectFlags & OF_EuthanizeMe) { - RemoveBehavior(type); + RemoveBehavior(type.TypeName); return nullptr; } } @@ -582,12 +583,12 @@ void AActor::TickBehaviors() TArray toRemove = {}; TArray toTick = {}; - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) { - auto b = pair->Value; - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + auto b = pair->Value.Get(); + if (b == nullptr) { toRemove.Push(pair->Key); continue; @@ -598,9 +599,9 @@ void AActor::TickBehaviors() for (auto& b : toTick) { - if (b->Owner != this) + if ((b->ObjectFlags & OF_EuthanizeMe) || b->Owner != this) { - toRemove.Push(pair->Key); + toRemove.Push(b->GetClass()->TypeName); continue; } @@ -610,12 +611,12 @@ void AActor::TickBehaviors() VMCall(func, params, 1, nullptr, 0); if (b->ObjectFlags & OF_EuthanizeMe) - toRemove.Push(pair->Key); + toRemove.Push(b->GetClass()->TypeName); } } for (auto& type : toRemove) - RemoveBehavior(*PClass::FindClass(type)); + RemoveBehavior(type); } static void TickBehaviors(AActor* self) @@ -632,14 +633,14 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, TickBehaviors, TickBehaviors) static DBehavior* FindBehavior(AActor* self, PClass* type) { - return self->FindBehavior(*type); + return self->FindBehavior(type->TypeName); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, FindBehavior, FindBehavior) { PARAM_SELF_PROLOGUE(AActor); PARAM_CLASS_NOT_NULL(type, DBehavior); - ACTION_RETURN_OBJECT(self->FindBehavior(*type)); + ACTION_RETURN_OBJECT(self->FindBehavior(type->TypeName)); } void AActor::MoveBehaviors(AActor& from) @@ -653,12 +654,12 @@ void AActor::MoveBehaviors(AActor& from) // Clean up any empty behaviors that remained as well while // changing the owner. - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) { - auto b = pair->Value; - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + auto b = pair->Value.Get(); + if (b == nullptr) { toRemove.Push(pair->Key); continue; @@ -673,7 +674,7 @@ void AActor::MoveBehaviors(AActor& from) } for (auto& type : toRemove) - RemoveBehavior(*PClass::FindClass(type)); + RemoveBehavior(type); } static void MoveBehaviors(AActor* self, AActor* from) @@ -689,30 +690,37 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, MoveBehaviors, MoveBehaviors) return 0; } -void AActor::ClearBehaviors() +void AActor::ClearBehaviors(PClass* type) { TArray toRemove = {}; - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) - toRemove.Push(pair->Key); + { + auto b = pair->Value.Get(); + if (type == nullptr || b == nullptr || b->IsKindOf(type)) + toRemove.Push(pair->Key); + } for (auto& type : toRemove) - RemoveBehavior(*PClass::FindClass(type)); + RemoveBehavior(type); - Behaviors.Clear(); + // If not removing a specific type, clear whatever remains. + if (type == nullptr) + Behaviors.Clear(); } -static void ClearBehaviors(AActor* self) +static void ClearBehaviors(AActor* self, PClass* type) { - self->ClearBehaviors(); + self->ClearBehaviors(type); } DEFINE_ACTION_FUNCTION_NATIVE(AActor, ClearBehaviors, ClearBehaviors) { PARAM_SELF_PROLOGUE(AActor); - self->ClearBehaviors(); + PARAM_CLASS(type, DBehavior); + self->ClearBehaviors(type); return 0; } @@ -720,38 +728,38 @@ void AActor::UnlinkBehaviorsFromLevel() { TArray toRemove = {}; - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) { - auto b = pair->Value; - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + auto b = pair->Value.Get(); + if (b == nullptr) toRemove.Push(pair->Key); else b->Level->RemoveActorBehavior(*b); } for (auto& type : toRemove) - RemoveBehavior(*PClass::FindClass(type)); + RemoveBehavior(type); } void AActor::LinkBehaviorsToLevel() { TArray toRemove = {}; - TMap::Iterator it = { Behaviors }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { Behaviors }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) { - auto b = pair->Value; - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + auto b = pair->Value.Get(); + if (b == nullptr) toRemove.Push(pair->Key); else Level->AddActorBehavior(*b); } for (auto& type : toRemove) - RemoveBehavior(*PClass::FindClass(type)); + RemoveBehavior(type); } //========================================================================== diff --git a/src/scripting/vmiterators.cpp b/src/scripting/vmiterators.cpp index 7762d176b..ec053e5fe 100644 --- a/src/scripting/vmiterators.cpp +++ b/src/scripting/vmiterators.cpp @@ -400,21 +400,21 @@ class DBehaviorIterator : public DObject { DECLARE_ABSTRACT_CLASS(DBehaviorIterator, DObject) size_t _index; - TArray _behaviors; + TArray> _behaviors; public: DBehaviorIterator(const AActor& mobj, PClass* type) { - TMap::ConstIterator it = { mobj.Behaviors }; - TMap::ConstPair* pair = nullptr; + TMap>::ConstIterator it = { mobj.Behaviors }; + TMap>::ConstPair* pair = nullptr; while (it.NextPair(pair)) { - auto b = pair->Value; - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) + auto b = pair->Value.Get(); + if (b == nullptr) continue; if (type == nullptr || b->IsKindOf(type)) - _behaviors.Push(b); + _behaviors.Push(pair->Value); } Reinit(); @@ -424,14 +424,11 @@ public: { for (auto& b : level.ActorBehaviors) { - if (b == nullptr || (b->ObjectFlags & OF_EuthanizeMe)) - continue; - if (ownerType != nullptr && !b->Owner->IsKindOf(ownerType)) continue; if (type == nullptr || b->IsKindOf(type)) - _behaviors.Push(b); + _behaviors.Push(MakeObjPtr(b)); } Reinit(); @@ -439,10 +436,14 @@ public: DBehavior* Next() { - if (_index >= _behaviors.Size()) - return nullptr; + while (_index < _behaviors.Size()) + { + auto b = _behaviors[_index++].Get(); + if (b != nullptr) + return b; + } - return _behaviors[_index++]; + return nullptr; } void Reinit() { _index = 0u; } diff --git a/src/serializer_doom.cpp b/src/serializer_doom.cpp index 566aa3164..a950a5d8e 100644 --- a/src/serializer_doom.cpp +++ b/src/serializer_doom.cpp @@ -226,17 +226,21 @@ FSerializer& FDoomSerializer::StatePointer(const char* key, void* ptraddr, bool } -FSerializer& Serialize(FSerializer& arc, const char* key, TMap& value, TMap* def) +FSerializer& Serialize(FSerializer& arc, const char* key, TMap>& value, TMap>* def) { if (!arc.BeginObject(key)) return arc; if (arc.isWriting()) { - TMap::Iterator it = { value }; - TMap::Pair* pair = nullptr; + TMap>::Iterator it = { value }; + TMap>::Pair* pair = nullptr; while (it.NextPair(pair)) - arc(pair->Key.GetChars(), pair->Value); + { + auto b = pair->Value.Get(); + if (b != nullptr) + arc(pair->Key.GetChars(), b); + } } else { diff --git a/src/serializer_doom.h b/src/serializer_doom.h index 4abc9fb19..1ce88c0e0 100644 --- a/src/serializer_doom.h +++ b/src/serializer_doom.h @@ -44,7 +44,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, ticcmd_t &sid, ticcmd_ FSerializer &Serialize(FSerializer &arc, const char *key, usercmd_t &cmd, usercmd_t *def); FSerializer &Serialize(FSerializer &arc, const char *key, FInterpolator &rs, FInterpolator *def); FSerializer& Serialize(FSerializer& arc, const char* key, struct FStandaloneAnimation& value, struct FStandaloneAnimation* defval); -FSerializer& Serialize(FSerializer& arc, const char* key, TMap& value, TMap* def); +FSerializer& Serialize(FSerializer& arc, const char* key, TMap>& value, TMap>* def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, FPolyObj *&value, FPolyObj **defval); template<> FSerializer &Serialize(FSerializer &arc, const char *key, sector_t *&value, sector_t **defval); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 5d24f34b0..1471dec61 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -522,7 +522,7 @@ class Actor : Thinker native native bool RemoveBehavior(class type); native Behavior AddBehavior(class type); native void TickBehaviors(); - native void ClearBehaviors(); + native void ClearBehaviors(class type = null); native void MoveBehaviors(Actor from); native clearscope bool isFrozen() const;