From e2af641c035d833c4246a275fa617fbf3aee5d3a Mon Sep 17 00:00:00 2001 From: Eric Robinson Date: Tue, 9 Dec 2025 16:54:32 -0500 Subject: [PATCH 1/3] Fix Delta Items --- Source/msg.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 47cf3c5c6..91f6aec91 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -233,8 +233,10 @@ struct DSpawnedMonster { int16_t golemSpellLevel; }; +constexpr int MaxDeltaItems = MAXITEMS * 2; + struct DLevel { - TCmdPItem item[MAXITEMS]; + TCmdPItem item[MaxDeltaItems]; ankerl::unordered_dense::map object; ankerl::unordered_dense::map spawnedMonsters; DMonsterStr monster[MaxMonsters]; @@ -531,7 +533,7 @@ int WaitForTurns() std::byte *DeltaExportItem(std::byte *dst, const TCmdPItem *src) { - for (int i = 0; i < MAXITEMS; i++, src++) { + for (int i = 0; i < MaxDeltaItems; i++, src++) { if (src->bCmd == CMD_INVALID) { *dst++ = std::byte { 0xFF }; } else { @@ -546,7 +548,7 @@ std::byte *DeltaExportItem(std::byte *dst, const TCmdPItem *src) const std::byte *DeltaImportItem(const std::byte *src, const std::byte *end, TCmdPItem *dst) { size_t size = 0; - for (int i = 0; i < MAXITEMS; i++, dst++) { + for (int i = 0; i < MaxDeltaItems; i++, dst++) { if (&src[size] >= end) return nullptr; if (src[size] == std::byte { 0xFF }) { @@ -1252,7 +1254,7 @@ size_t OnGotoGetItem(const TCmdLocParam1 &message, Player &player) { const Point position { message.x, message.y }; - if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && Swap16LE(message.wParam1) < MAXITEMS + 1) { + if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && Swap16LE(message.wParam1) < MaxDeltaItems + 1) { MakePlrPath(player, position, false); player.destAction = ACTION_PICKUPITEM; player.destParam1 = Swap16LE(message.wParam1); @@ -1267,7 +1269,7 @@ bool IsGItemValid(const TCmdGItem &message) return false; if (message.bPnum >= Players.size()) return false; - if (message.bCursitem >= MAXITEMS + 1) + if (message.bCursitem >= MaxDeltaItems + 1) return false; if (!IsValidLevelForMultiplayer(message.bLevel)) return false; @@ -1504,7 +1506,7 @@ size_t OnGotoAutoGetItem(const TCmdLocParam1 &message, Player &player) const Point position { message.x, message.y }; const uint16_t itemIdx = Swap16LE(message.wParam1); - if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && itemIdx < MAXITEMS + 1) { + if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && itemIdx < MaxDeltaItems + 1) { MakePlrPath(player, position, false); player.destAction = ACTION_PICKUPAITEM; player.destParam1 = itemIdx; From b97bfcb40756afc0767a688e954553dbaa0b5000 Mon Sep 17 00:00:00 2001 From: Eric Robinson Date: Tue, 9 Dec 2025 17:03:06 -0500 Subject: [PATCH 2/3] Update msg.cpp --- Source/msg.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 91f6aec91..ce578df00 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1254,7 +1254,7 @@ size_t OnGotoGetItem(const TCmdLocParam1 &message, Player &player) { const Point position { message.x, message.y }; - if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && Swap16LE(message.wParam1) < MaxDeltaItems + 1) { + if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && Swap16LE(message.wParam1) < MAXITEMS + 1) { MakePlrPath(player, position, false); player.destAction = ACTION_PICKUPITEM; player.destParam1 = Swap16LE(message.wParam1); @@ -1269,7 +1269,7 @@ bool IsGItemValid(const TCmdGItem &message) return false; if (message.bPnum >= Players.size()) return false; - if (message.bCursitem >= MaxDeltaItems + 1) + if (message.bCursitem >= MAXITEMS + 1) return false; if (!IsValidLevelForMultiplayer(message.bLevel)) return false; @@ -1506,7 +1506,7 @@ size_t OnGotoAutoGetItem(const TCmdLocParam1 &message, Player &player) const Point position { message.x, message.y }; const uint16_t itemIdx = Swap16LE(message.wParam1); - if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && itemIdx < MaxDeltaItems + 1) { + if (gbBufferMsgs != 1 && player.isOnActiveLevel() && InDungeonBounds(position) && itemIdx < MAXITEMS + 1) { MakePlrPath(player, position, false); player.destAction = ACTION_PICKUPAITEM; player.destParam1 = itemIdx; From c55a1f4d66808af7e8ccfa5e506a1f04ee140f87 Mon Sep 17 00:00:00 2001 From: Eric Robinson Date: Tue, 9 Dec 2025 17:28:03 -0500 Subject: [PATCH 3/3] Update CHANGELOG.md --- docs/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1617ce738..abaa2c6ea 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Bug Fixes + +#### Multiplayer + +- Potential item deletion when dropping a large amount of items and leaving the level + ## DevilutionX 1.5.2 ### Bug Fixes