Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix item command and fix InventoryManager.Add - #576

Merged
AngeloTadeucci merged 4 commits into
masterfrom
item-command
Sep 30, 2025
Merged

Fix item command and fix InventoryManager.Add#576
AngeloTadeucci merged 4 commits into
masterfrom
item-command

Conversation

@AngeloTadeucci

@AngeloTadeucciAngeloTadeucci commented Sep 30, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Centralized drop API that consolidates spawning and broadcasting; supports ownership context for dropped items.
    • New inventory add flow that uses a unified helper to add items and surface failures.
  • Bug Fixes

    • Non-stackable drops capped at 100 per action; extras spawn as separate items.
    • Stackable items clamp to slot max and stack correctly.
    • Inventory adds fill partial stacks first, validate free slots up front, and reject adds when not in a valid field.

@coderabbitai

coderabbitaiBot commented Sep 30, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

Separates drop vs give flows: ItemCommand now uses DropItem and GiveItem helpers with explicit drop rules; InventoryManager.Add is rewritten to multi‑step stacking with a session.Field null guard and explicit ItemDrop.CreateItem usage; field spawn/drop APIs consolidated to new SpawnItem/DropItem signatures and callers updated.

Changes

Cohort / File(s)Summary
Item command flow refactor
Maple2.Server.Game/Commands/ItemCommand.cs
Replaces prior ProcessSingleItem with explicit DropItem and GiveItem flows. Drop path: non‑stackable items capped at 100 and spawned individually; stackable items dropped as a single stack clamped to SlotMax. GiveItem encapsulates inventory add, error logging, discard on failure, and exit-code handling; non-drop path adds explicit slot checks and uses GiveItem consistently.
Inventory stacking rewrite
Maple2.Server.Game/Manager/Items/InventoryManager.cs
Adds guard rejecting Add when session.Field is null. Replaces per-unit recursion for SlotMax==1 with unified stacking: compute slotMax, fill partial stacks first, calculate full stacks + remainder, validate free slots, create stacks via session.Field.ItemDrop.CreateItem(...), and recursively Add each stack; retains standardized inventory-full error handling.
Field spawn/drop API & state
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs
Consolidates SpawnItem overloads to accept optional IFieldEntity? owner, sets FieldItem.Owner, removes older owner-specific overloads, and adds DropItem(...) helpers (owner and position variants) that create field items and broadcast drops.
Updated callers to use Field.DropItem
Maple2.Server.Game/Manager/MasteryManager.cs, Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs, Maple2.Server.Game/PacketHandlers/BreakableHandler.cs, Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs, Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs, Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs, Maple2.Server.Game/Trigger/TriggerContext.Field.cs
Replaces patterns of SpawnItem(...) + Broadcast(FieldPacket.DropItem(...)) with single session.Field.DropItem(...) calls (owner or position variants). Adjusts a few downstream usages (e.g., FunctionCube feed UID) to use item UIDs from created items or reward items as appropriate.

Sequence Diagram(s)

sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant ItemDrop as ItemDrop
participant Field as Field
participant Inv as InventoryManager
Admin->>Cmd: invoke /item (drop mode)
Cmd->>Sess: resolve session, metadata
alt Non-stackable (SlotMax == 1)
Cmd->>Cmd: clamp amount to 100
loop each unit up to cap
Cmd->>ItemDrop: CreateItem(id, rarity, 1)
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
else Stackable
Cmd->>ItemDrop: CreateItem(id, rarity, clamp(amount, SlotMax))
ItemDrop-->>Cmd: Item
Cmd->>Field: DropItem(position/owner, Item)
end
Cmd-->>Admin: ExitCode 0
Loading
sequenceDiagram
autonumber
actor Admin as Command Invoker
participant Cmd as ItemCommand
participant Sess as Session
participant Inv as InventoryManager
participant ItemDrop as ItemDrop
Admin->>Cmd: invoke /item (give mode)
Cmd->>Sess: resolve session, metadata
Cmd->>Inv: GiveItem(ctx, item)
Inv->>Sess: check session.Field != null
alt field null
Inv-->>Cmd: warn + false
Cmd-->>Admin: ExitCode 1
else
Inv->>Inv: determine slotMax, fill partial stacks
Inv->>Inv: compute fullStacks and remainder
alt insufficient free slots
Inv-->>Cmd: send inventory error
Cmd-->>Admin: ExitCode 1
else
loop each stack chunk
Inv->>ItemDrop: CreateItem(id, rarity, chunkAmount)
ItemDrop-->>Inv: Item
Inv-->>Cmd: add Item (success)
end
Cmd-->>Admin: ExitCode 0
end
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Zintixx

