Skip to content

Fix unvanish skin layers and mod crashes by using vanilla entity trac…#15

Open
Madtrent wants to merge 1 commit into
modl-gg:devfrom
Madtrent:dev-madtrent
Open

Fix unvanish skin layers and mod crashes by using vanilla entity trac…#15
Madtrent wants to merge 1 commit into
modl-gg:devfrom
Madtrent:dev-madtrent

Conversation

@Madtrent

@Madtrent Madtrent commented May 24, 2026

Copy link
Copy Markdown

…ker packets

Confidence Score: 3/5

This should be fixed before merging.

  • The changed unvanish path can send entity pairing packets to viewers who should not track that player.
  • The same issue is copied across all changed Fabric adapters.
  • The normal vanilla same-world and tracking-distance checks are bypassed by the direct packet send.

All changed FabricStaffModeHandler versions need the same tracking eligibility guard.

Important Files Changed

Filename Overview
platforms/fabric-121/src/main/java/gg/modl/minecraft/fabric/v1_21_1/handler/FabricStaffModeHandler.java Switches unvanish re-show packets to vanilla player-list and tracker pairing data.
platforms/fabric-1214/src/main/java/gg/modl/minecraft/fabric/v1_21_4/handler/FabricStaffModeHandler.java Applies the same vanilla tracker re-show path for Minecraft 1.21.4.
platforms/fabric-1218/src/main/java/gg/modl/minecraft/fabric/v1_21_8/handler/FabricStaffModeHandler.java Adds the 1.21.8 tracker constructor variant for the re-show path.
platforms/fabric-12111/src/main/java/gg/modl/minecraft/fabric/v1_21_11/handler/FabricStaffModeHandler.java Adds the 1.21.11 tracker sender implementation for the re-show path.
platforms/fabric-26/src/main/java/gg/modl/minecraft/fabric/v26/handler/FabricStaffModeHandler.java Uses Mojang-mapped player-info and ServerEntity pairing data for the re-show path.

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 5 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 5
platforms/fabric-121/src/main/java/gg/modl/minecraft/fabric/v1_21_1/handler/FabricStaffModeHandler.java:195-206
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

### Issue 2 of 5
platforms/fabric-1214/src/main/java/gg/modl/minecraft/fabric/v1_21_4/handler/FabricStaffModeHandler.java:194-205
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

### Issue 3 of 5
platforms/fabric-1218/src/main/java/gg/modl/minecraft/fabric/v1_21_8/handler/FabricStaffModeHandler.java:195-208
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

### Issue 4 of 5
platforms/fabric-12111/src/main/java/gg/modl/minecraft/fabric/v1_21_11/handler/FabricStaffModeHandler.java:196-221
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

### Issue 5 of 5
platforms/fabric-26/src/main/java/gg/modl/minecraft/fabric/v26/handler/FabricStaffModeHandler.java:227-256
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Reviews (1): Last reviewed commit: "Fix unvanish skin layers and mod crashes..." | Re-trigger Greptile

Greptile also left 5 inline comments on this PR.

Context used:

  • Rule used - THE CENTRAL RULE everything else serves: maintain ... (source)

Comment on lines +195 to +206
viewer.networkHandler.sendPacket(PlayerListS2CPacket.entryFromPlayer(List.of(toShow)));

WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
profile, true, toShow.networkHandler.getLatency(), peGameMode,
net.kyori.adventure.text.Component.text(toShow.getName().getString()), null
EntityTrackerEntry trackerEntry = new EntityTrackerEntry(
toShow.getServerWorld(),
toShow,
toShow.getType().getTrackTickInterval(),
toShow.getType().alwaysUpdateVelocity(),
packet -> {
}
);

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerPlayerInfoUpdate(
EnumSet.of(
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LATENCY,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE
),
info
));

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerSpawnEntity(
toShow.getId(),
Optional.of(toShow.getUuid()),
EntityTypes.PLAYER,
new Vector3d(toShow.getX(), toShow.getY(), toShow.getZ()),
toShow.getPitch(),
toShow.getYaw(),
toShow.getYaw(),
0,
Optional.of(new Vector3d(0, 0, 0))
));
trackerEntry.sendPackets(viewer, packet -> viewer.networkHandler.sendPacket(packet));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unconditional tracker pairing

