Browse Source

Big-endian support for multiplayer

Not sure if this works but it's a start
pull/5607/head
Gleb Mazovetskiy 3 years ago committed by Anders Jenbo
parent
commit
ca69237d59
  1. 487
      Source/msg.cpp
  2. 64
      Source/multi.cpp
  3. 34
      Source/sync.cpp
  4. 8
      Source/utils/endian.hpp

487
Source/msg.cpp

File diff suppressed because it is too large Load Diff

64
Source/multi.cpp

@ -74,6 +74,13 @@ const event_type EventTypes[3] = {
namespace {
constexpr uint16_t HeaderCheckVal =
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
LoadBE16("ip");
#else
LoadLE16("ip");
#endif
uint32_t sgbSentThisCycle;
void BufferInit(TBuffer *pBuf)
@ -124,15 +131,15 @@ void NetReceivePlayerData(TPkt *pkt)
const Player &myPlayer = *MyPlayer;
const Point target = myPlayer.GetTargetPosition();
pkt->hdr.wCheck = LoadBE32("\0\0ip");
pkt->hdr.wCheck = HeaderCheckVal;
pkt->hdr.px = myPlayer.position.tile.x;
pkt->hdr.py = myPlayer.position.tile.y;
pkt->hdr.targx = target.x;
pkt->hdr.targy = target.y;
pkt->hdr.php = myPlayer._pHitPoints;
pkt->hdr.pmhp = myPlayer._pMaxHP;
pkt->hdr.mana = myPlayer._pMana;
pkt->hdr.maxmana = myPlayer._pMaxMana;
pkt->hdr.php = SDL_SwapLE32(myPlayer._pHitPoints);
pkt->hdr.pmhp = SDL_SwapLE32(myPlayer._pMaxHP);
pkt->hdr.mana = SDL_SwapLE32(myPlayer._pMana);
pkt->hdr.maxmana = SDL_SwapLE32(myPlayer._pMaxMana);
pkt->hdr.bstr = myPlayer._pBaseStr;
pkt->hdr.bmag = myPlayer._pBaseMag;
pkt->hdr.bdex = myPlayer._pBaseDex;
@ -185,9 +192,10 @@ void SendPacket(int playerId, const byte *packet, size_t size)
TPkt pkt;
NetReceivePlayerData(&pkt);
pkt.hdr.wLen = static_cast<uint16_t>(size + sizeof(pkt.hdr));
const size_t sizeWithheader = size + sizeof(pkt.hdr);
pkt.hdr.wLen = SDL_SwapLE16(static_cast<uint16_t>(sizeWithheader));
memcpy(pkt.body, packet, size);
if (!SNetSendMessage(playerId, &pkt.hdr, pkt.hdr.wLen))
if (!SNetSendMessage(playerId, &pkt.hdr, sizeWithheader))
nthread_terminate_game("SNetSendMessage0");
}
@ -501,8 +509,8 @@ void NetSendHiPri(int playerId, const byte *data, size_t size)
byte *hipriBody = ReceivePacket(&sgHiPriBuf, pkt.body, &msgSize);
byte *lowpriBody = ReceivePacket(&sgLoPriBuf, hipriBody, &msgSize);
msgSize = sync_all_monsters(lowpriBody, msgSize);
size_t len = gdwNormalMsgSize - msgSize;
pkt.hdr.wLen = static_cast<uint16_t>(len);
const size_t len = gdwNormalMsgSize - msgSize;
pkt.hdr.wLen = SDL_SwapLE16(static_cast<uint16_t>(len));
if (!SNetSendMessage(SNPLAYER_OTHERS, &pkt.hdr, static_cast<unsigned>(len)))
nthread_terminate_game("SNetSendMessage");
}
@ -512,8 +520,8 @@ void multi_send_msg_packet(uint32_t pmask, const byte *data, size_t size)
{
TPkt pkt;
NetReceivePlayerData(&pkt);
size_t len = size + sizeof(pkt.hdr);
pkt.hdr.wLen = static_cast<uint16_t>(len);
const size_t len = size + sizeof(pkt.hdr);
pkt.hdr.wLen = SDL_SwapLE16(static_cast<uint16_t>(len));
memcpy(pkt.body, data, size);
size_t playerID = 0;
for (size_t v = 1; playerID < Players.size(); playerID++, v <<= 1) {
@ -601,9 +609,9 @@ void multi_process_network_packets()
continue;
if (playerId >= Players.size())
continue;
if (pkt->wCheck != LoadBE32("\0\0ip"))
if (pkt->wCheck != HeaderCheckVal)
continue;
if (pkt->wLen != dwMsgSize)
if (SDL_SwapLE16(pkt->wLen) != dwMsgSize)
continue;
Player &player = Players[playerId];
if (!IsNetPlayerValid(player)) {
@ -618,10 +626,10 @@ void multi_process_network_packets()
player.position.last = syncPosition;
if (&player != MyPlayer) {
assert(gbBufferMsgs != 2);
player._pHitPoints = pkt->php;
player._pMaxHP = pkt->pmhp;
player._pMana = pkt->mana;
player._pMaxMana = pkt->maxmana;
player._pHitPoints = SDL_SwapLE32(pkt->php);
player._pMaxHP = SDL_SwapLE32(pkt->pmhp);
player._pMana = SDL_SwapLE32(pkt->mana);
player._pMaxMana = SDL_SwapLE32(pkt->maxmana);
bool cond = gbBufferMsgs == 1;
player._pBaseStr = pkt->bstr;
player._pBaseMag = pkt->bmag;
@ -666,29 +674,27 @@ void multi_send_zero_packet(size_t pnum, _cmd_id bCmd, const byte *data, size_t
for (size_t offset = 0; offset < size;) {
TPkt pkt {};
pkt.hdr.wCheck = LoadBE32("\0\0ip");
pkt.hdr.wCheck = HeaderCheckVal;
auto &message = *reinterpret_cast<TCmdPlrInfoHdr *>(pkt.body);
message.bCmd = bCmd;
message.wOffset = offset;
message.wOffset = SDL_SwapLE16(offset);
size_t dwBody = gdwLargestMsgSize - sizeof(pkt.hdr) - sizeof(message);
dwBody = std::min(dwBody, size - offset);
assert(dwBody <= 0x0ffff);
message.wBytes = dwBody;
message.wBytes = SDL_SwapLE16(dwBody);
memcpy(&pkt.body[sizeof(message)], &data[offset], message.wBytes);
memcpy(&pkt.body[sizeof(message)], &data[offset], dwBody);
size_t dwMsg = sizeof(pkt.hdr);
dwMsg += sizeof(message);
dwMsg += message.wBytes;
pkt.hdr.wLen = dwMsg;
const size_t dwMsg = sizeof(pkt.hdr) + sizeof(message) + dwBody;
pkt.hdr.wLen = SDL_SwapLE16(dwMsg);
if (!SNetSendMessage(pnum, &pkt, dwMsg)) {
nthread_terminate_game("SNetSendMessage2");
return;
}
offset += message.wBytes;
offset += dwBody;
}
}
@ -787,7 +793,7 @@ void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
}
auto &packedPlayer = PackedPlayerBuffer[pnum];
if (sgwPackPlrOffsetTbl[pnum] != header.wOffset) {
if (sgwPackPlrOffsetTbl[pnum] != SDL_SwapLE16(header.wOffset)) {
sgwPackPlrOffsetTbl[pnum] = 0;
if (header.wOffset != 0) {
return;
@ -797,9 +803,9 @@ void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
SendPlayerInfo(pnum, CMD_ACK_PLRINFO);
}
memcpy(reinterpret_cast<uint8_t *>(&packedPlayer) + header.wOffset, reinterpret_cast<const uint8_t *>(&header) + sizeof(header), header.wBytes);
memcpy(reinterpret_cast<uint8_t *>(&packedPlayer) + SDL_SwapLE16(header.wOffset), reinterpret_cast<const uint8_t *>(&header) + sizeof(header), SDL_SwapLE16(header.wBytes));
sgwPackPlrOffsetTbl[pnum] += header.wBytes;
sgwPackPlrOffsetTbl[pnum] += SDL_SwapLE16(header.wBytes);
if (sgwPackPlrOffsetTbl[pnum] != sizeof(packedPlayer)) {
return;
}

34
Source/sync.cpp

@ -42,7 +42,7 @@ void SyncMonsterPos(TSyncMonster &monsterSync, int ndx)
monsterSync._menemy = encode_enemy(monster);
monsterSync._mdelta = sgnMonsterPriority[ndx] > 255 ? 255 : sgnMonsterPriority[ndx];
monsterSync.mWhoHit = monster.whoHit;
monsterSync._mhitpoints = monster.hitPoints;
monsterSync._mhitpoints = SDL_SwapLE32(monster.hitPoints);
sgnMonsterPriority[ndx] = 0xFFFF;
sgwLRU[ndx] = monster.activeForTicks == 0 ? 0xFFFF : 0xFFFE;
@ -106,27 +106,27 @@ void SyncPlrInv(TSyncHeader *pHdr)
auto &item = Items[pHdr->bItemI];
pHdr->bItemX = item.position.x;
pHdr->bItemY = item.position.y;
pHdr->wItemIndx = item.IDidx;
pHdr->wItemIndx = SDL_SwapLE16(item.IDidx);
if (item.IDidx == IDI_EAR) {
pHdr->wItemCI = (item._iIName[0] << 8) | item._iIName[1];
pHdr->dwItemSeed = (item._iIName[2] << 24) | (item._iIName[3] << 16) | (item._iIName[4] << 8) | item._iIName[5];
pHdr->wItemCI = SDL_SwapLE16((item._iIName[0] << 8) | item._iIName[1]);
pHdr->dwItemSeed = SDL_SwapLE32((item._iIName[2] << 24) | (item._iIName[3] << 16) | (item._iIName[4] << 8) | item._iIName[5]);
pHdr->bItemId = item._iIName[6];
pHdr->bItemDur = item._iIName[7];
pHdr->bItemMDur = item._iIName[8];
pHdr->bItemCh = item._iIName[9];
pHdr->bItemMCh = item._iIName[10];
pHdr->wItemVal = (item._iIName[11] << 8) | ((item._iCurs - ICURS_EAR_SORCERER) << 6) | item._ivalue;
pHdr->dwItemBuff = (item._iIName[12] << 24) | (item._iIName[13] << 16) | (item._iIName[14] << 8) | item._iIName[15];
pHdr->wItemVal = SDL_SwapLE16((item._iIName[11] << 8) | ((item._iCurs - ICURS_EAR_SORCERER) << 6) | item._ivalue);
pHdr->dwItemBuff = SDL_SwapLE32((item._iIName[12] << 24) | (item._iIName[13] << 16) | (item._iIName[14] << 8) | item._iIName[15]);
} else {
pHdr->wItemCI = item._iCreateInfo;
pHdr->dwItemSeed = item._iSeed;
pHdr->wItemCI = SDL_SwapLE16(item._iCreateInfo);
pHdr->dwItemSeed = SDL_SwapLE32(item._iSeed);
pHdr->bItemId = item._iIdentified ? 1 : 0;
pHdr->bItemDur = item._iDurability;
pHdr->bItemMDur = item._iMaxDur;
pHdr->bItemCh = item._iCharges;
pHdr->bItemMCh = item._iMaxCharges;
if (item.IDidx == IDI_GOLD) {
pHdr->wItemVal = item._ivalue;
pHdr->wItemVal = SDL_SwapLE16(item._ivalue);
}
}
}
@ -136,9 +136,9 @@ void SyncPlrInv(TSyncHeader *pHdr)
const auto &item = MyPlayer->InvBody[sgnSyncPInv];
if (!item.isEmpty()) {
pHdr->bPInvLoc = sgnSyncPInv;
pHdr->wPInvIndx = item.IDidx;
pHdr->wPInvCI = item._iCreateInfo;
pHdr->dwPInvSeed = item._iSeed;
pHdr->wPInvIndx = SDL_SwapLE16(item.IDidx);
pHdr->wPInvCI = SDL_SwapLE16(item._iCreateInfo);
pHdr->dwPInvSeed = SDL_SwapLE32(item._iSeed);
pHdr->bPInvId = item._iIdentified ? 1 : 0;
}
@ -282,6 +282,7 @@ uint32_t sync_all_monsters(byte *pbBuf, uint32_t dwMaxLen)
pHdr->wLen += sizeof(TSyncMonster);
dwMaxLen -= sizeof(TSyncMonster);
}
pHdr->wLen = SDL_SwapLE16(pHdr->wLen);
return dwMaxLen;
}
@ -289,18 +290,19 @@ uint32_t sync_all_monsters(byte *pbBuf, uint32_t dwMaxLen)
uint32_t OnSyncData(const TCmd *pCmd, size_t pnum)
{
const auto &header = *reinterpret_cast<const TSyncHeader *>(pCmd);
const uint16_t wLen = SDL_SwapLE16(header.wLen);
assert(gbBufferMsgs != 2);
if (gbBufferMsgs == 1) {
return header.wLen + sizeof(header);
return wLen + sizeof(header);
}
if (pnum == MyPlayerId) {
return header.wLen + sizeof(header);
return wLen + sizeof(header);
}
assert(header.wLen % sizeof(TSyncMonster) == 0);
int monsterCount = header.wLen / sizeof(TSyncMonster);
int monsterCount = wLen / sizeof(TSyncMonster);
uint8_t level = header.bLevel;
bool syncLocalLevel = !MyPlayer->_pLvlChanging && GetLevelForMultiplayer(*MyPlayer) == level;
@ -320,7 +322,7 @@ uint32_t OnSyncData(const TCmd *pCmd, size_t pnum)
}
}
return header.wLen + sizeof(header);
return wLen + sizeof(header);
}
void sync_init()

8
Source/utils/endian.hpp

@ -15,6 +15,14 @@ constexpr uint16_t LoadLE16(const T *b)
return (static_cast<uint8_t>(b[1]) << 8) | static_cast<uint8_t>(b[0]);
}
template <typename T>
constexpr uint16_t LoadBE16(const T *b)
{
static_assert(sizeof(T) == 1, "invalid argument");
// NOLINTNEXTLINE(readability-magic-numbers)
return (static_cast<uint8_t>(b[0]) << 8) | static_cast<uint8_t>(b[1]);
}
template <typename T>
constexpr uint32_t LoadLE32(const T *b)
{

Loading…
Cancel
Save