diff --git a/src/dobjgc.h b/src/dobjgc.h index 82db1de20..9fbad404e 100644 --- a/src/dobjgc.h +++ b/src/dobjgc.h @@ -190,13 +190,6 @@ public: assert(q != NULL); return *q; } - T *operator&() throw() - { - // Does not perform a read barrier. The only real use for this is with - // the DECLARE_POINTER macro, where a read barrier would be a very bad - // thing. - return &pp; - } T operator->() throw() { return GC::ReadBarrier(pp); diff --git a/src/g_level.cpp b/src/g_level.cpp index 23fc0cca6..11ed6c0c4 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1971,6 +1971,10 @@ void FLevelLocals::Mark() GC::Mark(SpotState); GC::Mark(FraggleScriptThinker); canvasTextureInfo.Mark(); + for (auto &c : CorpseQueue) + { + GC::Mark(c); + } for (auto &s : sectorPortals) { GC::Mark(s.mSkybox); diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index a8fc47fe0..99814cdf8 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -88,109 +88,21 @@ void A_Unblock(AActor *self, bool drop) // //---------------------------------------------------------------------------- -// Corpse queue for monsters - this should be saved out - -class DCorpsePointer : public DThinker -{ - DECLARE_CLASS (DCorpsePointer, DThinker) - HAS_OBJECT_POINTERS -public: - DCorpsePointer (AActor *ptr); - void Queue(); - void OnDestroy() override; - void Serialize(FSerializer &arc); - TObjPtr Corpse; - uint32_t Count; // Only the first corpse pointer's count is valid. -private: - DCorpsePointer () {} -}; - -IMPLEMENT_CLASS(DCorpsePointer, false, true) - -IMPLEMENT_POINTERS_START(DCorpsePointer) - IMPLEMENT_POINTER(Corpse) -IMPLEMENT_POINTERS_END - CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO) { if (self > 0) { - TThinkerIterator iterator (STAT_CORPSEPOINTER); - DCorpsePointer *first = iterator.Next (); - while (first != NULL && first->Count > (uint32_t)self) + auto &corpsequeue = level.CorpseQueue; + while (corpsequeue.Size() > (unsigned)self) { - DCorpsePointer *next = iterator.Next (); - first->Destroy (); - first = next; + AActor *corpse = corpsequeue[0]; + if (corpse) corpse->Destroy(); + corpsequeue.Delete(0); } } } -DCorpsePointer::DCorpsePointer(AActor *ptr) - : DThinker(STAT_CORPSEPOINTER), Corpse(ptr) -{ - Count = 0; -} - -void DCorpsePointer::Queue() -{ - // Thinkers are added to the end of their respective lists, so - // the first thinker in the list is the oldest one. - TThinkerIterator iterator (STAT_CORPSEPOINTER); - DCorpsePointer *first = iterator.Next (); - - if (first != nullptr) - { - if (first != this) - { - if (first->Count >= (uint32_t)sv_corpsequeuesize) - { - DCorpsePointer *next = iterator.Next(); - first->Destroy(); - first = next; - } - } - ++first->Count; - } -} - -void DCorpsePointer::OnDestroy () -{ - // Store the count of corpses in the first thinker in the list - TThinkerIterator iterator (STAT_CORPSEPOINTER); - DCorpsePointer *first = iterator.Next (); - - // During a serialization unwind the thinker list won't be available. - if (first != nullptr) - { - int prevCount = first->Count; - - if (first == this) - { - first = iterator.Next(); - } - - if (first != NULL) - { - first->Count = prevCount - 1; - } - - } - if (Corpse != NULL) - { - Corpse->Destroy(); - } - Super::OnDestroy(); -} - -void DCorpsePointer::Serialize(FSerializer &arc) -{ - Super::Serialize(arc); - arc("corpse", Corpse) - ("count", Count); -} - // throw another corpse on the queue DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) @@ -199,8 +111,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) if (sv_corpsequeuesize > 0) { - auto p = Create (self); - p->Queue(); + auto &corpsequeue = level.CorpseQueue; + while (corpsequeue.Size() >= (unsigned)sv_corpsequeuesize) + { + AActor *corpse = corpsequeue[0]; + if (corpse) corpse->Destroy(); + corpsequeue.Delete(0); + } + corpsequeue.Push(self); } return 0; } @@ -210,17 +128,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse) { PARAM_SELF_PROLOGUE(AActor); - TThinkerIterator iterator (STAT_CORPSEPOINTER); - DCorpsePointer *corpsePtr; - - while ((corpsePtr = iterator.Next()) != NULL) + auto &corpsequeue = level.CorpseQueue; + auto index = corpsequeue.FindEx([=](auto &element) { return element == self; }); + if (index < corpsequeue.Size()) { - if (corpsePtr->Corpse == self) - { - corpsePtr->Corpse = NULL; - corpsePtr->Destroy (); - return 0; - } + corpsequeue.Delete(index); } return 0; } diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 12b66bf88..eec393fd2 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -594,7 +594,7 @@ void DBaseStatusBar::Tick () for (size_t i = 0; i < countof(Messages); ++i) { DHUDMessageBase *msg = Messages[i]; - DHUDMessageBase **prev = &Messages[i]; + TObjPtr*prev = &Messages[i]; while (msg) { @@ -657,7 +657,7 @@ void DBaseStatusBar::CallTick() void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer) { DHUDMessageBase *old = NULL; - DHUDMessageBase **prev; + TObjPtr*prev; old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id); if (old != NULL) @@ -698,7 +698,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg) for (size_t i = 0; i < countof(Messages); ++i) { DHUDMessageBase *probe = Messages[i]; - DHUDMessageBase **prev = &Messages[i]; + TObjPtr*prev = &Messages[i]; while (probe && probe != msg) { @@ -720,7 +720,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id) for (size_t i = 0; i < countof(Messages); ++i) { DHUDMessageBase *probe = Messages[i]; - DHUDMessageBase **prev = &Messages[i]; + TObjPtr*prev = &Messages[i]; while (probe && probe->SBarID != id) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index d63c9f5e4..67e5ca4a5 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -976,6 +976,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) ("level.bodyqueslot", level.bodyqueslot) ("level.spawnindex", level.spawnindex) .Array("level.bodyque", level.bodyque, level.BODYQUESIZE) + ("level.corpsequeue", level.CorpseQueue) ("level.spotstate", level.SpotState) ("level.fragglethinker", level.FraggleScriptThinker); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 6ffb35af8..d2d76c965 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -275,6 +275,7 @@ void FLevelLocals::ClearLevelData() ClearPortals(); SpotState = nullptr; + CorpseQueue.Clear(); canvasTextureInfo.EmptyList(); sections.Clear(); segs.Clear();