mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 12:32:34 +00:00
- made the corpse queue a simple array in FLevelLocals.
I have to wonder why it had to use such a complicated implementation that provided no advantages whatsoever. The new code is just 1/5th of the old one's size and much closer to Hexen's original implementation which also was a simple array but with no means to resize the queue.
This commit is contained in:
parent
dab68184f5
commit
a0ad4ea193
6 changed files with 27 additions and 116 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<AActor*> 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<DCorpsePointer> 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<DCorpsePointer> 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<DCorpsePointer> 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<DCorpsePointer> (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<DCorpsePointer> 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;
|
||||
}
|
||||
|
|
|
@ -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<DHUDMessageBase *>*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<DHUDMessageBase *>*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<DHUDMessageBase *>*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<DHUDMessageBase *>*prev = &Messages[i];
|
||||
|
||||
while (probe && probe->SBarID != id)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -275,6 +275,7 @@ void FLevelLocals::ClearLevelData()
|
|||
ClearPortals();
|
||||
|
||||
SpotState = nullptr;
|
||||
CorpseQueue.Clear();
|
||||
canvasTextureInfo.EmptyList();
|
||||
sections.Clear();
|
||||
segs.Clear();
|
||||
|
|
Loading…
Reference in a new issue