unvanish() calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Rule Used: THE CENTRAL RULE everything else serves: maintain ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: platforms/fabric-121/src/main/java/gg/modl/minecraft/fabric/v1_21_1/handler/FabricStaffModeHandler.java
Line: 195-206

Comment:
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

**Rule Used:** THE CENTRAL RULE everything else serves: maintain ... ([source](https://app.greptile.com/review/custom-context?memory=21719055-65fa-440f-b434-eba8d358d917))

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +194 to +205
viewer.networkHandler.sendPacket(PlayerListS2CPacket.entryFromPlayer(List.of(toShow)));

WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
profile, true, toShow.networkHandler.getLatency(), peGameMode,
net.kyori.adventure.text.Component.text(toShow.getName().getString()), null
EntityTrackerEntry trackerEntry = new EntityTrackerEntry(
toShow.getServerWorld(),
toShow,
toShow.getType().getTrackTickInterval(),
toShow.getType().alwaysUpdateVelocity(),
packet -> {
}
);

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerPlayerInfoUpdate(
EnumSet.of(
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LATENCY,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE
),
info
));

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerSpawnEntity(
toShow.getId(),
Optional.of(toShow.getUuid()),
EntityTypes.PLAYER,
new Vector3d(toShow.getX(), toShow.getY(), toShow.getZ()),
toShow.getPitch(),
toShow.getYaw(),
toShow.getYaw(),
0,
Optional.of(new Vector3d(0, 0, 0))
));
trackerEntry.sendPackets(viewer, packet -> viewer.networkHandler.sendPacket(packet));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unconditional tracker pairing

unvanish() calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Rule Used: THE CENTRAL RULE everything else serves: maintain ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: platforms/fabric-1214/src/main/java/gg/modl/minecraft/fabric/v1_21_4/handler/FabricStaffModeHandler.java
Line: 194-205

Comment:
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

**Rule Used:** THE CENTRAL RULE everything else serves: maintain ... ([source](https://app.greptile.com/review/custom-context?memory=21719055-65fa-440f-b434-eba8d358d917))

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +195 to +208
viewer.networkHandler.sendPacket(PlayerListS2CPacket.entryFromPlayer(List.of(toShow)));

WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
profile, true, toShow.networkHandler.getLatency(), peGameMode,
net.kyori.adventure.text.Component.text(toShow.getName().getString()), null
);
EntityTrackerEntry trackerEntry = new EntityTrackerEntry(
toShow.getWorld(),
toShow,
toShow.getType().getTrackTickInterval(),
toShow.getType().alwaysUpdateVelocity(),
packet -> {},
(packet, excludedPlayers) -> {

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerPlayerInfoUpdate(
EnumSet.of(
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LATENCY,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE
),
info
));
}
);

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerSpawnEntity(
toShow.getId(),
Optional.of(toShow.getUuid()),
EntityTypes.PLAYER,
new Vector3d(toShow.getX(), toShow.getY(), toShow.getZ()),
toShow.getPitch(),
toShow.getYaw(),
toShow.getYaw(),
0,
Optional.of(new Vector3d(0, 0, 0))
));
}
trackerEntry.sendPackets(viewer, packet -> viewer.networkHandler.sendPacket(packet));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unconditional tracker pairing

unvanish() calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Rule Used: THE CENTRAL RULE everything else serves: maintain ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: platforms/fabric-1218/src/main/java/gg/modl/minecraft/fabric/v1_21_8/handler/FabricStaffModeHandler.java
Line: 195-208

Comment:
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

