Skip to content

Inbound 26.1 item wire + PacketDecoder MixinExtras; snapshot-2#3

Merged
ohnodev merged 3 commits intomainfrom
fix/inbound-item-wire-decode
Apr 12, 2026
Merged

Inbound 26.1 item wire + PacketDecoder MixinExtras; snapshot-2#3
ohnodev merged 3 commits intomainfrom
fix/inbound-item-wire-decode

Conversation

@ohnodev
Copy link
Copy Markdown
Owner

@ohnodev ohnodev commented Apr 12, 2026

Summary

Brings 26.1→26.2 item stack wire handling for serverbound traffic and fixes a runtime mixin crash that broke new connections when the first player/channel loaded PacketDecoder.

What changed

Inbound item wire (already on branch, commit ef3aeb3)

  • LegacyItemIdTable: legacy wire id ↔ server item id; serverItemIdFromLegacyWire() for inbound.
  • LegacyInboundDecoding: thread-local + re-entrant depth for inbound decode scope.
  • PacketDecoderMixin: establish decode context for legacy codecs (see below for implementation fix).
  • LegacyItemStackWireCodec, ItemStackOptionalCodecMixin (optional + untrusted), HashedStackActualItemMixin for container clicks.
  • legacylink.mixins.json: registers decoder + hashed stack mixins.

This PR (8e7a364)

  • @At("THROW") removed: Fabric’s Mixin rejects THROW as an injection point → PacketDecoder failed to transform on first connection (latest.log showed InvalidInjectionException).
  • MixinExtras @WrapMethod on PacketDecoder#decode: enterDecode / leaveDecode in try/finally so depth is correct on success and on codec exceptions.
  • LegacyLinkPreLaunch: MixinExtrasBootstrap.init() via fabric.mod.json preLaunch entrypoint.
  • Gradle: mixinextras-fabric 0.5.3 (annotationProcessor + implementation(include(...)) for jar-in-jar).
  • minecraft_version: 26.2-snapshot-2 (align compile target with production); README table + MixinExtras row.

Test notes

  • ./gradlew build passes.
  • Local server: join with 26.1.x to 127.0.0.1:25566 after deploying the built jar (includes nested MixinExtras).

Links

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added bidirectional wire-level item ID translation between protocol 26.2 and 26.1 with improved handling of optional/creative item stacks and container clicks for legacy clients.
    • Ensures decoding context is tracked during packet processing to make legacy translations reliable.
  • Chores

    • Bumped project version to 0.1.1 and updated prebuilt artifact/docs.
    • Updated Minecraft snapshot to 26.2-snapshot-2.
    • Embedded MixinExtras and registered a pre-launch initializer.

ohnodev added 2 commits April 12, 2026 15:53
- Build legacy→server inverse map in LegacyItemIdTable (collision → stone).
- Scope legacy decode to PacketDecoder#decode via LegacyInboundDecoding (reentrant-safe).
- LegacyItemStackWireCodec: decode/encode optional stacks with trusted + delimited patches.
- Wrap HashedStack.ActualItem.STREAM_CODEC for ServerboundContainerClickPacket.
- Version 0.1.1; README + prebuilt jar.

Made-with: Cursor
- Replace @Inject @at(THROW) (unsupported on this Mixin) with @WrapMethod +
  try/finally so LegacyInboundDecoding always leaves decode cleanly.
- Add MixinExtras 0.5.3 (annotationProcessor + jar-in-jar) and preLaunch
  entrypoint (MixinExtrasBootstrap.init()).
- Compile against Minecraft 26.2-snapshot-2; document MixinExtras in README.

Made-with: Cursor
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1bdd420c-d789-4020-8f5c-99da6e7f49c5

📥 Commits

Reviewing files that changed from the base of the PR and between 8e7a364 and 6035d25.

📒 Files selected for processing (3)
  • src/main/java/dev/ohno/legacylink/encoding/LegacyItemStackWireCodec.java
  • src/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java
  • src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/dev/ohno/legacylink/encoding/LegacyItemStackWireCodec.java

📝 Walkthrough

Walkthrough

