Browse Source

Validate item network messages

pull/3105/head
Anders Jenbo 4 years ago
parent
commit
b4f699f0a3
  1. 2
      Source/gendung.cpp
  2. 4
      Source/gendung.h
  3. 4
      Source/loadsave.cpp
  4. 394
      Source/msg.cpp
  5. 6
      Source/msg.h
  6. 6
      Source/multi.cpp
  7. 2
      Source/multi.h
  8. 10
      Source/pack.cpp
  9. 2
      Source/pack.h
  10. 2
      Source/player.h
  11. 4
      test/writehero_test.cpp

2
Source/gendung.cpp

@ -35,7 +35,7 @@ std::array<bool, MAXTILES + 1> nTrapTable;
Point dminPosition;
Point dmaxPosition;
dungeon_type leveltype;
BYTE currlevel;
uint8_t currlevel;
bool setlevel;
_setlevels setlvlnum;
dungeon_type setlvltype;

4
Source/gendung.h

@ -86,6 +86,8 @@ enum _difficulty : uint8_t {
DIFF_NORMAL,
DIFF_NIGHTMARE,
DIFF_HELL,
DIFF_LAST = DIFF_HELL,
};
struct ScrollStruct {
@ -176,7 +178,7 @@ extern Point dmaxPosition;
/** Specifies the active dungeon type of the current game. */
extern dungeon_type leveltype;
/** Specifies the active dungeon level of the current game. */
extern BYTE currlevel;
extern uint8_t currlevel;
extern bool setlevel;
/** Specifies the active quest level of the current game. */
extern _setlevels setlvlnum;

4
Source/loadsave.cpp

@ -311,7 +311,7 @@ void LoadPlayer(LoadHelper &file, Player &player)
player.destParam2 = file.NextLE<int32_t>();
player.destParam3 = static_cast<Direction>(file.NextLE<int32_t>());
player.destParam4 = file.NextLE<int32_t>();
player.plrlevel = file.NextLE<int32_t>();
player.plrlevel = file.NextLE<uint32_t>();
player.position.tile.x = file.NextLE<int32_t>();
player.position.tile.y = file.NextLE<int32_t>();
player.position.future.x = file.NextLE<int32_t>();
@ -978,7 +978,7 @@ void SavePlayer(SaveHelper &file, const Player &player)
file.WriteLE<int32_t>(player.destParam2);
file.WriteLE<int32_t>(static_cast<int32_t>(player.destParam3));
file.WriteLE<int32_t>(player.destParam4);
file.WriteLE<int32_t>(player.plrlevel);
file.WriteLE<uint32_t>(player.plrlevel);
file.WriteLE<int32_t>(player.position.tile.x);
file.WriteLE<int32_t>(player.position.tile.y);
file.WriteLE<int32_t>(player.position.future.x);

394
Source/msg.cpp

@ -401,13 +401,13 @@ void DeltaLeaveSync(BYTE bLevel)
if (monster._mhitpoints == 0)
continue;
sgbDeltaChanged = true;
DMonsterStr *pD = &sgLevels[bLevel].monster[ma];
pD->_mx = monster.position.tile.x;
pD->_my = monster.position.tile.y;
pD->_mdir = monster._mdir;
pD->_menemy = encode_enemy(monster);
pD->_mhitpoints = monster._mhitpoints;
pD->_mactive = monster._msquelch;
DMonsterStr &delta = sgLevels[bLevel].monster[ma];
delta._mx = monster.position.tile.x;
delta._my = monster.position.tile.y;
delta._mdir = monster._mdir;
delta._menemy = encode_enemy(monster);
delta._mhitpoints = monster._mhitpoints;
delta._mactive = monster._msquelch;
}
memcpy(&sgLocals[bLevel].automapsv, AutomapView, sizeof(AutomapView));
}
@ -421,91 +421,87 @@ void DeltaSyncObject(int oi, _cmd_id bCmd, BYTE bLevel)
sgLevels[bLevel].object[oi].bCmd = bCmd;
}
bool DeltaGetItem(const TCmdGItem *pI, BYTE bLevel)
bool DeltaGetItem(const TCmdGItem &message, BYTE bLevel)
{
if (!gbIsMultiplayer)
return true;
TCmdPItem *pD = sgLevels[bLevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd == CMD_INVALID || pD->wIndx != pI->wIndx || pD->wCI != pI->wCI || pD->dwSeed != pI->dwSeed)
for (TCmdPItem &item : sgLevels[bLevel].item) {
if (item.bCmd == CMD_INVALID || item.wIndx != message.wIndx || item.wCI != message.wCI || item.dwSeed != message.dwSeed)
continue;
if (pD->bCmd == CMD_WALKXY) {
if (item.bCmd == CMD_WALKXY) {
return true;
}
if (pD->bCmd == CMD_STAND) {
if (item.bCmd == CMD_STAND) {
sgbDeltaChanged = true;
pD->bCmd = CMD_WALKXY;
item.bCmd = CMD_WALKXY;
return true;
}
if (pD->bCmd == CMD_ACK_PLRINFO) {
if (item.bCmd == CMD_ACK_PLRINFO) {
sgbDeltaChanged = true;
pD->bCmd = CMD_INVALID;
item.bCmd = CMD_INVALID;
return true;
}
app_fatal("delta:1");
}
if ((pI->wCI & CF_PREGEN) == 0)
if ((message.wCI & CF_PREGEN) == 0)
return false;
pD = sgLevels[bLevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd == CMD_INVALID) {
for (TCmdPItem &item : sgLevels[bLevel].item) {
if (item.bCmd == CMD_INVALID) {
sgbDeltaChanged = true;
pD->bCmd = CMD_WALKXY;
pD->x = pI->x;
pD->y = pI->y;
pD->wIndx = pI->wIndx;
pD->wCI = pI->wCI;
pD->dwSeed = pI->dwSeed;
pD->bId = pI->bId;
pD->bDur = pI->bDur;
pD->bMDur = pI->bMDur;
pD->bCh = pI->bCh;
pD->bMCh = pI->bMCh;
pD->wValue = pI->wValue;
pD->dwBuff = pI->dwBuff;
pD->wToHit = pI->wToHit;
pD->wMaxDam = pI->wMaxDam;
pD->bMinStr = pI->bMinStr;
pD->bMinMag = pI->bMinMag;
pD->bMinDex = pI->bMinDex;
pD->bAC = pI->bAC;
item.bCmd = CMD_WALKXY;
item.x = message.x;
item.y = message.y;
item.wIndx = message.wIndx;
item.wCI = message.wCI;
item.dwSeed = message.dwSeed;
item.bId = message.bId;
item.bDur = message.bDur;
item.bMDur = message.bMDur;
item.bCh = message.bCh;
item.bMCh = message.bMCh;
item.wValue = message.wValue;
item.dwBuff = message.dwBuff;
item.wToHit = message.wToHit;
item.wMaxDam = message.wMaxDam;
item.bMinStr = message.bMinStr;
item.bMinMag = message.bMinMag;
item.bMinDex = message.bMinDex;
item.bAC = message.bAC;
break;
}
}
return true;
}
void DeltaPutItem(const TCmdPItem *pI, int x, int y, BYTE bLevel)
void DeltaPutItem(const TCmdPItem &message, Point position, BYTE bLevel)
{
if (!gbIsMultiplayer)
return;
TCmdPItem *pD = sgLevels[bLevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd != CMD_WALKXY
&& pD->bCmd != CMD_INVALID
&& pD->wIndx == pI->wIndx
&& pD->wCI == pI->wCI
&& pD->dwSeed == pI->dwSeed) {
if (pD->bCmd == CMD_ACK_PLRINFO)
for (const TCmdPItem &item : sgLevels[bLevel].item) {
if (item.bCmd != CMD_WALKXY
&& item.bCmd != CMD_INVALID
&& item.wIndx == message.wIndx
&& item.wCI == message.wCI
&& item.dwSeed == message.dwSeed) {
if (item.bCmd == CMD_ACK_PLRINFO)
return;
app_fatal("%s", _("Trying to drop a floor item?"));
}
}
pD = sgLevels[bLevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd == CMD_INVALID) {
for (TCmdPItem &item : sgLevels[bLevel].item) {
if (item.bCmd == CMD_INVALID) {
sgbDeltaChanged = true;
memcpy(pD, pI, sizeof(TCmdPItem));
pD->bCmd = CMD_ACK_PLRINFO;
pD->x = x;
pD->y = y;
memcpy(&item, &message, sizeof(TCmdPItem));
item.bCmd = CMD_ACK_PLRINFO;
item.x = position.x;
item.y = position.y;
return;
}
}
@ -676,58 +672,87 @@ DWORD OnGotoGetItem(const TCmd *pCmd, Player &player)
return sizeof(message);
}
bool IsGItemValid(const TCmdGItem &message)
{
if (message.bMaster >= MAX_PLRS)
return false;
if (message.bPnum >= MAX_PLRS)
return false;
if (message.bCursitem >= MAXITEMS + 1)
return false;
if (message.bLevel >= NUMLEVELS)
return false;
if (!InDungeonBounds({ message.x, message.y }))
return false;
return IsItemAvailable(message.wIndx);
}
bool IsPItemValid(const TCmdPItem &message)
{
const Point position { message.x, message.y };
if (!InDungeonBounds(position))
return false;
return IsItemAvailable(message.wIndx);
}
DWORD OnRequestGetItem(const TCmd *pCmd, Player &player)
{
auto *p = (TCmdGItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdGItem *>(pCmd);
if (gbBufferMsgs != 1 && IOwnLevel(player.plrlevel)) {
if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
if (gbBufferMsgs != 1 && IOwnLevel(player.plrlevel) && IsGItemValid(message)) {
const Point position { message.x, message.y };
if (GetItemRecord(message.dwSeed, message.wCI, message.wIndx)) {
int ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed);
if (ii != -1) {
NetSendCmdGItem2(false, CMD_GETITEM, MyPlayerId, p->bPnum, *p);
if (p->bPnum != MyPlayerId)
SyncGetItem({ p->x, p->y }, p->wIndx, p->wCI, p->dwSeed);
NetSendCmdGItem2(false, CMD_GETITEM, MyPlayerId, message.bPnum, message);
if (message.bPnum != MyPlayerId)
SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed);
else
InvGetItem(MyPlayerId, &Items[ii], ii);
SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
} else if (!NetSendCmdReq2(CMD_REQUESTGITEM, MyPlayerId, p->bPnum, *p)) {
NetSendCmdExtra(*p);
SetItemRecord(message.dwSeed, message.wCI, message.wIndx);
} else if (!NetSendCmdReq2(CMD_REQUESTGITEM, MyPlayerId, message.bPnum, message)) {
NetSendCmdExtra(message);
}
}
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnGetItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdGItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdGItem *>(pCmd);
if (gbBufferMsgs == 1) {
SendPacket(pnum, p, sizeof(*p));
} else {
int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
if (DeltaGetItem(p, p->bLevel)) {
if ((currlevel == p->bLevel || p->bPnum == MyPlayerId) && p->bMaster != MyPlayerId) {
if (p->bPnum == MyPlayerId) {
if (currlevel != p->bLevel) {
SendPacket(pnum, &message, sizeof(message));
} else if (IsGItemValid(message)) {
const Point position { message.x, message.y };
int ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed);
if (DeltaGetItem(message, message.bLevel)) {
if ((currlevel == message.bLevel || message.bPnum == MyPlayerId) && message.bMaster != MyPlayerId) {
if (message.bPnum == MyPlayerId) {
if (currlevel != message.bLevel) {
auto &player = Players[MyPlayerId];
ii = SyncPutItem(player, player.position.tile, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
ii = SyncPutItem(player, player.position.tile, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC);
if (ii != -1)
InvGetItem(MyPlayerId, &Items[ii], ii);
} else {
InvGetItem(MyPlayerId, &Items[ii], ii);
}
} else {
SyncGetItem({ p->x, p->y }, p->wIndx, p->wCI, p->dwSeed);
SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed);
}
}
} else {
NetSendCmdGItem2(true, CMD_GETITEM, p->bMaster, p->bPnum, *p);
NetSendCmdGItem2(true, CMD_GETITEM, message.bMaster, message.bPnum, message);
}
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnGotoAutoGetItem(const TCmd *pCmd, Player &player)
@ -746,140 +771,149 @@ DWORD OnGotoAutoGetItem(const TCmd *pCmd, Player &player)
DWORD OnRequestAutoGetItem(const TCmd *pCmd, Player &player)
{
auto *p = (TCmdGItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdGItem *>(pCmd);
if (gbBufferMsgs != 1 && IOwnLevel(player.plrlevel)) {
if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
if (gbBufferMsgs != 1 && IOwnLevel(player.plrlevel) && IsGItemValid(message)) {
const Point position { message.x, message.y };
if (GetItemRecord(message.dwSeed, message.wCI, message.wIndx)) {
int ii = FindGetItem(message.wIndx, message.wCI, message.dwSeed);
if (ii != -1) {
NetSendCmdGItem2(false, CMD_AGETITEM, MyPlayerId, p->bPnum, *p);
if (p->bPnum != MyPlayerId)
SyncGetItem({ p->x, p->y }, p->wIndx, p->wCI, p->dwSeed);
NetSendCmdGItem2(false, CMD_AGETITEM, MyPlayerId, message.bPnum, message);
if (message.bPnum != MyPlayerId)
SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed);
else
AutoGetItem(MyPlayerId, &Items[p->bCursitem], p->bCursitem);
SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
} else if (!NetSendCmdReq2(CMD_REQUESTAGITEM, MyPlayerId, p->bPnum, *p)) {
NetSendCmdExtra(*p);
AutoGetItem(MyPlayerId, &Items[message.bCursitem], message.bCursitem);
SetItemRecord(message.dwSeed, message.wCI, message.wIndx);
} else if (!NetSendCmdReq2(CMD_REQUESTAGITEM, MyPlayerId, message.bPnum, message)) {
NetSendCmdExtra(message);
}
}
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnAutoGetItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdGItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdGItem *>(pCmd);
if (gbBufferMsgs == 1) {
SendPacket(pnum, p, sizeof(*p));
} else {
FindGetItem(p->wIndx, p->wCI, p->dwSeed);
if (DeltaGetItem(p, p->bLevel)) {
if ((currlevel == p->bLevel || p->bPnum == MyPlayerId) && p->bMaster != MyPlayerId) {
if (p->bPnum == MyPlayerId) {
if (currlevel != p->bLevel) {
SendPacket(pnum, &message, sizeof(message));
} else if (IsGItemValid(message)) {
const Point position { message.x, message.y };
if (DeltaGetItem(message, message.bLevel)) {
if ((currlevel == message.bLevel || message.bPnum == MyPlayerId) && message.bMaster != MyPlayerId) {
if (message.bPnum == MyPlayerId) {
if (currlevel != message.bLevel) {
auto &player = Players[MyPlayerId];
int ii = SyncPutItem(player, player.position.tile, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
int ii = SyncPutItem(player, player.position.tile, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC);
if (ii != -1)
AutoGetItem(MyPlayerId, &Items[ii], ii);
} else {
AutoGetItem(MyPlayerId, &Items[p->bCursitem], p->bCursitem);
AutoGetItem(MyPlayerId, &Items[message.bCursitem], message.bCursitem);
}
} else {
SyncGetItem({ p->x, p->y }, p->wIndx, p->wCI, p->dwSeed);
SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed);
}
}
} else {
NetSendCmdGItem2(true, CMD_AGETITEM, p->bMaster, p->bPnum, *p);
NetSendCmdGItem2(true, CMD_AGETITEM, message.bMaster, message.bPnum, message);
}
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnItemExtra(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdGItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdGItem *>(pCmd);
if (gbBufferMsgs == 1) {
SendPacket(pnum, p, sizeof(*p));
} else {
DeltaGetItem(p, p->bLevel);
SendPacket(pnum, &message, sizeof(message));
} else if (IsGItemValid(message)) {
const Point position { message.x, message.y };
DeltaGetItem(message, message.bLevel);
if (currlevel == Players[pnum].plrlevel)
SyncGetItem({ p->x, p->y }, p->wIndx, p->wCI, p->dwSeed);
SyncGetItem(position, message.wIndx, message.wCI, message.dwSeed);
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnPutItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdPItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdPItem *>(pCmd);
if (gbBufferMsgs == 1)
SendPacket(pnum, p, sizeof(*p));
else if (currlevel == Players[pnum].plrlevel) {
int ii;
if (pnum == MyPlayerId)
ii = InvPutItem(Players[pnum], { p->x, p->y });
else
ii = SyncPutItem(Players[pnum], { p->x, p->y }, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
if (ii != -1) {
PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
DeltaPutItem(p, Items[ii].position.x, Items[ii].position.y, Players[pnum].plrlevel);
if (gbBufferMsgs == 1) {
SendPacket(pnum, &message, sizeof(message));
} else if (IsPItemValid(message)) {
const Point position { message.x, message.y };
if (currlevel == Players[pnum].plrlevel) {
int ii;
if (pnum == MyPlayerId)
ii = InvPutItem(Players[pnum], position);
else
ii = SyncPutItem(Players[pnum], position, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC);
if (ii != -1) {
PutItemRecord(message.dwSeed, message.wCI, message.wIndx);
DeltaPutItem(message, Items[ii].position, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(message);
} else {
PutItemRecord(message.dwSeed, message.wCI, message.wIndx);
DeltaPutItem(message, position, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(*p);
} else {
PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
DeltaPutItem(p, p->x, p->y, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnSyncPutItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdPItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdPItem *>(pCmd);
if (gbBufferMsgs == 1)
SendPacket(pnum, p, sizeof(*p));
else if (currlevel == Players[pnum].plrlevel) {
int ii = SyncPutItem(Players[pnum], { p->x, p->y }, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
if (ii != -1) {
PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
DeltaPutItem(p, Items[ii].position.x, Items[ii].position.y, Players[pnum].plrlevel);
SendPacket(pnum, &message, sizeof(message));
else if (IsPItemValid(message)) {
const Point position { message.x, message.y };
if (currlevel == Players[pnum].plrlevel) {
int ii = SyncPutItem(Players[pnum], position, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC);
if (ii != -1) {
PutItemRecord(message.dwSeed, message.wCI, message.wIndx);
DeltaPutItem(message, Items[ii].position, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(message);
} else {
PutItemRecord(message.dwSeed, message.wCI, message.wIndx);
DeltaPutItem(message, position, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(*p);
} else {
PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
DeltaPutItem(p, p->x, p->y, Players[pnum].plrlevel);
CheckUpdatePlayer(pnum);
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnRespawnItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdPItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdPItem *>(pCmd);
if (gbBufferMsgs == 1) {
SendPacket(pnum, p, sizeof(*p));
} else {
SendPacket(pnum, &message, sizeof(message));
} else if (IsPItemValid(message)) {
const Point position { message.x, message.y };
auto &player = Players[pnum];
int playerLevel = player.plrlevel;
if (currlevel == playerLevel && pnum != MyPlayerId) {
SyncPutItem(player, { p->x, p->y }, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
SyncPutItem(player, position, message.wIndx, message.wCI, message.dwSeed, message.bId, message.bDur, message.bMDur, message.bCh, message.bMCh, message.wValue, message.dwBuff, message.wToHit, message.wMaxDam, message.bMinStr, message.bMinMag, message.bMinDex, message.bAC);
}
PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
DeltaPutItem(p, p->x, p->y, playerLevel);
PutItemRecord(message.dwSeed, message.wCI, message.wIndx);
DeltaPutItem(message, position, playerLevel);
}
return sizeof(*p);
return sizeof(message);
}
DWORD OnAttackTile(const TCmd *pCmd, Player &player)
@ -1578,14 +1612,14 @@ DWORD OnPlayerLevel(const TCmd *pCmd, int pnum)
DWORD OnDropItem(const TCmd *pCmd, int pnum)
{
auto *p = (TCmdPItem *)pCmd;
const auto &message = *reinterpret_cast<const TCmdPItem *>(pCmd);
if (gbBufferMsgs == 1)
SendPacket(pnum, p, sizeof(*p));
else
DeltaPutItem(p, p->x, p->y, Players[pnum].plrlevel);
SendPacket(pnum, &message, sizeof(message));
else if (IsPItemValid(message))
DeltaPutItem(message, { message.x, message.y }, Players[pnum].plrlevel);
return sizeof(*p);
return sizeof(message);
}
DWORD OnSendPlayerInfo(const TCmd *pCmd, int pnum)
@ -2049,42 +2083,40 @@ void DeltaAddItem(int ii)
if (!gbIsMultiplayer)
return;
TCmdPItem *pD = sgLevels[currlevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd != CMD_INVALID
&& pD->wIndx == Items[ii].IDidx
&& pD->wCI == Items[ii]._iCreateInfo
&& pD->dwSeed == Items[ii]._iSeed
&& (pD->bCmd == CMD_WALKXY || pD->bCmd == CMD_STAND)) {
for (const TCmdPItem &item : sgLevels[currlevel].item) {
if (item.bCmd != CMD_INVALID
&& item.wIndx == Items[ii].IDidx
&& item.wCI == Items[ii]._iCreateInfo
&& item.dwSeed == Items[ii]._iSeed
&& (item.bCmd == CMD_WALKXY || item.bCmd == CMD_STAND)) {
return;
}
}
pD = sgLevels[currlevel].item;
for (int i = 0; i < MAXITEMS; i++, pD++) {
if (pD->bCmd != CMD_INVALID)
for (TCmdPItem &item : sgLevels[currlevel].item) {
if (item.bCmd != CMD_INVALID)
continue;
sgbDeltaChanged = true;
pD->bCmd = CMD_STAND;
pD->x = Items[ii].position.x;
pD->y = Items[ii].position.y;
pD->wIndx = Items[ii].IDidx;
pD->wCI = Items[ii]._iCreateInfo;
pD->dwSeed = Items[ii]._iSeed;
pD->bId = Items[ii]._iIdentified ? 1 : 0;
pD->bDur = Items[ii]._iDurability;
pD->bMDur = Items[ii]._iMaxDur;
pD->bCh = Items[ii]._iCharges;
pD->bMCh = Items[ii]._iMaxCharges;
pD->wValue = Items[ii]._ivalue;
pD->wToHit = Items[ii]._iPLToHit;
pD->wMaxDam = Items[ii]._iMaxDam;
pD->bMinStr = Items[ii]._iMinStr;
pD->bMinMag = Items[ii]._iMinMag;
pD->bMinDex = Items[ii]._iMinDex;
pD->bAC = Items[ii]._iAC;
pD->dwBuff = Items[ii].dwBuff;
item.bCmd = CMD_STAND;
item.x = Items[ii].position.x;
item.y = Items[ii].position.y;
item.wIndx = Items[ii].IDidx;
item.wCI = Items[ii]._iCreateInfo;
item.dwSeed = Items[ii]._iSeed;
item.bId = Items[ii]._iIdentified ? 1 : 0;
item.bDur = Items[ii]._iDurability;
item.bMDur = Items[ii]._iMaxDur;
item.bCh = Items[ii]._iCharges;
item.bMCh = Items[ii]._iMaxCharges;
item.wValue = Items[ii]._ivalue;
item.wToHit = Items[ii]._iPLToHit;
item.wMaxDam = Items[ii]._iMaxDam;
item.bMinStr = Items[ii]._iMinStr;
item.bMinMag = Items[ii]._iMinMag;
item.bMinDex = Items[ii]._iMinDex;
item.bAC = Items[ii]._iAC;
item.dwBuff = Items[ii].dwBuff;
return;
}
}

6
Source/msg.h

@ -219,6 +219,9 @@ struct TCmdQuest {
uint8_t qvar1;
};
/**
* Represents an item being picked up from the ground
*/
struct TCmdGItem {
_cmd_id bCmd;
uint8_t bMaster;
@ -246,6 +249,9 @@ struct TCmdGItem {
int16_t bAC;
};
/**
* Represents an item being dropped onto the ground
*/
struct TCmdPItem {
_cmd_id bCmd;
uint8_t x;

6
Source/multi.cpp

@ -32,7 +32,6 @@ bool gbSomebodyWonGameKludge;
TBuffer sgHiPriBuf;
char szPlayerDescript[128];
uint16_t sgwPackPlrOffsetTbl[MAX_PLRS];
PlayerPack netplr[MAX_PLRS];
bool sgbPlayerTurnBitTbl[MAX_PLRS];
bool sgbPlayerLeftGameTbl[MAX_PLRS];
bool gbShouldValidatePackage;
@ -759,14 +758,14 @@ bool NetInit(bool bSinglePlayer)
void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
{
const char *szEvent;
static PlayerPack PackedPlayerBuffer[MAX_PLRS];
if (MyPlayerId == pnum) {
return;
}
assert(pnum >= 0 && pnum < MAX_PLRS);
auto &player = Players[pnum];
auto &packedPlayer = netplr[pnum];
auto &packedPlayer = PackedPlayerBuffer[pnum];
if (sgwPackPlrOffsetTbl[pnum] != header.wOffset) {
sgwPackPlrOffsetTbl[pnum] = 0;
@ -799,6 +798,7 @@ void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
player.plractive = true;
gbActivePlayers++;
const char *szEvent;
if (sgbPlayerTurnBitTbl[pnum]) {
szEvent = _("Player '{:s}' (level {:d}) just joined the game");
} else {

2
Source/multi.h

@ -63,6 +63,6 @@ void multi_process_network_packets();
void multi_send_zero_packet(int pnum, _cmd_id bCmd, const byte *data, size_t size);
void NetClose();
bool NetInit(bool bSinglePlayer);
void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &message, bool recv);
void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv);
} // namespace devilution

10
Source/pack.cpp

@ -193,21 +193,21 @@ bool UnPackPlayer(const PlayerPack *pPack, Player &player, bool netSync)
return false;
}
int dungeonLevel = pPack->plrlevel;
uint8_t dungeonLevel = pPack->plrlevel;
if (dungeonLevel >= NUMLEVELS) {
return false;
}
if (pPack->pClass > static_cast<int>(HeroClass::LAST)) {
if (pPack->pClass >= enum_size<HeroClass>::value) {
return false;
}
auto heroClass = static_cast<HeroClass>(pPack->pClass);
if (pPack->pLevel >= MAXCHARLEVEL) {
if (pPack->pLevel >= MAXCHARLEVEL || pPack->pLevel < 1) {
return false;
}
int difficulty = SDL_SwapLE32(pPack->pDifficulty);
if (difficulty > DIFF_HELL) {
uint32_t difficulty = SDL_SwapLE32(pPack->pDifficulty);
if (difficulty > DIFF_LAST) {
return false;
}

2
Source/pack.h

@ -39,7 +39,7 @@ struct PlayerPack {
uint8_t targx;
uint8_t targy;
char pName[PLR_NAME_LEN];
int8_t pClass;
uint8_t pClass;
uint8_t pBaseStr;
uint8_t pBaseMag;
uint8_t pBaseDex;

2
Source/player.h

@ -179,7 +179,7 @@ struct Player {
int destParam2;
Direction destParam3;
int destParam4;
int plrlevel;
uint8_t plrlevel;
ActorPosition position;
Direction _pdir; // Direction faced by player (direction enum)
int _pgfxnum; // Bitmask indicating what variant of the sprite the player is using. Lower byte define weapon (PlayerWeaponGraphic) and higher values define armour (starting with PlayerArmorGraphic)

4
test/writehero_test.cpp

@ -191,7 +191,7 @@ static void PackPlayerTest(PlayerPack *pPack)
for (auto i = 0; i < 7; i++)
pPack->InvBody[i].idx = -1;
strcpy(pPack->pName, "TestPlayer");
pPack->pClass = static_cast<int8_t>(HeroClass::Rogue);
pPack->pClass = static_cast<uint8_t>(HeroClass::Rogue);
pPack->pBaseStr = 20 + 35;
pPack->pBaseMag = 15 + 55;
pPack->pBaseDex = 30 + 220;
@ -286,7 +286,7 @@ static void AssertPlayer(Player &player)
ASSERT_EQ(player._pMaxHP, 16640);
ASSERT_EQ(player._pMana, 14624);
ASSERT_EQ(player._pMaxMana, 14624);
ASSERT_EQ(player._pNextExper, 2000);
ASSERT_EQ(player._pNextExper, 1583495809);
ASSERT_EQ(player._pMagResist, 75);
ASSERT_EQ(player._pFireResist, 16);
ASSERT_EQ(player._pLghtResist, 75);

Loading…
Cancel
Save