|
|
|
|
@ -35,7 +35,6 @@
|
|
|
|
|
namespace devilution { |
|
|
|
|
|
|
|
|
|
bool gbSomebodyWonGameKludge; |
|
|
|
|
TBuffer highPriorityBuffer; |
|
|
|
|
uint16_t sgwPackPlrOffsetTbl[MAX_PLRS]; |
|
|
|
|
bool sgbPlayerTurnBitTbl[MAX_PLRS]; |
|
|
|
|
bool sgbPlayerLeftGameTbl[MAX_PLRS]; |
|
|
|
|
@ -47,7 +46,6 @@ GameData sgGameInitInfo;
|
|
|
|
|
bool gbSelectProvider; |
|
|
|
|
int sglTimeoutStart; |
|
|
|
|
int sgdwPlayerLeftReasonTbl[MAX_PLRS]; |
|
|
|
|
TBuffer lowPriorityBuffer; |
|
|
|
|
uint32_t sgdwGameLoops; |
|
|
|
|
/**
|
|
|
|
|
* Specifies the maximum number of players in a game, where 1 |
|
|
|
|
@ -76,6 +74,14 @@ const event_type EventTypes[3] = {
|
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
struct TBuffer { |
|
|
|
|
size_t dwNextWriteOffset; |
|
|
|
|
std::byte bData[4096]; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
TBuffer highPriorityBuffer; |
|
|
|
|
TBuffer lowPriorityBuffer; |
|
|
|
|
|
|
|
|
|
constexpr uint16_t HeaderCheckVal = |
|
|
|
|
#if SDL_BYTEORDER == SDL_LIL_ENDIAN |
|
|
|
|
LoadBE16("ip"); |
|
|
|
|
@ -122,7 +128,7 @@ std::byte *CopyBufferedPackets(std::byte *destination, TBuffer *source, size_t *
|
|
|
|
|
*size -= chunkSize; |
|
|
|
|
} |
|
|
|
|
memmove(source->bData, srcPtr, (source->bData - srcPtr) + source->dwNextWriteOffset + 1); |
|
|
|
|
source->dwNextWriteOffset += static_cast<uint32_t>(source->bData - srcPtr); |
|
|
|
|
source->dwNextWriteOffset += source->bData - srcPtr; |
|
|
|
|
return destination; |
|
|
|
|
} |
|
|
|
|
return destination; |
|
|
|
|
@ -163,7 +169,7 @@ bool IsNetPlayerValid(const Player &player)
|
|
|
|
|
|
|
|
|
|
void CheckPlayerInfoTimeouts() |
|
|
|
|
{ |
|
|
|
|
for (size_t i = 0; i < Players.size(); i++) { |
|
|
|
|
for (uint8_t i = 0; i < Players.size(); i++) { |
|
|
|
|
Player &player = Players[i]; |
|
|
|
|
if (&player == MyPlayer) { |
|
|
|
|
continue; |
|
|
|
|
@ -192,7 +198,7 @@ void CheckPlayerInfoTimeouts()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SendPacket(size_t playerId, const std::byte *packet, size_t size) |
|
|
|
|
void SendPacket(uint8_t playerId, const std::byte *packet, size_t size) |
|
|
|
|
{ |
|
|
|
|
TPkt pkt; |
|
|
|
|
|
|
|
|
|
@ -200,7 +206,7 @@ void SendPacket(size_t playerId, const std::byte *packet, size_t size)
|
|
|
|
|
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(static_cast<int>(playerId), &pkt.hdr, sizeWithheader)) |
|
|
|
|
if (!SNetSendMessage(playerId, &pkt.hdr, sizeWithheader)) |
|
|
|
|
nthread_terminate_game("SNetSendMessage0"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -208,13 +214,13 @@ void MonsterSeeds()
|
|
|
|
|
{ |
|
|
|
|
sgdwGameLoops++; |
|
|
|
|
const uint32_t seed = (sgdwGameLoops >> 8) | (sgdwGameLoops << 24); |
|
|
|
|
for (size_t i = 0; i < MaxMonsters; i++) |
|
|
|
|
for (uint32_t i = 0; i < MaxMonsters; i++) |
|
|
|
|
Monsters[i].aiSeed = seed + i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void HandleTurnUpperBit(size_t pnum) |
|
|
|
|
void HandleTurnUpperBit(uint8_t pnum) |
|
|
|
|
{ |
|
|
|
|
size_t i; |
|
|
|
|
uint8_t i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < Players.size(); i++) { |
|
|
|
|
if ((player_state[i] & PS_CONNECTED) != 0 && i != pnum) |
|
|
|
|
@ -228,7 +234,7 @@ void HandleTurnUpperBit(size_t pnum)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ParseTurn(size_t pnum, uint32_t turn) |
|
|
|
|
void ParseTurn(uint8_t pnum, uint32_t turn) |
|
|
|
|
{ |
|
|
|
|
if ((turn & 0x80000000) != 0) |
|
|
|
|
HandleTurnUpperBit(pnum); |
|
|
|
|
@ -277,7 +283,7 @@ void PlayerLeftMsg(Player &player, bool left)
|
|
|
|
|
|
|
|
|
|
void ClearPlayerLeftState() |
|
|
|
|
{ |
|
|
|
|
for (size_t i = 0; i < Players.size(); i++) { |
|
|
|
|
for (uint8_t i = 0; i < Players.size(); i++) { |
|
|
|
|
if (sgbPlayerLeftGameTbl[i]) { |
|
|
|
|
if (gbBufferMsgs == 1) |
|
|
|
|
msg_send_drop_pkt(i, sgdwPlayerLeftReasonTbl[i]); |
|
|
|
|
@ -292,7 +298,7 @@ void ClearPlayerLeftState()
|
|
|
|
|
|
|
|
|
|
void CheckDropPlayer() |
|
|
|
|
{ |
|
|
|
|
for (size_t i = 0; i < Players.size(); i++) { |
|
|
|
|
for (uint8_t i = 0; i < Players.size(); i++) { |
|
|
|
|
if ((player_state[i] & PS_ACTIVE) == 0 && (player_state[i] & PS_CONNECTED) != 0) { |
|
|
|
|
SNetDropPlayer(i, LEAVE_DROP); |
|
|
|
|
} |
|
|
|
|
@ -322,9 +328,9 @@ void BeginTimeout()
|
|
|
|
|
CheckDropPlayer(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void HandleAllPackets(size_t pnum, const std::byte *data, size_t size) |
|
|
|
|
void HandleAllPackets(uint8_t pnum, const std::byte *data, size_t size) |
|
|
|
|
{ |
|
|
|
|
for (unsigned offset = 0; offset < size;) { |
|
|
|
|
for (size_t offset = 0; offset < size;) { |
|
|
|
|
size_t messageSize = ParseCmd(pnum, reinterpret_cast<const TCmd *>(&data[offset])); |
|
|
|
|
if (messageSize == 0) { |
|
|
|
|
break; |
|
|
|
|
@ -345,7 +351,7 @@ void ProcessTmsgs()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SendPlayerInfo(size_t pnum, _cmd_id cmd) |
|
|
|
|
void SendPlayerInfo(uint8_t pnum, _cmd_id cmd) |
|
|
|
|
{ |
|
|
|
|
PlayerNetPack packed; |
|
|
|
|
Player &myPlayer = *MyPlayer; |
|
|
|
|
@ -493,7 +499,7 @@ void InitGameInfo()
|
|
|
|
|
sgGameInitInfo.fullQuests = (!gbIsMultiplayer || *sgOptions.Gameplay.multiplayerFullQuests) ? 1 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NetSendLoPri(size_t playerId, const std::byte *data, size_t size) |
|
|
|
|
void NetSendLoPri(uint8_t playerId, const std::byte *data, size_t size) |
|
|
|
|
{ |
|
|
|
|
if (data != nullptr && size != 0) { |
|
|
|
|
CopyPacket(&lowPriorityBuffer, data, size); |
|
|
|
|
@ -501,7 +507,7 @@ void NetSendLoPri(size_t playerId, const std::byte *data, size_t size)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void NetSendHiPri(size_t playerId, const std::byte *data, size_t size) |
|
|
|
|
void NetSendHiPri(uint8_t playerId, const std::byte *data, size_t size) |
|
|
|
|
{ |
|
|
|
|
if (data != nullptr && size != 0) { |
|
|
|
|
CopyPacket(&highPriorityBuffer, data, size); |
|
|
|
|
@ -518,7 +524,7 @@ void NetSendHiPri(size_t playerId, const std::byte *data, size_t size)
|
|
|
|
|
remainingSpace = sync_all_monsters(destination, remainingSpace); |
|
|
|
|
const size_t len = gdwNormalMsgSize - remainingSpace; |
|
|
|
|
pkt.hdr.wLen = SDL_SwapLE16(static_cast<uint16_t>(len)); |
|
|
|
|
if (!SNetSendMessage(SNPLAYER_OTHERS, &pkt.hdr, static_cast<unsigned>(len))) |
|
|
|
|
if (!SNetSendMessage(SNPLAYER_OTHERS, &pkt.hdr, len)) |
|
|
|
|
nthread_terminate_game("SNetSendMessage"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -530,8 +536,8 @@ void multi_send_msg_packet(uint32_t pmask, const std::byte *data, size_t size)
|
|
|
|
|
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) { |
|
|
|
|
uint8_t playerID = 0; |
|
|
|
|
for (uint32_t v = 1; playerID < Players.size(); playerID++, v <<= 1) { |
|
|
|
|
if ((v & pmask) != 0) { |
|
|
|
|
if (!SNetSendMessage(playerID, &pkt.hdr, len)) { |
|
|
|
|
nthread_terminate_game("SNetSendMessage"); |
|
|
|
|
@ -543,7 +549,7 @@ void multi_send_msg_packet(uint32_t pmask, const std::byte *data, size_t size)
|
|
|
|
|
|
|
|
|
|
void multi_msg_countdown() |
|
|
|
|
{ |
|
|
|
|
for (size_t i = 0; i < Players.size(); i++) { |
|
|
|
|
for (uint8_t i = 0; i < Players.size(); i++) { |
|
|
|
|
if ((player_state[i] & PS_TURN_ARRIVED) != 0) { |
|
|
|
|
if (gdwMsgLenTbl[i] == sizeof(int32_t)) |
|
|
|
|
ParseTurn(i, *(int32_t *)glpMsgTbl[i]); |
|
|
|
|
@ -551,7 +557,7 @@ void multi_msg_countdown()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void multi_player_left(int pnum, int reason) |
|
|
|
|
void multi_player_left(uint8_t pnum, int reason) |
|
|
|
|
{ |
|
|
|
|
sgbPlayerLeftGameTbl[pnum] = true; |
|
|
|
|
sgdwPlayerLeftReasonTbl[pnum] = reason; |
|
|
|
|
@ -571,7 +577,7 @@ bool multi_handle_delta()
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < Players.size(); i++) { |
|
|
|
|
for (uint8_t i = 0; i < Players.size(); i++) { |
|
|
|
|
if (sgbSendDeltaTbl[i]) { |
|
|
|
|
sgbSendDeltaTbl[i] = false; |
|
|
|
|
DeltaExportData(i); |
|
|
|
|
@ -612,7 +618,7 @@ void multi_process_network_packets()
|
|
|
|
|
|
|
|
|
|
uint8_t playerId = std::numeric_limits<uint8_t>::max(); |
|
|
|
|
TPktHdr *pkt; |
|
|
|
|
uint32_t dwMsgSize = 0; |
|
|
|
|
size_t dwMsgSize = 0; |
|
|
|
|
while (SNetReceiveMessage(&playerId, (void **)&pkt, &dwMsgSize)) { |
|
|
|
|
dwRecCount++; |
|
|
|
|
ClearPlayerLeftState(); |
|
|
|
|
@ -679,7 +685,7 @@ void multi_process_network_packets()
|
|
|
|
|
CheckPlayerInfoTimeouts(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void multi_send_zero_packet(size_t pnum, _cmd_id bCmd, const std::byte *data, size_t size) |
|
|
|
|
void multi_send_zero_packet(uint8_t pnum, _cmd_id bCmd, const std::byte *data, size_t size) |
|
|
|
|
{ |
|
|
|
|
assert(pnum != MyPlayerId); |
|
|
|
|
assert(data != nullptr); |
|
|
|
|
@ -690,17 +696,19 @@ void multi_send_zero_packet(size_t pnum, _cmd_id bCmd, const std::byte *data, si
|
|
|
|
|
pkt.hdr.wCheck = HeaderCheckVal; |
|
|
|
|
auto &message = *reinterpret_cast<TCmdPlrInfoHdr *>(pkt.body); |
|
|
|
|
message.bCmd = bCmd; |
|
|
|
|
message.wOffset = SDL_SwapLE16(offset); |
|
|
|
|
assert(offset <= 0x0ffff); |
|
|
|
|
message.wOffset = SDL_SwapLE16(static_cast<uint16_t>(offset)); |
|
|
|
|
|
|
|
|
|
size_t dwBody = gdwLargestMsgSize - sizeof(pkt.hdr) - sizeof(message); |
|
|
|
|
dwBody = std::min(dwBody, size - offset); |
|
|
|
|
assert(dwBody <= 0x0ffff); |
|
|
|
|
message.wBytes = SDL_SwapLE16(dwBody); |
|
|
|
|
message.wBytes = SDL_SwapLE16(static_cast<uint16_t>(dwBody)); |
|
|
|
|
|
|
|
|
|
memcpy(&pkt.body[sizeof(message)], &data[offset], dwBody); |
|
|
|
|
|
|
|
|
|
const size_t dwMsg = sizeof(pkt.hdr) + sizeof(message) + dwBody; |
|
|
|
|
pkt.hdr.wLen = SDL_SwapLE16(dwMsg); |
|
|
|
|
assert(dwMsg <= 0x0ffff); |
|
|
|
|
pkt.hdr.wLen = SDL_SwapLE16(static_cast<uint16_t>(dwMsg)); |
|
|
|
|
|
|
|
|
|
if (!SNetSendMessage(pnum, &pkt, dwMsg)) { |
|
|
|
|
nthread_terminate_game("SNetSendMessage2"); |
|
|
|
|
@ -802,7 +810,7 @@ void recv_plrinfo(Player &player, const TCmdPlrInfoHdr &header, bool recv)
|
|
|
|
|
if (&player == MyPlayer) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
size_t pnum = player.getId(); |
|
|
|
|
uint8_t pnum = player.getId(); |
|
|
|
|
auto &packedPlayer = PackedPlayerBuffer[pnum]; |
|
|
|
|
|
|
|
|
|
if (sgwPackPlrOffsetTbl[pnum] != SDL_SwapLE16(header.wOffset)) { |
|
|
|
|
|