mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 14:52:01 +00:00
- simplified the event code by removing the priority queue layer.
We do not need that compatibility handling so the high level code can use the multiset directly.
This commit is contained in:
parent
b97f12a2eb
commit
71e70f8d15
5 changed files with 51 additions and 270 deletions
|
@ -1,13 +1,13 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 Nuke.YKT
|
||||
Copyright (C) 2020 Christoph Oelckers & Mitchell Richters
|
||||
|
||||
This file is part of NBlood.
|
||||
This file is part of Raze.
|
||||
|
||||
NBlood is free software; you can redistribute it and/or
|
||||
Raze is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
|
|
@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <set>
|
||||
#include "build.h"
|
||||
#include "common_game.h"
|
||||
|
||||
|
@ -34,7 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "eventq.h"
|
||||
#include "globals.h"
|
||||
#include "loadsave.h"
|
||||
#include "pqueue.h"
|
||||
#include "triggers.h"
|
||||
#include "view.h"
|
||||
#include "nnexts.h"
|
||||
|
@ -42,41 +42,49 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
||||
struct queueItem
|
||||
{
|
||||
uint32_t priority;
|
||||
EVENT data;
|
||||
|
||||
bool operator<(const queueItem& other) const
|
||||
{
|
||||
return priority < other.priority;
|
||||
}
|
||||
};
|
||||
|
||||
class EventQueue
|
||||
{
|
||||
public:
|
||||
PriorityQueue<EVENT>* PQueue;
|
||||
EventQueue()
|
||||
{
|
||||
PQueue = NULL;
|
||||
}
|
||||
~EventQueue()
|
||||
{
|
||||
if (PQueue) delete PQueue;
|
||||
}
|
||||
std::multiset<queueItem> set;
|
||||
|
||||
bool IsNotEmpty(unsigned int nTime)
|
||||
{
|
||||
return PQueue->Size() > 0 && nTime >= PQueue->LowestPriority();
|
||||
return set.size() > 0 && nTime >= set.begin()->priority;
|
||||
}
|
||||
EVENT ERemove(void)
|
||||
{
|
||||
return PQueue->Remove();
|
||||
assert(set.size() > 0);
|
||||
EVENT data = set.begin()->data;
|
||||
set.erase(set.begin());
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class func>
|
||||
void Kill(func pMatch)
|
||||
{
|
||||
for (auto i = set.begin(); i != set.end();)
|
||||
{
|
||||
if (pMatch(i->data))
|
||||
i = set.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
void Kill(int, int);
|
||||
void Kill(int, int, CALLBACK_ID);
|
||||
};
|
||||
|
||||
EventQueue eventQ;
|
||||
void EventQueue::Kill(int a1, int a2)
|
||||
{
|
||||
PQueue->Kill([=](EVENT nItem)->bool {return nItem.index == a1 && nItem.type == a2; });
|
||||
}
|
||||
|
||||
void EventQueue::Kill(int a1, int a2, CALLBACK_ID a3)
|
||||
{
|
||||
EVENT evn = { (unsigned int)a1, (unsigned int)a2, kCmdCallback, (unsigned int)a3 };
|
||||
PQueue->Kill([=](EVENT nItem)->bool {return !memcmp(&nItem, &evn, sizeof(EVENT)); });
|
||||
}
|
||||
|
||||
RXBUCKET rxBucket[kChannelMax+1];
|
||||
|
||||
|
@ -265,13 +273,7 @@ unsigned short bucketHead[1024+1];
|
|||
|
||||
void evInit(void)
|
||||
{
|
||||
if (eventQ.PQueue)
|
||||
delete eventQ.PQueue;
|
||||
if (VanillaMode())
|
||||
eventQ.PQueue = new VanillaPriorityQueue<EVENT>();
|
||||
else
|
||||
eventQ.PQueue = new StdPriorityQueue<EVENT>();
|
||||
eventQ.PQueue->Clear();
|
||||
eventQ.set.clear();
|
||||
int nCount = 0;
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
|
@ -501,7 +503,7 @@ void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command) {
|
|||
evn.index = nIndex;
|
||||
evn.type = nType;
|
||||
evn.cmd = command;
|
||||
eventQ.PQueue->Insert(gFrameClock+nDelta, evn);
|
||||
eventQ.set.insert({ gFrameClock + nDelta, evn });
|
||||
}
|
||||
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback) {
|
||||
|
@ -510,23 +512,11 @@ void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback) {
|
|||
evn.type = nType;
|
||||
evn.cmd = kCmdCallback;
|
||||
evn.funcID = callback;
|
||||
eventQ.PQueue->Insert(gFrameClock+nDelta, evn);
|
||||
eventQ.set.insert({ gFrameClock + nDelta, evn });
|
||||
}
|
||||
|
||||
void evProcess(unsigned int nTime)
|
||||
{
|
||||
#if 0
|
||||
while (1)
|
||||
{
|
||||
// Inlined?
|
||||
char bDone;
|
||||
if (eventQ.fNodeCount > 0 && nTime >= eventQ.queueItems[1])
|
||||
bDone = 1;
|
||||
else
|
||||
bDone = 0;
|
||||
if (!bDone)
|
||||
break;
|
||||
#endif
|
||||
while(eventQ.IsNotEmpty(nTime))
|
||||
{
|
||||
EVENT event = eventQ.ERemove();
|
||||
|
@ -556,12 +546,13 @@ void evProcess(unsigned int nTime)
|
|||
|
||||
void evKill(int a1, int a2)
|
||||
{
|
||||
eventQ.Kill(a1, a2);
|
||||
eventQ.Kill([=](EVENT nItem)->bool {return nItem.index == a1 && nItem.type == a2; });
|
||||
}
|
||||
|
||||
void evKill(int a1, int a2, CALLBACK_ID a3)
|
||||
{
|
||||
eventQ.Kill(a1, a2, a3);
|
||||
EVENT evn = { (unsigned int)a1, (unsigned int)a2, kCmdCallback, (unsigned int)a3 };
|
||||
eventQ.Kill([=](EVENT nItem)->bool {return !memcmp(&nItem, &evn, sizeof(EVENT)); });
|
||||
}
|
||||
|
||||
class EventQLoadSave : public LoadSave
|
||||
|
@ -573,22 +564,14 @@ public:
|
|||
|
||||
void EventQLoadSave::Load()
|
||||
{
|
||||
if (eventQ.PQueue)
|
||||
delete eventQ.PQueue;
|
||||
Read(&eventQ, sizeof(eventQ));
|
||||
if (VanillaMode())
|
||||
eventQ.PQueue = new VanillaPriorityQueue<EVENT>();
|
||||
else
|
||||
eventQ.PQueue = new StdPriorityQueue<EVENT>();
|
||||
eventQ.set.clear();
|
||||
int nEvents;
|
||||
Read(&nEvents, sizeof(nEvents));
|
||||
for (int i = 0; i < nEvents; i++)
|
||||
{
|
||||
EVENT event = {};
|
||||
unsigned int eventtime;
|
||||
Read(&eventtime, sizeof(eventtime));
|
||||
queueItem event = {};
|
||||
Read(&event, sizeof(event));
|
||||
eventQ.PQueue->Insert(eventtime, event);
|
||||
eventQ.set.insert(event);
|
||||
}
|
||||
Read(rxBucket, sizeof(rxBucket));
|
||||
Read(bucketHead, sizeof(bucketHead));
|
||||
|
@ -596,22 +579,11 @@ void EventQLoadSave::Load()
|
|||
|
||||
void EventQLoadSave::Save()
|
||||
{
|
||||
EVENT events[1024];
|
||||
unsigned int eventstime[1024];
|
||||
Write(&eventQ, sizeof(eventQ));
|
||||
int nEvents = eventQ.PQueue->Size();
|
||||
int nEvents = eventQ.set.size();
|
||||
Write(&nEvents, sizeof(nEvents));
|
||||
for (int i = 0; i < nEvents; i++)
|
||||
for (auto &item : eventQ.set)
|
||||
{
|
||||
eventstime[i] = eventQ.PQueue->LowestPriority();
|
||||
events[i] = eventQ.ERemove();
|
||||
Write(&eventstime[i], sizeof(eventstime[i]));
|
||||
Write(&events[i], sizeof(events[i]));
|
||||
}
|
||||
assert(eventQ.PQueue->Size() == 0);
|
||||
for (int i = 0; i < nEvents; i++)
|
||||
{
|
||||
eventQ.PQueue->Insert(eventstime[i], events[i]);
|
||||
Write(&item, sizeof(item));
|
||||
}
|
||||
Write(rxBucket, sizeof(rxBucket));
|
||||
Write(bucketHead, sizeof(bucketHead));
|
||||
|
|
|
@ -465,7 +465,7 @@ void LoadSave::Read(void *pData, int nSize)
|
|||
I_Error("Error reading save file.");
|
||||
}
|
||||
|
||||
void LoadSave::Write(void *pData, int nSize)
|
||||
void LoadSave::Write(const void *pData, int nSize)
|
||||
{
|
||||
dword_27AA38 += nSize;
|
||||
dword_27AA3C += nSize;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
virtual void Save(void);
|
||||
virtual void Load(void);
|
||||
void Read(void *, int);
|
||||
void Write(void *, int);
|
||||
void Write(const void *, int);
|
||||
};
|
||||
|
||||
void LoadSaveSetup(void);
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 Nuke.YKT
|
||||
|
||||
This file is part of NBlood.
|
||||
|
||||
NBlood is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include <functional>
|
||||
#include "common_game.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
enum { kPQueueSize = 1024 };
|
||||
|
||||
template <typename T> struct queueItem
|
||||
{
|
||||
uint32_t TotalKills; // priority
|
||||
T Kills; // data
|
||||
bool operator>(const queueItem& other) const
|
||||
{
|
||||
return TotalKills > other.TotalKills;
|
||||
}
|
||||
bool operator<(const queueItem& other) const
|
||||
{
|
||||
return TotalKills < other.TotalKills;
|
||||
}
|
||||
bool operator>=(const queueItem& other) const
|
||||
{
|
||||
return TotalKills >= other.TotalKills;
|
||||
}
|
||||
bool operator<=(const queueItem& other) const
|
||||
{
|
||||
return TotalKills <= other.TotalKills;
|
||||
}
|
||||
bool operator!=(const queueItem& other) const
|
||||
{
|
||||
return TotalKills != other.TotalKills;
|
||||
}
|
||||
bool operator==(const queueItem& other) const
|
||||
{
|
||||
return TotalKills == other.TotalKills;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class PriorityQueue
|
||||
{
|
||||
public:
|
||||
virtual ~PriorityQueue() {}
|
||||
virtual uint32_t Size(void) = 0;
|
||||
virtual void Clear(void) = 0;
|
||||
virtual void Insert(uint32_t, T) = 0;
|
||||
virtual T Remove(void) = 0;
|
||||
virtual uint32_t LowestPriority(void) = 0;
|
||||
virtual void Kill(std::function<bool(T)> pMatch) = 0;
|
||||
};
|
||||
|
||||
template<typename T> class VanillaPriorityQueue : public PriorityQueue<T>
|
||||
{
|
||||
public:
|
||||
queueItem<T> queueItems[kPQueueSize + 1];
|
||||
uint32_t fNodeCount; // at2008
|
||||
~VanillaPriorityQueue() {}
|
||||
uint32_t Size(void) { return fNodeCount; };
|
||||
void Clear(void)
|
||||
{
|
||||
fNodeCount = 0;
|
||||
memset(queueItems, 0, sizeof(queueItems));
|
||||
}
|
||||
void Upheap(void)
|
||||
{
|
||||
queueItem<T> item = queueItems[fNodeCount];
|
||||
queueItems[0].TotalKills = 0;
|
||||
uint32_t x = fNodeCount;
|
||||
while (queueItems[x>>1] > item)
|
||||
{
|
||||
queueItems[x] = queueItems[x>>1];
|
||||
x >>= 1;
|
||||
}
|
||||
queueItems[x] = item;
|
||||
}
|
||||
void Downheap(uint32_t n)
|
||||
{
|
||||
queueItem<T> item = queueItems[n];
|
||||
while (fNodeCount/2 >= n)
|
||||
{
|
||||
uint32_t t = n*2;
|
||||
if (t < fNodeCount && queueItems[t] > queueItems[t+1])
|
||||
t++;
|
||||
if (item <= queueItems[t])
|
||||
break;
|
||||
queueItems[n] = queueItems[t];
|
||||
n = t;
|
||||
}
|
||||
queueItems[n] = item;
|
||||
}
|
||||
void Delete(uint32_t k)
|
||||
{
|
||||
assert(k <= fNodeCount);
|
||||
queueItems[k] = queueItems[fNodeCount--];
|
||||
Downheap(k);
|
||||
}
|
||||
void Insert(uint32_t a1, T a2)
|
||||
{
|
||||
assert(fNodeCount < kPQueueSize);
|
||||
fNodeCount++;
|
||||
queueItems[fNodeCount].TotalKills = a1;
|
||||
queueItems[fNodeCount].Kills = a2;
|
||||
Upheap();
|
||||
}
|
||||
T Remove(void)
|
||||
{
|
||||
T data = queueItems[1].Kills;
|
||||
queueItems[1] = queueItems[fNodeCount--];
|
||||
Downheap(1);
|
||||
return data;
|
||||
}
|
||||
uint32_t LowestPriority(void)
|
||||
{
|
||||
assert(fNodeCount > 0);
|
||||
return queueItems[1].TotalKills;
|
||||
}
|
||||
void Kill(std::function<bool(T)> pMatch)
|
||||
{
|
||||
for (unsigned int i = 1; i <= fNodeCount;)
|
||||
{
|
||||
if (pMatch(queueItems[i].Kills))
|
||||
Delete(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class StdPriorityQueue : public PriorityQueue<T>
|
||||
{
|
||||
public:
|
||||
std::multiset<queueItem<T>> stdQueue;
|
||||
~StdPriorityQueue()
|
||||
{
|
||||
stdQueue.clear();
|
||||
}
|
||||
uint32_t Size(void) { return stdQueue.size(); };
|
||||
void Clear(void)
|
||||
{
|
||||
stdQueue.clear();
|
||||
}
|
||||
void Insert(uint32_t nPriority, T data)
|
||||
{
|
||||
stdQueue.insert({ nPriority, data });
|
||||
}
|
||||
T Remove(void)
|
||||
{
|
||||
assert(stdQueue.size() > 0);
|
||||
T data = stdQueue.begin()->Kills;
|
||||
stdQueue.erase(stdQueue.begin());
|
||||
return data;
|
||||
}
|
||||
uint32_t LowestPriority(void)
|
||||
{
|
||||
return stdQueue.begin()->TotalKills;
|
||||
}
|
||||
void Kill(std::function<bool(T)> pMatch)
|
||||
{
|
||||
for (auto i = stdQueue.begin(); i != stdQueue.end();)
|
||||
{
|
||||
if (pMatch(i->Kills))
|
||||
i = stdQueue.erase(i);
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
END_BLD_NS
|
Loading…
Reference in a new issue