Procházet zdrojové kódy

[11] fix(inventory): refuse to dismantle a locked item

Review: locked items can be dismantled.
Resolution: staging a dismantle refuses an item carrying the native
locked bit.

stage_item_dismantle checked ownership, placement and row resolution but
never read the item's state flags, so a locked item dismantled like any
other.

Names the native locked bit and refuses the staging when it is set. The
bit was confirmed against the installed build rather than assumed: three
observed lock and unlock transitions moved flags between 0x0 and 0x1 on
an unequipped item.

This is defence in depth rather than a repair of something reachable in
play. The Client gates the action itself and sends no opcode 402 for a
locked item, which the same capture confirmed, so only a request that
skips the Client could reach the staging. The Server should not depend
on the Client declining to ask.

Thomas Shields před 3 týdny
rodič
revize
f640855afd

+ 5 - 0
Sunrise/src/state/account/inventory/inventory_state.h

@@ -55,6 +55,11 @@ inline constexpr std::size_t kProfileItemCapacity = 701;
 inline constexpr std::size_t kProfileActionSourceCapacity = 100;
 /** Runtime-owned SOIDs for profile stacks use a namespace separate from created item instances. */
 inline constexpr std::uint64_t kFirstProfileItemInstanceSoid = 0x5000000000000001ULL;
+/**
+ * Native item-state bit the Client sets to lock one item against destruction.
+ * Confirmed against the installed build by three observed lock and unlock transitions.
+ */
+inline constexpr std::uint32_t kLockedItemFlag = 0x1;
 /**
  * The 16 supported character equipment buckets reserve 151 native rows in this build. One row
 

+ 3 - 1
Sunrise/src/state/runtime/state_account_runtime.cpp

@@ -1637,7 +1637,9 @@ apply_dismantle_rewards(const AccountState& before,
             break;
         }
     }
-    if (inventoryIndex >= before.inventory.count) {
+    if (inventoryIndex >= before.inventory.count
+        || (before.inventory.values[inventoryIndex].flags & authored_inventory::kLockedItemFlag)
+               != 0) {
         return false;
     }