**Rule Used:** THE CENTRAL RULE everything else serves: maintain ... ([source](https://app.greptile.com/review/custom-context?memory=21719055-65fa-440f-b434-eba8d358d917))

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +196 to +221
viewer.networkHandler.sendPacket(PlayerListS2CPacket.entryFromPlayer(List.of(toShow)));

WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
profile, true, toShow.networkHandler.getLatency(), peGameMode,
net.kyori.adventure.text.Component.text(toShow.getName().getString()), null
);
EntityTrackerEntry trackerEntry = new EntityTrackerEntry(
toShow.getEntityWorld(),
toShow,
toShow.getType().getTrackTickInterval(),
toShow.getType().alwaysUpdateVelocity(),
new EntityTrackerEntry.TrackerPacketSender() {
@Override
public void sendToListeners(Packet<? super ClientPlayPacketListener> packet) {
}

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerPlayerInfoUpdate(
EnumSet.of(
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LATENCY,
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_GAME_MODE
),
info
));
@Override
public void sendToSelfAndListeners(Packet<? super ClientPlayPacketListener> packet) {
}

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerSpawnEntity(
toShow.getId(),
Optional.of(toShow.getUuid()),
EntityTypes.PLAYER,
new Vector3d(toShow.getX(), toShow.getY(), toShow.getZ()),
toShow.getPitch(),
toShow.getYaw(),
toShow.getYaw(),
0,
Optional.of(new Vector3d(0, 0, 0))
));
@Override
public void sendToListenersIf(
Packet<? super ClientPlayPacketListener> packet,
Predicate<ServerPlayerEntity> predicate
) {
}
}
);

trackerEntry.sendPackets(viewer, packet -> viewer.networkHandler.sendPacket(packet));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unconditional tracker pairing

unvanish() calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Rule Used: THE CENTRAL RULE everything else serves: maintain ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: platforms/fabric-12111/src/main/java/gg/modl/minecraft/fabric/v1_21_11/handler/FabricStaffModeHandler.java
Line: 196-221

Comment:
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

**Rule Used:** THE CENTRAL RULE everything else serves: maintain ... ([source](https://app.greptile.com/review/custom-context?memory=21719055-65fa-440f-b434-eba8d358d917))

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +227 to +256
viewer.connection.send(

peApi.getPlayerManager().sendPacket(viewer,
new WrapperPlayServerSpawnEntity(
toShow.getId(),
Optional.of(toShow.getUUID()),
EntityTypes.PLAYER,
new Vector3d(toShow.getX(), toShow.getY(), toShow.getZ()),
toShow.getXRot(),
toShow.getYRot(),
toShow.getYRot(),
0,
Optional.of(new Vector3d(0, 0, 0))
));
ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(toShow))
);

ServerEntity trackerEntry = new ServerEntity(
toShow.level(),
toShow,
toShow.getType().updateInterval(),
toShow.getType().trackDeltas(),
new ServerEntity.Synchronizer() {
@Override
public void sendToTrackingPlayers(Packet<? super ClientGamePacketListener> packet) {
}

@Override
public void sendToTrackingPlayersAndSelf(Packet<? super ClientGamePacketListener> packet) {
}


@Override
public void sendToTrackingPlayersFiltered(
Packet<? super ClientGamePacketListener> packet,
Predicate<ServerPlayer> predicate
) {
}
}
);

trackerEntry.sendPairingData(viewer,packet -> viewer.connection.send(packet)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unconditional tracker pairing

unvanish() calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

Rule Used: THE CENTRAL RULE everything else serves: maintain ... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: platforms/fabric-26/src/main/java/gg/modl/minecraft/fabric/v26/handler/FabricStaffModeHandler.java
Line: 227-256

Comment:
**Unconditional tracker pairing**

`unvanish()` calls this for every online player, but this new vanilla-packet path sends player-list and tracker pairing data without checking that the viewer is in the same world or inside the normal tracking range. If a vanished staff member unvanishes in another dimension or far away, this can spawn a ghost player entity for viewers who vanilla tracking would not pair with at all. Gate this send through the same world/range conditions, or use the real server tracker’s pairing decision instead of sending a fresh tracker entry to every viewer.

**Rule Used:** THE CENTRAL RULE everything else serves: maintain ... ([source](https://app.greptile.com/review/custom-context?memory=21719055-65fa-440f-b434-eba8d358d917))

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@byteful byteful changed the base branch from main to dev May 25, 2026 09:06
@TheoBong

Copy link
Copy Markdown
Member

This looks good to me but I'll wait for @byteful to handle this into dev branch for next update since there are some conflicts and it's not a bug that requires immediate attention.

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.

2 participants