mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-19 15:40:58 +00:00
- simplified the event management further and added a JSON serializer for it.
This commit is contained in:
parent
5f54eac297
commit
1535182577
6 changed files with 678 additions and 573 deletions
|
@ -71,6 +71,7 @@ struct GameInterface : ::GameInterface
|
|||
{
|
||||
const char* Name() override { return "Blood"; }
|
||||
void app_init() override;
|
||||
void SerializeGameState(FSerializer& arc) override;
|
||||
void loadPalette() override;
|
||||
void clearlocalinputstate() override;
|
||||
bool GenerateSavePic() override;
|
||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxXSprites = 16384,
|
||||
|
@ -31,6 +32,17 @@ enum
|
|||
kMaxXSectors = 512
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kAttrMove = 0x0001, // is affected by movement physics
|
||||
kAttrGravity = 0x0002, // is affected by gravity
|
||||
kAttrFalling = 0x0004, // in z motion
|
||||
kAttrAiming = 0x0008,
|
||||
kAttrRespawn = 0x0010,
|
||||
kAttrFree = 0x0020,
|
||||
kAttrSmoke = 0x0100, // receives tsprite smoke/steam
|
||||
};
|
||||
|
||||
|
||||
// by NoOne: functions to quckly check range of specifical arrays
|
||||
inline bool xspriRangeIsFine(int nXindex) {
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 Nuke.YKT
|
||||
Copyright (C) 2020 Christoph Oelckers
|
||||
|
||||
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.
|
||||
|
||||
|
@ -21,109 +22,76 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "ns.h" // Must come before everything else!
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ns.h"
|
||||
#include <set>
|
||||
#include "build.h"
|
||||
#include "printf.h"
|
||||
#include "common_game.h"
|
||||
|
||||
#include "callback.h"
|
||||
#include "db.h"
|
||||
#include "eventq.h"
|
||||
#include "globals.h"
|
||||
#include "loadsave.h"
|
||||
#include "db.h"
|
||||
#include "levels.h"
|
||||
#include "triggers.h"
|
||||
#include "view.h"
|
||||
#include "nnexts.h"
|
||||
#include "secrets.h"
|
||||
#include "serializer.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
||||
struct queueItem
|
||||
{
|
||||
uint32_t priority;
|
||||
EVENT data;
|
||||
const int kMaxID = 1024;
|
||||
RXBUCKET rxBucket[kChannelMax];
|
||||
unsigned short bucketHead[kMaxID + 1];
|
||||
static int bucketCount;
|
||||
static std::multiset<EVENT> queue;
|
||||
|
||||
bool operator<(const queueItem& other) const
|
||||
{
|
||||
return priority < other.priority;
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class EventQueue
|
||||
static int GetBucketChannel(const RXBUCKET* pBucket)
|
||||
{
|
||||
public:
|
||||
std::multiset<queueItem> set;
|
||||
|
||||
bool IsNotEmpty(unsigned int nTime)
|
||||
int nXIndex;
|
||||
switch (pBucket->type)
|
||||
{
|
||||
return set.size() > 0 && nTime >= set.begin()->priority;
|
||||
}
|
||||
EVENT ERemove(void)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
EventQueue eventQ;
|
||||
|
||||
RXBUCKET rxBucket[kChannelMax+1];
|
||||
|
||||
int GetBucketChannel(const RXBUCKET *pRX)
|
||||
{
|
||||
switch (pRX->type) {
|
||||
case 6: {
|
||||
int nIndex = pRX->index;
|
||||
int nXIndex = sector[nIndex].extra;
|
||||
case SS_SECTOR:
|
||||
nXIndex = sector[pBucket->index].extra;
|
||||
assert(nXIndex > 0);
|
||||
return xsector[nXIndex].rxID;
|
||||
}
|
||||
case 0: {
|
||||
int nIndex = pRX->index;
|
||||
int nXIndex = wall[nIndex].extra;
|
||||
|
||||
case SS_WALL:
|
||||
nXIndex = wall[pBucket->index].extra;
|
||||
assert(nXIndex > 0);
|
||||
return xwall[nXIndex].rxID;
|
||||
}
|
||||
case 3: {
|
||||
int nIndex = pRX->index;
|
||||
int nXIndex = sprite[nIndex].extra;
|
||||
|
||||
case SS_SPRITE:
|
||||
nXIndex = sprite[pBucket->index].extra;
|
||||
assert(nXIndex > 0);
|
||||
return xsprite[nXIndex].rxID;
|
||||
}
|
||||
}
|
||||
|
||||
Printf(PRINT_HIGH, "Unexpected rxBucket type %d", pBucket->type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int CompareChannels(const void *a, const void *b)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static int CompareChannels(const RXBUCKET* ref1, const RXBUCKET* ref2)
|
||||
{
|
||||
return GetBucketChannel((const RXBUCKET*)a)-GetBucketChannel((const RXBUCKET*)b);
|
||||
return GetBucketChannel(ref1) - GetBucketChannel(ref2);
|
||||
}
|
||||
#else
|
||||
static int CompareChannels(RXBUCKET *a, RXBUCKET *b)
|
||||
{
|
||||
return GetBucketChannel(a) - GetBucketChannel(b);
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static RXBUCKET* SortGetMiddle(RXBUCKET* a1, RXBUCKET* a2, RXBUCKET* a3)
|
||||
{
|
||||
|
@ -156,6 +124,12 @@ static void SortSwap(RXBUCKET *a, RXBUCKET *b)
|
|||
*b = t;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void SortRXBucket(int nCount)
|
||||
{
|
||||
RXBUCKET* v144[32];
|
||||
|
@ -180,49 +154,48 @@ static void SortRXBucket(int nCount)
|
|||
}
|
||||
break;
|
||||
}
|
||||
RXBUCKET *v30, *vdi, *vsi;
|
||||
vdi = pArray + nCount / 2;
|
||||
RXBUCKET * middle = pArray + nCount / 2;
|
||||
if (nCount > 29)
|
||||
{
|
||||
v30 = pArray;
|
||||
vsi = pArray + nCount-1;
|
||||
RXBUCKET* first = pArray;
|
||||
RXBUCKET* last = pArray + nCount - 1;
|
||||
if (nCount > 42)
|
||||
{
|
||||
int v20 = nCount / 8;
|
||||
v30 = SortGetMiddle(v30, v30+v20, v30+v20*2);
|
||||
vdi = SortGetMiddle(vdi-v20, vdi, vdi+v20);
|
||||
vsi = SortGetMiddle(vsi-v20*2, vsi-v20, vsi);
|
||||
int eighth = nCount / 8;
|
||||
first = SortGetMiddle(first, first + eighth, first + eighth * 2);
|
||||
middle = SortGetMiddle(middle - eighth, middle, middle + eighth);
|
||||
last = SortGetMiddle(last - eighth * 2, last - eighth, last);
|
||||
}
|
||||
vdi = SortGetMiddle(v30, vdi, vsi);
|
||||
middle = SortGetMiddle(first, middle, last);
|
||||
}
|
||||
RXBUCKET v44 = *vdi;
|
||||
RXBUCKET *vc = pArray;
|
||||
RXBUCKET *v8 = pArray+nCount-1;
|
||||
RXBUCKET *vbx = vc;
|
||||
RXBUCKET *v4 = v8;
|
||||
RXBUCKET pivot = *middle;
|
||||
RXBUCKET* first = pArray;
|
||||
RXBUCKET* last = pArray + nCount - 1;
|
||||
RXBUCKET* vbx = first;
|
||||
RXBUCKET* v4 = last;
|
||||
while (true)
|
||||
{
|
||||
while (vbx <= v4)
|
||||
{
|
||||
int nCmp = CompareChannels(vbx, &v44);
|
||||
int nCmp = CompareChannels(vbx, &pivot);
|
||||
if (nCmp > 0)
|
||||
break;
|
||||
if (nCmp == 0)
|
||||
{
|
||||
SortSwap(vbx, vc);
|
||||
vc++;
|
||||
SortSwap(vbx, first);
|
||||
first++;
|
||||
}
|
||||
vbx++;
|
||||
}
|
||||
while (vbx <= v4)
|
||||
{
|
||||
int nCmp = CompareChannels(v4, &v44);
|
||||
int nCmp = CompareChannels(v4, &pivot);
|
||||
if (nCmp < 0)
|
||||
break;
|
||||
if (nCmp == 0)
|
||||
{
|
||||
SortSwap(v4, v8);
|
||||
v8--;
|
||||
SortSwap(v4, last);
|
||||
last--;
|
||||
}
|
||||
v4--;
|
||||
}
|
||||
|
@ -233,18 +206,18 @@ static void SortRXBucket(int nCount)
|
|||
vbx++;
|
||||
}
|
||||
RXBUCKET* v2c = pArray + nCount;
|
||||
int vt = ClipHigh(vbx-vc, vc-pArray);
|
||||
int vt = ClipHigh(vbx - first, first - pArray);
|
||||
for (int i = 0; i < vt; i++)
|
||||
{
|
||||
SortSwap(&vbx[i - vt], &pArray[i]);
|
||||
}
|
||||
vt = ClipHigh(v8-v4, v2c-v8-1);
|
||||
vt = ClipHigh(last - v4, v2c - last - 1);
|
||||
for (int i = 0; i < vt; i++)
|
||||
{
|
||||
SortSwap(&v2c[i - vt], &vbx[i]);
|
||||
}
|
||||
int vvsi = v8-v4;
|
||||
int vvdi = vbx-vc;
|
||||
int vvsi = last - v4;
|
||||
int vvdi = vbx - first;
|
||||
if (vvsi >= vvdi)
|
||||
{
|
||||
vc4[v14] = vvsi;
|
||||
|
@ -269,90 +242,122 @@ static void SortRXBucket(int nCount)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned short bucketHead[1024+1];
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evInit(void)
|
||||
static void createBucketHeads()
|
||||
{
|
||||
int i, j;
|
||||
// create the list of header indices
|
||||
for (i = 0, j = 0; i < kMaxID; i++)
|
||||
{
|
||||
bucketHead[i] = (short)j;
|
||||
while (j < bucketCount && GetBucketChannel(&rxBucket[j]) == i)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
bucketHead[i] = (short)j;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evInit()
|
||||
{
|
||||
eventQ.set.clear();
|
||||
int nCount = 0;
|
||||
|
||||
queue.clear();
|
||||
memset(rxBucket, 0, sizeof(rxBucket));
|
||||
|
||||
// add all the tags to the bucket array
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
int nXSector = sector[i].extra;
|
||||
if (nXSector >= kMaxXSectors)
|
||||
I_Error("Invalid xsector reference in sector %d", i);
|
||||
if (nXSector > 0 && xsector[nXSector].rxID > 0)
|
||||
{
|
||||
assert(nCount < kChannelMax);
|
||||
rxBucket[nCount].type = 6;
|
||||
rxBucket[nCount].type = SS_SECTOR;
|
||||
rxBucket[nCount].index = i;
|
||||
nCount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < numwalls; i++)
|
||||
{
|
||||
int nXWall = wall[i].extra;
|
||||
if (nXWall >= kMaxXWalls)
|
||||
I_Error("Invalid xwall reference in wall %d", i);
|
||||
if (nXWall > 0 && xwall[nXWall].rxID > 0)
|
||||
{
|
||||
assert(nCount < kChannelMax);
|
||||
rxBucket[nCount].type = 0;
|
||||
rxBucket[nCount].type = SS_WALL;
|
||||
rxBucket[nCount].index = i;
|
||||
nCount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < kMaxSprites; i++)
|
||||
{
|
||||
if (sprite[i].statnum < kMaxStatus)
|
||||
{
|
||||
int nXSprite = sprite[i].extra;
|
||||
if (nXSprite >= kMaxXSprites)
|
||||
I_Error("Invalid xsprite reference in sprite %d", i);
|
||||
if (nXSprite > 0 && xsprite[nXSprite].rxID > 0)
|
||||
{
|
||||
assert(nCount < kChannelMax);
|
||||
rxBucket[nCount].type = 3;
|
||||
rxBucket[nCount].type = SS_SPRITE;
|
||||
rxBucket[nCount].index = i;
|
||||
nCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SortRXBucket(nCount);
|
||||
int i, j = 0;
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
bucketHead[i] = j;
|
||||
while(j < nCount && GetBucketChannel(&rxBucket[j]) == i)
|
||||
j++;
|
||||
}
|
||||
bucketHead[i] = j;
|
||||
bucketCount = nCount;
|
||||
createBucketHeads();
|
||||
}
|
||||
|
||||
char evGetSourceState(int nType, int nIndex)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static bool evGetSourceState(int type, int nIndex)
|
||||
{
|
||||
switch (nType)
|
||||
int nXIndex;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 6:
|
||||
{
|
||||
int nXIndex = sector[nIndex].extra;
|
||||
case SS_SECTOR:
|
||||
nXIndex = sector[nIndex].extra;
|
||||
assert(nXIndex > 0 && nXIndex < kMaxXSectors);
|
||||
return xsector[nXIndex].state;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
int nXIndex = wall[nIndex].extra;
|
||||
return xsector[nXIndex].state != 0;
|
||||
|
||||
case SS_WALL:
|
||||
nXIndex = wall[nIndex].extra;
|
||||
assert(nXIndex > 0 && nXIndex < kMaxXWalls);
|
||||
return xwall[nXIndex].state;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
int nXIndex = sprite[nIndex].extra;
|
||||
return xwall[nXIndex].state != 0;
|
||||
|
||||
case SS_SPRITE:
|
||||
nXIndex = sprite[nIndex].extra;
|
||||
assert(nXIndex > 0 && nXIndex < kMaxXSprites);
|
||||
return xsprite[nXIndex].state;
|
||||
return xsprite[nXIndex].state != 0;
|
||||
}
|
||||
|
||||
// shouldn't reach this point
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
|
||||
{
|
||||
|
@ -450,25 +455,32 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
|
|||
}
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap) {
|
||||
|
||||
if (gModernMap)
|
||||
{
|
||||
// allow to send commands on player sprites
|
||||
PLAYER* pPlayer = NULL;
|
||||
if (playerRXRngIsFine(rxId)) {
|
||||
if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != NULL)
|
||||
if (playerRXRngIsFine(rxId))
|
||||
{
|
||||
if ((pPlayer = getPlayerById((kChannelPlayer0 - kChannelPlayer7) + kMaxPlayers)) != nullptr)
|
||||
trMessageSprite(pPlayer->nSprite, event);
|
||||
} else if (rxId == kChannelAllPlayers) {
|
||||
for (int i = 0; i < kMaxPlayers; i++) {
|
||||
if ((pPlayer = getPlayerById(i)) != NULL)
|
||||
}
|
||||
else if (rxId == kChannelAllPlayers)
|
||||
{
|
||||
for (int i = 0; i < kMaxPlayers; i++)
|
||||
{
|
||||
if ((pPlayer = getPlayerById(i)) != nullptr)
|
||||
trMessageSprite(pPlayer->nSprite, event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
for (int i = bucketHead[rxId]; i < bucketHead[rxId+1]; i++) {
|
||||
if (event.type != rxBucket[i].type || event.index != rxBucket[i].index) {
|
||||
switch (rxBucket[i].type) {
|
||||
for (int i = bucketHead[rxId]; i < bucketHead[rxId + 1]; i++)
|
||||
{
|
||||
if (event.type != rxBucket[i].type || event.index != rxBucket[i].index)
|
||||
{
|
||||
switch (rxBucket[i].type)
|
||||
{
|
||||
case 6:
|
||||
trMessageSector(rxBucket[i].index, event);
|
||||
break;
|
||||
|
@ -495,48 +507,82 @@ void evSend(int nIndex, int nType, int rxId, COMMAND_ID command)
|
|||
}
|
||||
}
|
||||
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command) {
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command)
|
||||
{
|
||||
assert(command != kCmdCallback);
|
||||
if (command == kCmdState) command = evGetSourceState(nType, nIndex) ? kCmdOn : kCmdOff;
|
||||
else if (command == kCmdNotState) command = evGetSourceState(nType, nIndex) ? kCmdOff : kCmdOn;
|
||||
EVENT evn = {};
|
||||
evn.index = nIndex;
|
||||
evn.type = nType;
|
||||
evn.cmd = command;
|
||||
eventQ.set.insert({ gFrameClock + nDelta, evn });
|
||||
EVENT evn = { (int16_t)nIndex, (int8_t)nType, (int8_t)command, 0, gFrameClock + (int)nDelta };
|
||||
queue.insert(evn);
|
||||
}
|
||||
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback) {
|
||||
EVENT evn = {};
|
||||
evn.index = nIndex;
|
||||
evn.type = nType;
|
||||
evn.cmd = kCmdCallback;
|
||||
evn.funcID = callback;
|
||||
eventQ.set.insert({ gFrameClock + nDelta, evn });
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback)
|
||||
{
|
||||
EVENT evn = { (int16_t)nIndex, (int8_t)nType, kCmdCallback, (int16_t)callback, gFrameClock + (int)nDelta };
|
||||
queue.insert(evn);
|
||||
}
|
||||
|
||||
void evProcess(unsigned int nTime)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evKill(int index, int type)
|
||||
{
|
||||
while(eventQ.IsNotEmpty(nTime))
|
||||
for (auto ev = queue.begin(); ev != queue.end();)
|
||||
{
|
||||
EVENT event = eventQ.ERemove();
|
||||
if (ev->index == index && ev->type == type) ev = queue.erase(ev);
|
||||
else ev++;
|
||||
}
|
||||
}
|
||||
|
||||
void evKill(int index, int type, CALLBACK_ID cb)
|
||||
{
|
||||
for (auto ev = queue.begin(); ev != queue.end();)
|
||||
{
|
||||
if (ev->index == index && ev->type == type && ev->funcID == cb) ev = queue.erase(ev);
|
||||
else ev++;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evProcess(unsigned int time)
|
||||
{
|
||||
while (queue.size() > 0 && time >= queue.begin()->priority)
|
||||
{
|
||||
EVENT event = *queue.begin();
|
||||
queue.erase(queue.begin());
|
||||
|
||||
if (event.cmd == kCmdCallback)
|
||||
{
|
||||
assert(event.funcID < kCallbackMax);
|
||||
assert(gCallback[event.funcID] != NULL);
|
||||
assert(gCallback[event.funcID] != nullptr);
|
||||
gCallback[event.funcID](event.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case 6:
|
||||
case SS_SECTOR:
|
||||
trMessageSector(event.index, event);
|
||||
break;
|
||||
case 0:
|
||||
case SS_WALL:
|
||||
trMessageWall(event.index, event);
|
||||
break;
|
||||
case 3:
|
||||
case SS_SPRITE:
|
||||
trMessageSprite(event.index, event);
|
||||
break;
|
||||
}
|
||||
|
@ -544,55 +590,76 @@ void evProcess(unsigned int nTime)
|
|||
}
|
||||
}
|
||||
|
||||
void evKill(int a1, int a2)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, EVENT& w, EVENT* def)
|
||||
{
|
||||
eventQ.Kill([=](EVENT nItem)->bool {return nItem.index == a1 && nItem.type == a2; });
|
||||
if (arc.BeginObject(keyname))
|
||||
{
|
||||
arc("index", w.index)
|
||||
("type", w.type)
|
||||
("command", w.cmd)
|
||||
("func", w.funcID)
|
||||
("prio", w.priority)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
void evKill(int a1, int a2, CALLBACK_ID a3)
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, RXBUCKET& w, RXBUCKET* def)
|
||||
{
|
||||
EVENT evn = { (unsigned int)a1, (unsigned int)a2, kCmdCallback, (unsigned int)a3 };
|
||||
eventQ.Kill([=](EVENT nItem)->bool {return !memcmp(&nItem, &evn, sizeof(EVENT)); });
|
||||
if (arc.BeginObject(keyname))
|
||||
{
|
||||
arc("index", w.index)
|
||||
("type", w.type)
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
class EventQLoadSave : public LoadSave
|
||||
{
|
||||
public:
|
||||
virtual void Load();
|
||||
virtual void Save();
|
||||
};
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void EventQLoadSave::Load()
|
||||
void SerializeEvents(FSerializer& arc)
|
||||
{
|
||||
eventQ.set.clear();
|
||||
int nEvents;
|
||||
Read(&nEvents, sizeof(nEvents));
|
||||
for (int i = 0; i < nEvents; i++)
|
||||
if (arc.BeginObject("events"))
|
||||
{
|
||||
queueItem event = {};
|
||||
Read(&event, sizeof(event));
|
||||
eventQ.set.insert(event);
|
||||
}
|
||||
Read(rxBucket, sizeof(rxBucket));
|
||||
Read(bucketHead, sizeof(bucketHead));
|
||||
}
|
||||
arc("bucketcount", bucketCount)
|
||||
.Array("buckets", rxBucket, bucketCount);
|
||||
|
||||
void EventQLoadSave::Save()
|
||||
if (arc.isReading()) createBucketHeads();
|
||||
int numEvents = (int)queue.size();
|
||||
arc("eventcount", numEvents);
|
||||
if (arc.BeginArray("events"))
|
||||
{
|
||||
int nEvents = eventQ.set.size();
|
||||
Write(&nEvents, sizeof(nEvents));
|
||||
for (auto &item : eventQ.set)
|
||||
if (arc.isReading())
|
||||
{
|
||||
Write(&item, sizeof(item));
|
||||
queue.clear();
|
||||
EVENT ev;
|
||||
for (int i = 0; i < numEvents; i++)
|
||||
{
|
||||
arc(nullptr, ev);
|
||||
queue.insert(ev);
|
||||
}
|
||||
Write(rxBucket, sizeof(rxBucket));
|
||||
Write(bucketHead, sizeof(bucketHead));
|
||||
}
|
||||
|
||||
|
||||
void EventQLoadSaveConstruct(void)
|
||||
else
|
||||
{
|
||||
new EventQLoadSave();
|
||||
for (auto item : queue)
|
||||
{
|
||||
arc(nullptr, item);
|
||||
}
|
||||
}
|
||||
arc.EndArray();
|
||||
}
|
||||
arc.EndObject();
|
||||
}
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -76,6 +76,7 @@ struct RXBUCKET
|
|||
uint16_t index;
|
||||
uint8_t type;
|
||||
};
|
||||
extern void (*gCallback[])(int);
|
||||
extern RXBUCKET rxBucket[];
|
||||
extern unsigned short bucketHead[];
|
||||
|
||||
|
@ -120,6 +121,17 @@ kCmdModernFeaturesDisable = 200, // must be in object with kChannelMapModerniz
|
|||
kCmdNumbericMax = 255,
|
||||
};
|
||||
|
||||
enum SSType
|
||||
{
|
||||
SS_WALL = 0,
|
||||
SS_CEILING = 1,
|
||||
SS_FLOOR = 2,
|
||||
SS_SPRITE = 3,
|
||||
SS_MASKED = 4,
|
||||
|
||||
SS_SECTOR = 6,
|
||||
};
|
||||
|
||||
inline bool playerRXRngIsFine(int rx) {
|
||||
return (rx >= kChannelPlayer0 && rx < kChannelPlayer7);
|
||||
}
|
||||
|
@ -128,15 +140,21 @@ inline bool channelRangeIsFine(int channel) {
|
|||
return (channel >= kChannelUser && channel < kChannelUserMax);
|
||||
}
|
||||
|
||||
struct EVENT {
|
||||
unsigned int index: 14; // index
|
||||
unsigned int type: 3; // type
|
||||
unsigned int cmd: 8; // cmd
|
||||
unsigned int funcID: 8; // callback
|
||||
struct EVENT
|
||||
{
|
||||
int16_t index;
|
||||
int8_t type;
|
||||
int8_t cmd;
|
||||
int16_t funcID;
|
||||
int priority;
|
||||
|
||||
bool operator<(const EVENT& other) const
|
||||
{
|
||||
return priority < other.priority;
|
||||
}
|
||||
};
|
||||
|
||||
void evInit(void);
|
||||
char evGetSourceState(int nType, int nIndex);
|
||||
void evSend(int nIndex, int nType, int rxId, COMMAND_ID command);
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, COMMAND_ID command);
|
||||
void evPost(int nIndex, int nType, unsigned int nDelta, CALLBACK_ID callback);
|
||||
|
|
|
@ -731,7 +731,6 @@ void MyLoadSave::Save(void)
|
|||
void ActorLoadSaveConstruct(void);
|
||||
void AILoadSaveConstruct(void);
|
||||
void EndGameLoadSaveConstruct(void);
|
||||
void EventQLoadSaveConstruct(void);
|
||||
void LevelsLoadSaveConstruct(void);
|
||||
void MessagesLoadSaveConstruct(void);
|
||||
void MirrorLoadSaveConstruct(void);
|
||||
|
@ -751,7 +750,6 @@ void LoadSaveSetup(void)
|
|||
ActorLoadSaveConstruct();
|
||||
AILoadSaveConstruct();
|
||||
EndGameLoadSaveConstruct();
|
||||
EventQLoadSaveConstruct();
|
||||
LevelsLoadSaveConstruct();
|
||||
MessagesLoadSaveConstruct();
|
||||
MirrorLoadSaveConstruct();
|
||||
|
@ -765,4 +763,14 @@ void LoadSaveSetup(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SerializeEvents(FSerializer& arc);
|
||||
|
||||
void GameInterface::SerializeGameState(FSerializer& arc)
|
||||
{
|
||||
SerializeEvents(arc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -101,6 +101,7 @@ static void SerializeSession(FSerializer& arc)
|
|||
SerializeAutomap(arc);
|
||||
SerializeHud(arc);
|
||||
SerializeGlobals(arc);
|
||||
gi->SerializeGameState(arc);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -156,7 +157,6 @@ bool OpenSaveGameForRead(const char *name)
|
|||
// Load system-side data from savegames.
|
||||
loadMapBackup(currentLevel->fileName);
|
||||
SerializeSession(arc);
|
||||
gi->SerializeGameState(arc);
|
||||
}
|
||||
return savereader != nullptr;
|
||||
}
|
||||
|
@ -250,7 +250,6 @@ bool OpenSaveGameForWrite(const char* filename, const char *name)
|
|||
// Handle system-side modules that need to persist data in savegames here, in a central place.
|
||||
savegamesession.OpenWriter(save_formatted);
|
||||
SerializeSession(savegamesession);
|
||||
gi->SerializeGameState(savegamesession);
|
||||
buff = savegamesession.GetCompressedOutput();
|
||||
AddCompressedSavegameChunk("session.json", buff);
|
||||
|
||||
|
|
Loading…
Reference in a new issue