Poem

A rabbit hops with joyful cheer,
I drop small stacks and keep them near.
I cap the piles and fill each slot,
I nudge the fields and skip a spot.
Hooray — items land; the meadow’s hot! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 9.09% which is insufficient. The required threshold is 80.00%.You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title Check✅ PassedThe title accurately references fixes to the item command and the InventoryManager.Add method, which correspond directly to modifications in the ItemCommand.cs and InventoryManager.cs files. Although the pull request also encompasses broader refactoring of item drop logic across multiple modules, the title remains specific and pertinent to two of the core changes implemented. Therefore, it is sufficiently clear and relevant to the changeset.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d4984 and 872e1fc.

📒 Files selected for processing (4)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

179-221: Check Add return in partial-fill loop
In the partial-stack filling loop you call Add(itemToStack, notifyNew, commit) without checking its return value, so a database failure there would be ignored and lead to lost items—change it to

if(!Add(itemToStack,notifyNew,commit))returnfalse;

to prevent silent failures.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17beeb1 and 2d32ffb.

📒 Files selected for processing (2)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
Maple2.Server.Game/Commands/ItemCommand.cs (4)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (591-599)
  • FreeSlots (579-583)
  • Add (149-276)
  • Discard (730-749)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (1)

151-154: Field null guard prevents additions outside of field context.

The guard correctly rejects additions when session.Field is null. This is necessary because the new stacking logic relies on session.Field.ItemDrop.CreateItem for item creation (lines 190, 206, 214).

Maple2.Server.Game/Commands/ItemCommand.cs (8)

7-7: LGTM!

Added import for ItemInventoryError is necessary for the error handling at line 85.


45-45: Direct field access is safe due to guard at line 41.

The change from optional access (session.Field?.ItemDrop.CreateItem) to direct access (session.Field.ItemDrop.CreateItem) is safe because of the null check at line 41 that returns early if session.Field is null.


51-55: Currency handling uses GiveItem helper correctly.

The currency path now delegates to GiveItem, which properly handles addition failures by discarding the item and logging an error.


59-80: Drop logic correctly handles stackable vs non-stackable items.

The drop path distinguishes between:

  1. Non-stackable items (SlotMax == 1): Drops up to 100 individual items
  2. Stackable items: Drops a single stack clamped to SlotMax

The 100-item cap for non-stackable drops prevents spam/abuse.


82-103: Free slots check for non-stackable items prevents inventory overflow.

The logic:

  1. Checks available free slots before attempting to add non-stackable items
  2. Clamps the amount to available slots
  3. Uses GiveItem which aborts on failure

However, there's a potential issue: the FreeSlots check is performed once at the beginning, but the loop doesn't re-check after each successful addition. If another concurrent operation consumes slots, subsequent additions could fail.

This is a minor edge case since the code is wrapped in a lock at the InventoryManager level, but the failure handling via GiveItem returning false will abort the operation.


104-109: Stackable item handling correctly delegates to Add method.

For stackable items, the amount is set directly on the item and GiveItem is called once. This delegates the stack splitting logic to InventoryManager.Add, which handles the multi-step stacking.


119-123: DropItem helper correctly spawns and broadcasts item drops.

The helper properly:

  1. Guards against null field
  2. Spawns the item in the field
  3. Broadcasts the drop event to all players

