Skip to content

Commit

Permalink
Server: undo inventory client prediction
Browse files Browse the repository at this point in the history
The affected player inventory list is now marked as modified.
This way, it will also be re-sent if the server denies the action.
  • Loading branch information
SmallJoker committed Feb 2, 2025
1 parent 8caf922 commit b2a6c3b
Showing 1 changed file with 25 additions and 1 deletion.
26 changes: 25 additions & 1 deletion src/network/serverpackethandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,24 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
where the client made a bad prediction.
*/

auto mark_player_inv_list_dirty = [this](const InventoryLocation &loc,
const std::string &list_name) {

// Undo the client prediction of the affected list. See `clientApply`.
if (loc.type != InventoryLocation::PLAYER)
return;

Inventory *inv = m_inventory_mgr->getInventory(loc);
if (!inv)
return;

InventoryList *list = inv->getList(list_name);
if (!list)
return;

list->setModified(true);
};

const bool player_has_interact = checkPriv(player->getName(), "interact");

auto check_inv_access = [player, player_has_interact, this] (
Expand Down Expand Up @@ -651,8 +669,12 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
ma->to_inv.applyCurrentPlayer(player->getName());

m_inventory_mgr->setInventoryModified(ma->from_inv);
if (ma->from_inv != ma->to_inv)
mark_player_inv_list_dirty(ma->from_inv, ma->from_list);
bool inv_different = ma->from_inv != ma->to_inv;
if (inv_different)
m_inventory_mgr->setInventoryModified(ma->to_inv);
if (inv_different || ma->from_list != ma->to_list)
mark_player_inv_list_dirty(ma->to_inv, ma->to_list);

if (!check_inv_access(ma->from_inv) ||
!check_inv_access(ma->to_inv))
Expand Down Expand Up @@ -689,6 +711,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
da->from_inv.applyCurrentPlayer(player->getName());

m_inventory_mgr->setInventoryModified(da->from_inv);
mark_player_inv_list_dirty(da->from_inv, da->from_list);

/*
Disable dropping items out of craftpreview
Expand Down Expand Up @@ -721,6 +744,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
ca->craft_inv.applyCurrentPlayer(player->getName());

m_inventory_mgr->setInventoryModified(ca->craft_inv);
// Note: `ICraftAction::clientApply` is empty, thus nothing to revert.

// Disallow crafting if not allowed to interact
if (!player_has_interact) {
Expand Down

0 comments on commit b2a6c3b

Please sign in to comment.