mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-31 04:20: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);
|
assert(q != NULL);
|
||||||
return *q;
|
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()
|
T operator->() throw()
|
||||||
{
|
{
|
||||||
return GC::ReadBarrier(pp);
|
return GC::ReadBarrier(pp);
|
||||||
|
|
|
@ -1971,6 +1971,10 @@ void FLevelLocals::Mark()
|
||||||
GC::Mark(SpotState);
|
GC::Mark(SpotState);
|
||||||
GC::Mark(FraggleScriptThinker);
|
GC::Mark(FraggleScriptThinker);
|
||||||
canvasTextureInfo.Mark();
|
canvasTextureInfo.Mark();
|
||||||
|
for (auto &c : CorpseQueue)
|
||||||
|
{
|
||||||
|
GC::Mark(c);
|
||||||
|
}
|
||||||
for (auto &s : sectorPortals)
|
for (auto &s : sectorPortals)
|
||||||
{
|
{
|
||||||
GC::Mark(s.mSkybox);
|
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)
|
CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||||
{
|
{
|
||||||
if (self > 0)
|
if (self > 0)
|
||||||
{
|
{
|
||||||
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
|
auto &corpsequeue = level.CorpseQueue;
|
||||||
DCorpsePointer *first = iterator.Next ();
|
while (corpsequeue.Size() > (unsigned)self)
|
||||||
while (first != NULL && first->Count > (uint32_t)self)
|
|
||||||
{
|
{
|
||||||
DCorpsePointer *next = iterator.Next ();
|
AActor *corpse = corpsequeue[0];
|
||||||
first->Destroy ();
|
if (corpse) corpse->Destroy();
|
||||||
first = next;
|
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
|
// throw another corpse on the queue
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
|
DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
|
||||||
|
@ -199,8 +111,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse)
|
||||||
|
|
||||||
if (sv_corpsequeuesize > 0)
|
if (sv_corpsequeuesize > 0)
|
||||||
{
|
{
|
||||||
auto p = Create<DCorpsePointer> (self);
|
auto &corpsequeue = level.CorpseQueue;
|
||||||
p->Queue();
|
while (corpsequeue.Size() >= (unsigned)sv_corpsequeuesize)
|
||||||
|
{
|
||||||
|
AActor *corpse = corpsequeue[0];
|
||||||
|
if (corpse) corpse->Destroy();
|
||||||
|
corpsequeue.Delete(0);
|
||||||
|
}
|
||||||
|
corpsequeue.Push(self);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -210,17 +128,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeQueueCorpse)
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
PARAM_SELF_PROLOGUE(AActor);
|
||||||
|
|
||||||
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
|
auto &corpsequeue = level.CorpseQueue;
|
||||||
DCorpsePointer *corpsePtr;
|
auto index = corpsequeue.FindEx([=](auto &element) { return element == self; });
|
||||||
|
if (index < corpsequeue.Size())
|
||||||
while ((corpsePtr = iterator.Next()) != NULL)
|
|
||||||
{
|
{
|
||||||
if (corpsePtr->Corpse == self)
|
corpsequeue.Delete(index);
|
||||||
{
|
|
||||||
corpsePtr->Corpse = NULL;
|
|
||||||
corpsePtr->Destroy ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,7 +594,7 @@ void DBaseStatusBar::Tick ()
|
||||||
for (size_t i = 0; i < countof(Messages); ++i)
|
for (size_t i = 0; i < countof(Messages); ++i)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *msg = Messages[i];
|
DHUDMessageBase *msg = Messages[i];
|
||||||
DHUDMessageBase **prev = &Messages[i];
|
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
||||||
|
|
||||||
while (msg)
|
while (msg)
|
||||||
{
|
{
|
||||||
|
@ -657,7 +657,7 @@ void DBaseStatusBar::CallTick()
|
||||||
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
|
void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *old = NULL;
|
DHUDMessageBase *old = NULL;
|
||||||
DHUDMessageBase **prev;
|
TObjPtr<DHUDMessageBase *>*prev;
|
||||||
|
|
||||||
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
|
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
|
||||||
if (old != NULL)
|
if (old != NULL)
|
||||||
|
@ -698,7 +698,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (DHUDMessageBase *msg)
|
||||||
for (size_t i = 0; i < countof(Messages); ++i)
|
for (size_t i = 0; i < countof(Messages); ++i)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *probe = Messages[i];
|
DHUDMessageBase *probe = Messages[i];
|
||||||
DHUDMessageBase **prev = &Messages[i];
|
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
||||||
|
|
||||||
while (probe && probe != msg)
|
while (probe && probe != msg)
|
||||||
{
|
{
|
||||||
|
@ -720,7 +720,7 @@ DHUDMessageBase *DBaseStatusBar::DetachMessage (uint32_t id)
|
||||||
for (size_t i = 0; i < countof(Messages); ++i)
|
for (size_t i = 0; i < countof(Messages); ++i)
|
||||||
{
|
{
|
||||||
DHUDMessageBase *probe = Messages[i];
|
DHUDMessageBase *probe = Messages[i];
|
||||||
DHUDMessageBase **prev = &Messages[i];
|
TObjPtr<DHUDMessageBase *>*prev = &Messages[i];
|
||||||
|
|
||||||
while (probe && probe->SBarID != id)
|
while (probe && probe->SBarID != id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -976,6 +976,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
|
||||||
("level.bodyqueslot", level.bodyqueslot)
|
("level.bodyqueslot", level.bodyqueslot)
|
||||||
("level.spawnindex", level.spawnindex)
|
("level.spawnindex", level.spawnindex)
|
||||||
.Array("level.bodyque", level.bodyque, level.BODYQUESIZE)
|
.Array("level.bodyque", level.bodyque, level.BODYQUESIZE)
|
||||||
|
("level.corpsequeue", level.CorpseQueue)
|
||||||
("level.spotstate", level.SpotState)
|
("level.spotstate", level.SpotState)
|
||||||
("level.fragglethinker", level.FraggleScriptThinker);
|
("level.fragglethinker", level.FraggleScriptThinker);
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,7 @@ void FLevelLocals::ClearLevelData()
|
||||||
ClearPortals();
|
ClearPortals();
|
||||||
|
|
||||||
SpotState = nullptr;
|
SpotState = nullptr;
|
||||||
|
CorpseQueue.Clear();
|
||||||
canvasTextureInfo.EmptyList();
|
canvasTextureInfo.EmptyList();
|
||||||
sections.Clear();
|
sections.Clear();
|
||||||
segs.Clear();
|
segs.Clear();
|
||||||
|
|
Loading…
Reference in a new issue