This PR bumps the project from v0.1.0 → v0.1.1, adds MixinExtras and a pre-launch entrypoint, updates the Minecraft snapshot baseline to 26.2-snapshot-2, and implements inbound legacy wire-level item-id translation via thread-local decoder context, new codecs, mixins, and an inverse legacy→server item-id map.

Changes

Cohort / File(s) Summary
Configuration & Versioning
README.md, build.gradle.kts, gradle.properties
Bump release to 0.1.1, add io.github.llamalad7:mixinextras-fabric:0.5.3 as an embedded dependency, and update minecraft_version to 26.2-snapshot-2; README prebuilt artifact/checksum updated.
Fabric Loader Integration
src/main/resources/fabric.mod.json
Register dev.ohno.legacylink.LegacyLinkPreLaunch as a pre-launch entrypoint.
Pre-Launch Entrypoint
src/main/java/dev/ohno/legacylink/LegacyLinkPreLaunch.java
New PreLaunchEntrypoint that calls MixinExtrasBootstrap.init() during pre-launch.
Inbound Packet Decoder Context
src/main/java/dev/ohno/legacylink/encoding/LegacyInboundDecoding.java, src/main/java/dev/ohno/legacylink/mixin/PacketDecoderMixin.java
Add thread-local decoder context with enter/leave APIs and mixin to bracket PacketDecoder#decode, ensuring context cleanup on exceptions.
Item Stack Wire Codecs & Mixins
src/main/java/dev/ohno/legacylink/encoding/LegacyItemStackWireCodec.java, src/main/java/dev/ohno/legacylink/mixin/ItemStackOptionalCodecMixin.java, src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java
Introduce legacy-aware optional item-stack wire codec and refactor mixins to delegate to it; add mixin wrapping HashedStack.ActualItem codec for legacy encode/decode.
Legacy Item ID Mapping
src/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java
Add inverse lookup legacyToServer and public API serverItemIdFromLegacyWire(int) to translate inbound 26.1 legacy wire IDs to 26.2 server numeric item IDs with Stone fallback.
Mixin Configuration
src/main/resources/legacylink.mixins.json
Register new mixins HashedStackActualItemMixin and PacketDecoderMixin.

Sequence Diagram(s)

sequenceDiagram
    participant Netty as Netty I/O
    participant PD as PacketDecoderMixin
    participant LID as LegacyInboundDecoding
    participant Codec as LegacyItemStackWireCodec
    participant LIT as LegacyItemIdTable
    participant Reg as BuiltInRegistries.ITEM

    Netty->>PD: decode(ctx, input, out)
    PD->>LID: enterDecode(ctx.channel())
    PD->>PD: original.decode(ctx, input, out)
    PD->>Codec: decodeOptional(...) (item stacks)
    Codec->>LID: connection()
    alt legacy connection active
        Codec->>LIT: serverItemIdFromLegacyWire(legacyWireId)
        LIT->>Reg: lookup item holder by server id (fallback STONE)
        Codec->>Codec: decode DataComponentPatch / construct ItemStack
    else non-legacy or no connection
        Codec->>Codec: delegate to vanilla codec
    end
    PD->>LID: leaveDecode()
    PD->>Netty: return decoded packets
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰
I nudge the mixins, tap the thread,
Old IDs find new homes instead—
Pre-launch boots and codecs sing,
Stone stands ready for anything,
Version hops forward, ears aloft with glee.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main changes: adding inbound 26.1 item wire decoding support and integrating MixinExtras for PacketDecoder fixes, targeting Minecraft snapshot-2.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/inbound-item-wire-decode

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java (1)

131-138: Minor: Redundant negative check on line 137.