125-131: GiveItem helper properly handles inventory addition failures.

The helper:

  1. Attempts to add the item to inventory with notifyNew = true
  2. On failure, discards the item (preventing leaks)
  3. Logs an error message to the console
  4. Sets exit code and returns false to abort

This ensures proper cleanup and error reporting.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (3)

198-205: Open slots check should precede partial stack fills.

The stacksNeeded calculation and open slots validation (lines 198-205) occur after attempting to fill partial stacks (lines 185-196). If the inventory lacks sufficient space, some partial stacks may already have been added before the error is detected.

While the error handling in lines 192-195 prevents silent failures during partial fills, moving the capacity check before line 185 would avoid unnecessary work and provide clearer early validation.

Consider this refactor to validate capacity upfront:

+ // Calculate space requirements upfront+ int existingPartialSlots = items.Count(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired());+ int maxFillableFromPartials = existingPartialSlots > 0 + ? items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())+ .Sum(x => slotMax - x.Amount)+ : 0;+ int amountAfterPartials = Math.Max(0, totalAmount - maxFillableFromPartials);+ int fullStacks = amountAfterPartials / slotMax;+ int remainder = amountAfterPartials % slotMax;+ int stacksNeeded = fullStacks + (remainder > 0 ? 1 : 0);++ if (items.OpenSlots < stacksNeeded) {+ session.Send(ItemInventoryPacket.Error(s_err_inventory));+ return false;+ }+
// 1. Fill partially filled stacks first
foreach (Item existing in items.Where(x => x.Id == add.Id && x.Rarity == add.Rarity && x.Amount < slotMax && !x.IsExpired())) {

Based on learnings


207-213: Pass amount directly to CreateItem for consistency.

Lines 209-211 create an item with the default amount (1) and then manually override it to slotMax. This is inconsistent with the partial stack creation at line 190, which passes the amount directly: CreateItem(add.Id, add.Rarity, toFill).

For clarity and consistency, pass slotMax as the amount parameter to CreateItem.

Apply this diff:

 // 2. Add full stacks
for (int i = 0; i < fullStacks; i++) {
- Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? stackItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, slotMax);
if (stackItem is null) return false;
- stackItem.Amount = slotMax;
if (!Add(stackItem, notifyNew, commit)) return false;
}

216-221: Pass amount directly to CreateItem for remainder stack.

Similar to the full stacks, lines 217-219 create an item and then manually set the amount to remainder. For consistency with line 190, pass remainder directly to CreateItem.

Apply this diff:

 // 3. Add remainder stack
if (remainder > 0) {
- Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity);+ Item? remainderItem = session.Field.ItemDrop.CreateItem(add.Id, add.Rarity, remainder);
if (remainderItem is null) return false;
- remainderItem.Amount = remainder;
if (!Add(remainderItem, notifyNew, commit)) return false;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32ffb and 8ff7da1.

📒 Files selected for processing (1)
  • Maple2.Server.Game/Manager/Items/InventoryManager.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsExpired (94-94)
Maple2.Server.Core/Network/Session.cs (2)
  • Send (145-145)
  • Send (147-147)
Maple2.Server.Game/Packets/ItemInventoryPacket.cs (1)
  • ItemInventoryPacket (11-150)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (2)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (2)

151-154: Good defensive guard.

The null check for session.Field prevents potential null reference exceptions when calling session.Field.ItemDrop.CreateItem in the stacking logic below.


185-196: Error handling improved for partial stack fills.

The code now properly checks the return value of recursive Add calls (lines 192-195) and returns false with logging on failure, addressing the silent failure concern from previous reviews.

Comment threadMaple2.Server.Game/Manager/Items/InventoryManager.cs
Comment threadMaple2.Server.Game/Commands/ItemCommand.cs Outdated

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff7da1 and 68d4984.

