fix: inventory move leaves source slot uncleared on client#2089
fix: inventory move leaves source slot uncleared on client#2089erwan-joly merged 1 commit intomasterfrom
Conversation
The client never removed the item from the source slot after mvi / mve
because the server was sending ivn {slot}.-1.0.0.0: the hard-coded
VNum = -1 is the Serializer's null-sub-packet marker, but real NosTale
ivn for a cleared slot uses VNum = 0. The client ignores -1 and treats
0 as "empty" — so the populated destination showed up while the source
kept rendering the old item.
Consumes NosCore.Packets 17.0.0:
- IvnPacket / InvPacket / Stash* now carry List<IvnSubPacket> (inner
items non-nullable) so a cleared slot must be a concrete sub-packet
with VNum = 0 rather than a null entry the serializer would emit -1 for.
- IvnSubPacket gains two fields (Unknown5, Unknown6) so equipment ivn
matches the 7-field wire: 19.0.0.0.0.0.0 for a cleared equipment slot.
- InItemSubPacket swaps indices 2 and 3 so the wire emits
{amount} {isQuest} 0 {owner} matching traces of "in 9".
- InCharacterSubPacket audit: Unknown -> FairyBooster,
Morph -> FairyMorph, Unknown2 -> ShowInEffect, Unknown3 -> Morph.
The previously named "Morph" was actually the fairy's morph per
vanosilla; the character's morph lives one slot later.
NosCore side:
- ItemInstanceExtension.GenerateIvnSubPacket: null-item case now
returns a sub-packet with VNum = 0 instead of -1.
- PlayerBundleExtensions initializes InCharacterSubPacket with the
renamed fields (FairyBooster / FairyMorph / ShowInEffect / Morph).
- CharacterEntityExtension moves its inventory lists to the
non-nullable inner type.
- BiPacketHandlerTests "slot should be cleared" now asserts VNum = 0.
All 924 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughThe NosCore.Packets dependency is upgraded from version 16.9.0 to 17.0.0. Corresponding code changes adjust packet construction logic: inventory packet structures change from nullable to non-nullable element lists; redundant field assignments are removed; unknown placeholder fields are replaced with named properties; and test assertions are updated accordingly. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/NosCore.GameObject/Ecs/Extensions/ItemInstanceExtension.cs (1)
22-27: Make cleared-slotVNumexplicit instead of implicit default.At Line 26, only
Slotis assigned. Given this PR fixes a protocol-sensitive clear-slot path, explicitly settingVNum = 0improves safety and intent.Proposed change
if (itemInstance == null) { return new IvnSubPacket { - Slot = slot + Slot = slot, + VNum = 0 }; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/NosCore.GameObject/Ecs/Extensions/ItemInstanceExtension.cs` around lines 22 - 27, The returned IvnSubPacket when itemInstance is null omits an explicit VNum, relying on the implicit default; update the null branch that constructs the IvnSubPacket (where itemInstance == null) to set VNum = 0 along with Slot to make the cleared-slot value explicit (reference IvnSubPacket, itemInstance, slot, and VNum).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/NosCore.GameObject/Ecs/Extensions/ItemInstanceExtension.cs`:
- Around line 22-27: The returned IvnSubPacket when itemInstance is null omits
an explicit VNum, relying on the implicit default; update the null branch that
constructs the IvnSubPacket (where itemInstance == null) to set VNum = 0 along
with Slot to make the cleared-slot value explicit (reference IvnSubPacket,
itemInstance, slot, and VNum).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: b43dbbdd-e2f5-4f04-becb-8d49b9bc95ee
📒 Files selected for processing (5)
Directory.Packages.propssrc/NosCore.GameObject/Ecs/Extensions/CharacterEntityExtension.cssrc/NosCore.GameObject/Ecs/Extensions/ItemInstanceExtension.cssrc/NosCore.GameObject/Ecs/Extensions/PlayerBundleExtensions.cstest/NosCore.PacketHandlers.Tests/Inventory/BiPacketHandlerTests.cs
Summary
Why
Trace shows the server reply to `mvi 0 19 1 20` is two `ivn` packets, one zeroed (`ivn 0 19.0.0.0.0.0.0`) and one populated (`ivn 0 20.4998.0.0.0.0.0`). NosCore was producing `ivn 0 19.-1.0.0.0` — different VNum, fewer fields — and the client rendered the move as a duplicate instead of a reassignment.
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Chores
Bug Fixes
Tests