The sid >= 0 check is always true given how buildLegacyToServerInverse constructs the array (all values are either stoneServerId or valid server IDs from toLegacyTable indices). However, this is acceptable defensive coding.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java` around
lines 131 - 138, The conditional in serverItemIdFromLegacyWire redundantly
checks "sid >= 0" even though buildLegacyToServerInverse guarantees entries are
either valid server IDs or stoneServerItemId; simplify the method by removing
the unnecessary negative check and directly return the mapped value (use
legacyToServer and stoneServerItemId as currently referenced), or if you prefer
defensive coding keep the bounds check for legacyWireId but change the final
return to just "return sid;" to avoid the redundant comparison.
src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java (1)

45-54: Consolidate legacy item-id remap logic to avoid divergence.

The decode/encode remap + fallback logic here duplicates the same pattern already centralized in src/main/java/dev/ohno/legacylink/encoding/LegacyItemStackWireCodec.java. Extracting shared helpers (e.g., id translation + fallback resolution) would reduce protocol drift risk in future snapshot bumps.

Also applies to: 64-67

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java`
around lines 45 - 54, The decode path in HashedStackActualItemMixin duplicates
the legacy wire-id remap + fallback logic (wireItemId ->
LegacyItemIdTable.serverItemIdFromLegacyWire -> BuiltInRegistries.ITEM.byId ->
fallback to Items.STONE) that already exists in LegacyItemStackWireCodec; add a
shared helper in LegacyItemStackWireCodec (e.g., resolveHolderFromWireId(int
wireId) or resolveItemHolder(int wireId)) to encapsulate translation and
fallback, then replace the duplicated code in HashedStackActualItemMixin (and
the similar block at the 64-67 range) to call that helper (use the same
Holder<Item> return to construct HashedStack.ActualItem), ensuring all
remap/fallback behavior is centralized.
🤖 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/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java`:
- Around line 131-138: The conditional in serverItemIdFromLegacyWire redundantly
checks "sid >= 0" even though buildLegacyToServerInverse guarantees entries are
either valid server IDs or stoneServerItemId; simplify the method by removing
the unnecessary negative check and directly return the mapped value (use
legacyToServer and stoneServerItemId as currently referenced), or if you prefer
defensive coding keep the bounds check for legacyWireId but change the final
return to just "return sid;" to avoid the redundant comparison.

In `@src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java`:
- Around line 45-54: The decode path in HashedStackActualItemMixin duplicates
the legacy wire-id remap + fallback logic (wireItemId ->
LegacyItemIdTable.serverItemIdFromLegacyWire -> BuiltInRegistries.ITEM.byId ->
fallback to Items.STONE) that already exists in LegacyItemStackWireCodec; add a
shared helper in LegacyItemStackWireCodec (e.g., resolveHolderFromWireId(int
wireId) or resolveItemHolder(int wireId)) to encapsulate translation and
fallback, then replace the duplicated code in HashedStackActualItemMixin (and
the similar block at the 64-67 range) to call that helper (use the same
Holder<Item> return to construct HashedStack.ActualItem), ensuring all
remap/fallback behavior is centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5186567e-a312-49b0-ad20-2445f5a92d2a

📥 Commits

Reviewing files that changed from the base of the PR and between 599e476 and 8e7a364.

⛔ Files ignored due to path filters (1)
  • prebuilt/legacylink-0.1.1.jar is excluded by !**/*.jar
📒 Files selected for processing (12)
  • README.md
  • build.gradle.kts
  • gradle.properties
  • src/main/java/dev/ohno/legacylink/LegacyLinkPreLaunch.java
  • src/main/java/dev/ohno/legacylink/encoding/LegacyInboundDecoding.java
  • src/main/java/dev/ohno/legacylink/encoding/LegacyItemStackWireCodec.java
  • src/main/java/dev/ohno/legacylink/mapping/LegacyItemIdTable.java
  • src/main/java/dev/ohno/legacylink/mixin/HashedStackActualItemMixin.java
  • src/main/java/dev/ohno/legacylink/mixin/ItemStackOptionalCodecMixin.java
  • src/main/java/dev/ohno/legacylink/mixin/PacketDecoderMixin.java
  • src/main/resources/fabric.mod.json
  • src/main/resources/legacylink.mixins.json

- serverItemIdFromLegacyWire: drop redundant sid>=0 (inverse table is always valid)
- LegacyItemStackWireCodec.holderFromLegacyWireId for remap + byId + stone fallback
- HashedStackActualItemMixin decode uses shared helper (matches optional stack decode)

Made-with: Cursor
@ohnodev ohnodev merged commit 854d3af into main Apr 12, 2026
1 check passed
@ohnodev ohnodev deleted the fix/inbound-item-wire-decode branch April 12, 2026 19:13
Sign up for free to 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.

1 participant