📒 Files selected for processing (10)
  • Maple2.Server.Game/Commands/ItemCommand.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2 hunks)
  • Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1 hunks)
  • Maple2.Server.Game/Manager/MasteryManager.cs (1 hunks)
  • Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3 hunks)
  • Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (1 hunks)
  • Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1 hunks)
  • Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (2)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Model/Field/Actor/FieldNpc.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/MasteryManager.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Commands/ItemCommand.cs (5)
Maple2.Server.Game/Manager/Items/InventoryManager.cs (4)
  • Item (594-602)
  • FreeSlots (582-586)
  • Add (149-279)
  • Discard (733-752)
Maple2.Server.Game/Manager/Items/ItemDropManager.cs (1)
  • Item (294-316)
Maple2.Model/ModelExtensions.cs (1)
  • IsCurrency (87-87)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (3)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (5)
  • FieldItem (73-73)
  • FieldItem (74-74)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FieldPacket.cs (1)
  • FieldPacket (19-353)
Maple2.Server.Game/Trigger/TriggerContext.Field.cs (4)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (2)
  • DropItem (76-76)
  • DropItem (77-77)
Maple2.Server.Game/PacketHandlers/ItemInventoryHandler.cs (1)
  • DropItem (91-118)
Maple2.Server.Game/Model/Field/Actor/FieldPet.cs (1)
  • DropItem (92-111)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (1)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (4)
  • FieldItem (247-262)
  • FieldItem (264-276)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (5)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.State.cs (2)
  • DropItem (278-281)
  • DropItem (283-286)
Maple2.Server.Game/Manager/Field/FieldManager/IField.cs (3)
  • DropItem (76-76)
  • DropItem (77-77)
  • Broadcast (66-66)
Maple2.Database/Storage/Game/GameStorage.Nurturing.cs (1)
  • UpdateNurturing (33-49)
Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs (1)
  • Broadcast (695-704)
Maple2.Server.Game/Packets/FunctionCubePacket.cs (1)
  • FunctionCubePacket (11-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (9)
Maple2.Server.Game/Manager/MasteryManager.cs (1)

210-211: DropItem usage maintains gather ownership. Passing the characterId into the centralized helper keeps gather rewards instanced while leveraging the shared drop path.

Maple2.Server.Game/Trigger/TriggerContext.Field.cs (2)

419-420: DropItem centralization retains fixed-position drops. Routing event spawn rewards through DropItem(... fixedPosition: true) keeps placement behavior unchanged while reusing the new helper.


445-446: Consistent drop handling for range spawns. This mirrors the earlier loop so range-triggered rewards also benefit from the unified DropItem flow.

Maple2.Server.Game/PacketHandlers/InteractObjectHandler.cs (2)

98-101: Drop path alignment looks good. Setting the interact object as owner and forwarding the characterId preserves instanced drops while using the centralized helper.


104-107: Secondary drop path mirrors the new helper. The individual-box rewards get the same ownership treatment, so both flows stay consistent.

Maple2.Server.Game/PacketHandlers/BreakableHandler.cs (1)

50-51: Breakable drop now flows through DropItem. Supplying the breakable as owner together with the characterId keeps attribution intact while simplifying the broadcast.

Maple2.Server.Game/PacketHandlers/FunctionCubeHandler.cs (3)

126-127: Stage reward leverages unified drop path. Using DropItem with the player owner keeps the reward instanced as before without manual spawn/broadcast plumbing.


150-156: Feed reward flow stays coherent. The drop helper plus reusing rewardItem.Uid for the feed packet preserves client updates while sharing the new drop logic.


183-184: Play reward drop matches the other branches. This mirrors the nurturing paths so every reward now funnels through the centralized helper.

Comment threadMaple2.Server.Game/Commands/ItemCommand.cs
@AngeloTadeucci
AngeloTadeucci merged commit c0f27c0 into masterSep 30, 2025
3 of 4 checks passed
@AngeloTadeucci
AngeloTadeucci deleted the item-command branch September 30, 2025 22:32
@coderabbitaicoderabbitaiBot mentioned this pull request Feb 21, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@AngeloTadeucci@Zintixx