From 6f1482f62b9301fba29f6f2f74034cc05ffe6679 Mon Sep 17 00:00:00 2001 From: Beanes Date: Wed, 8 Apr 2026 02:23:38 +0200 Subject: [PATCH 1/5] Add invisible nametag tracking to 1.7 by spawning using an invisible bat as passenger --- .../rewriter/EntityPacketRewriter1_8.java | 10 ++ .../rewriter/ScoreboardPacketRewriter1_8.java | 21 +++- .../storage/EntityTracker1_8.java | 113 ++++++++++++++++++ .../storage/ScoreboardTracker.java | 23 ++++ 4 files changed, 166 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java index 51fc9e8f3..2dd01c2b1 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java @@ -115,6 +115,10 @@ public void register() { tracker.getHolograms().get(entityId).syncState(EntityPacketRewriter1_8.this, entityData); } else if (tracker.hasEntity(entityId)) { handleEntityData(entityId, entityData, wrapper.user()); + // Check invisible flag updates for player entities + if (tracker.entityType(entityId) == EntityTypes1_8.EntityType.PLAYER) { + tracker.handlePlayerEntityFlags(entityId, entityData); + } } else { wrapper.cancel(); } @@ -337,6 +341,12 @@ public void register() { map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data handler(getTrackerAndDataHandler(RewindTypes.ENTITY_DATA_LIST1_7, EntityTypes1_8.EntityType.PLAYER)); + handler(wrapper -> { + final int entityId = wrapper.get(Types.VAR_INT, 0); + final List entityData = wrapper.get(RewindTypes.ENTITY_DATA_LIST1_7, 0); + final EntityTracker1_8 tracker = tracker(wrapper.user()); + tracker.handlePlayerEntityFlags(entityId, entityData); + }); } }); protocol.registerClientbound(ClientboundPackets1_8.SET_EQUIPPED_ITEM, new PacketHandlers() { diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/ScoreboardPacketRewriter1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/ScoreboardPacketRewriter1_8.java index a518886be..b15476462 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/ScoreboardPacketRewriter1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/ScoreboardPacketRewriter1_8.java @@ -19,6 +19,7 @@ import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5; import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.Protocol1_8To1_7_6_10; +import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.EntityTracker1_8; import com.viaversion.viarewind.protocol.v1_8to1_7_6_10.storage.ScoreboardTracker; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers; @@ -173,6 +174,7 @@ public void register() { } final ScoreboardTracker scoreboard = wrapper.user().get(ScoreboardTracker.class); + final EntityTracker1_8 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_7_6_10.class); final byte mode = wrapper.passthrough(Types.BYTE); if (mode != 0 && !scoreboard.teamExists(team)) { @@ -190,6 +192,10 @@ public void register() { if (mode == 0) { scoreboard.addTeam(team); } else if (mode == 1) { + // Team removed, nametag visibility might have changed + for (String member : scoreboard.getTeamMembers(team)) { + tracker.checkNametagVisbility(member); + } scoreboard.removeTeam(team); } @@ -198,7 +204,9 @@ public void register() { wrapper.passthrough(Types.STRING); // Prefix wrapper.passthrough(Types.STRING); // Suffix wrapper.passthrough(Types.BYTE); // Friendly fire - wrapper.read(Types.STRING); // Name tag visibility + final String nameTagVisibility = wrapper.read(Types.STRING); + final String previousVisibility = scoreboard.getTeamNameTagVisibility(team); + scoreboard.setTeamNameTagVisibility(team, nameTagVisibility); byte color = wrapper.read(Types.BYTE); if (mode == 2 && scoreboard.getTeamColor(team).get() != color) { final String sidebar = scoreboard.getColorDependentSidebar().get(color); @@ -209,6 +217,13 @@ public void register() { sidebarPacket.scheduleSend(Protocol1_8To1_7_6_10.class); } scoreboard.setTeamColor(team, color); + + // Re-evaluate nametag visibility for all team members when visibility changes + if (mode == 2 && !nameTagVisibility.equals(previousVisibility)) { + for (String member : scoreboard.getTeamMembers(team)) { + tracker.checkNametagVisbility(member); + } + } } if (mode == 0 || mode == 3 || mode == 4) { byte color = scoreboard.getTeamColor(team).get(); @@ -223,6 +238,8 @@ public void register() { continue; } scoreboard.removePlayerFromTeam(entry, team); + // Player left team, nametag visibility may change + tracker.checkNametagVisbility(entry); if (entry.equals(username)) { final PacketWrapper sidebarPacket = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user()); sidebarPacket.write(Types.BYTE, (byte) 1); @@ -231,6 +248,8 @@ public void register() { } } else { scoreboard.addPlayerToTeam(entry, team); + // Player joined team, nametag visibility may change + tracker.checkNametagVisbility(entry); if (entry.equals(username) && scoreboard.getColorDependentSidebar().containsKey(color)) { final PacketWrapper displayObjective = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_DISPLAY_OBJECTIVE, wrapper.user()); displayObjective.write(Types.BYTE, (byte) 1); diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java index ad7c0bd31..016ee987e 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java @@ -37,18 +37,26 @@ import com.viaversion.viaversion.libs.fastutil.objects.Object2IntOpenHashMap; import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import java.util.logging.Level; +import com.viaversion.viarewind.api.minecraft.entitydata.EntityDataTypes1_7_6_10; +import com.viaversion.viarewind.api.type.RewindTypes; +import com.viaversion.viarewind.protocol.v1_7_6_10to1_7_2_5.packet.ClientboundPackets1_7_2_5; + public class EntityTracker1_8 extends EntityTrackerBase { private final Int2ObjectMap holograms = new Int2ObjectArrayMap<>(); private final Int2IntMap vehicles = new Int2IntArrayMap(); private final Int2ObjectMap entityIdToUUID = new Int2ObjectArrayMap<>(); private final Object2IntMap entityUUIDToId = new Object2IntOpenHashMap<>(); + private final Set invisiblePlayerEntities = new HashSet<>(); + private final Int2IntMap playerBats = new Int2IntArrayMap(); private final List entityData = new ArrayList<>(); @@ -77,6 +85,11 @@ public void removeEntity(int entityId) { holograms.remove(entityId); } + if (playerBats.containsKey(entityId)) { + despawnBat(entityId); + } + invisiblePlayerEntities.remove(entityId); + if (entityIdToUUID.containsKey(entityId)) { final UUID playerId = entityIdToUUID.remove(entityId); @@ -89,6 +102,8 @@ public void removeEntity(int entityId) { public void clearEntities() { super.clearEntities(); vehicles.clear(); + playerBats.clear(); + invisiblePlayerEntities.clear(); } @Override @@ -155,6 +170,11 @@ public void setPassenger(final int vehicleId, final int passengerId) { } else { vehicles.put(vehicleId, passengerId); } + + // Re-evaluate nametag visibility when a player entity's passenger changes + if (vehicleId != -1 && entityIdToUUID.containsKey(vehicleId)) { + checkNametagVisibility(vehicleId); + } } protected void attachEntity(final int target) { @@ -185,6 +205,99 @@ public void setSpectating(int spectating) { } } + public void handlePlayerEntityFlags(final int entityId, final List entityData) { + if (!entityIdToUUID.containsKey(entityId)) return; + for (EntityData data : entityData) { + if (data.id() == 0) { // Entity flags + final byte flags = ((Number) data.getValue()).byteValue(); + if ((flags & 0x20) != 0) { + invisiblePlayerEntities.add(entityId); + } else { + invisiblePlayerEntities.remove(entityId); + } + checkNametagVisibility(entityId); + break; + } + } + } + + public void checkNametagVisibility(final int entityId) { + if (!entityIdToUUID.containsKey(entityId)) return; + final boolean shouldHide = isPlayerNametagHidden(entityId); + final boolean hasServerPassenger = getPassenger(entityId) != -1; + final boolean hasBat = playerBats.containsKey(entityId); + + if (shouldHide && !hasServerPassenger && !hasBat) { + spawnBat(entityId); + } else if ((!shouldHide || hasServerPassenger) && hasBat) { + despawnBat(entityId); + } + } + + public void checkNametagVisbility(final String username) { + final GameProfileStorage profileStorage = user().get(GameProfileStorage.class); + final GameProfileStorage.GameProfile profile = profileStorage.get(username, false); + if (profile == null) return; + + final int entityId = getPlayerEntityId(profile.uuid); + if (entityId == -1) return; + + checkNametagVisibility(entityId); + } + + private boolean isPlayerNametagHidden(final int entityId) { + if (invisiblePlayerEntities.contains(entityId)) return true; + final UUID uuid = entityIdToUUID.get(entityId); + if (uuid == null) return false; + final GameProfileStorage profileStorage = user().get(GameProfileStorage.class); + final GameProfileStorage.GameProfile profile = profileStorage.get(uuid); + if (profile == null) return false; + return user().get(ScoreboardTracker.class).isNametagHidden(profile.name); + } + + private int getBatEntityId(final int playerEntityId) { + return Integer.MAX_VALUE - 32000 - playerEntityId; + } + + private void spawnBat(final int playerEntityId) { + final int batId = getBatEntityId(playerEntityId); + playerBats.put(playerEntityId, batId); + + final List batData = new ArrayList<>(); + batData.add(new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0x20)); // Invisible + + final PacketWrapper spawnBat = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user()); + spawnBat.write(Types.VAR_INT, batId); + spawnBat.write(Types.UNSIGNED_BYTE, (short) EntityTypes1_8.EntityType.BAT.getId()); + spawnBat.write(Types.INT, 0); // X + spawnBat.write(Types.INT, 0); // Y + spawnBat.write(Types.INT, 0); // Z + spawnBat.write(Types.BYTE, (byte) 0); // Yaw + spawnBat.write(Types.BYTE, (byte) 0); // Pitch + spawnBat.write(Types.BYTE, (byte) 0); // Head yaw + spawnBat.write(Types.SHORT, (short) 0); // Velocity x + spawnBat.write(Types.SHORT, (short) 0); // Velocity y + spawnBat.write(Types.SHORT, (short) 0); // Velocity z + spawnBat.write(RewindTypes.ENTITY_DATA_LIST1_7, batData); + spawnBat.scheduleSend(Protocol1_8To1_7_6_10.class); + + final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user()); + attach.write(Types.INT, batId); + attach.write(Types.INT, playerEntityId); + attach.write(Types.BOOLEAN, false); + attach.scheduleSend(Protocol1_8To1_7_6_10.class); + } + + private void despawnBat(final int playerEntityId) { + if (!playerBats.containsKey(playerEntityId)) return; + final int batId = playerBats.remove(playerEntityId); + + final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user()); + despawn.write(Types.BYTE, (byte) 1); + despawn.write(Types.INT, batId); + despawn.scheduleSend(Protocol1_8To1_7_6_10.class); + } + public Int2ObjectMap getHolograms() { return holograms; } diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/ScoreboardTracker.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/ScoreboardTracker.java index 32ae65eed..40a11be88 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/ScoreboardTracker.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/ScoreboardTracker.java @@ -37,6 +37,7 @@ public class ScoreboardTracker extends StoredObject { private final HashMap teamColors = new HashMap<>(); private final HashSet scoreTeamNames = new HashSet<>(); private final HashMap colorDependentSidebar = new HashMap<>(); + private final HashMap teamNameTagVisibilities = new HashMap<>(); private String colorIndependentSidebar; public ScoreboardTracker(UserConnection user) { @@ -63,6 +64,7 @@ public void removeTeam(String team) { teams.remove(team); scoreTeams.remove(team); teamColors.remove(team); + teamNameTagVisibilities.remove(team); } public boolean teamExists(String team) { @@ -98,6 +100,27 @@ public Optional getTeam(String player) { return Optional.empty(); } + public void setTeamNameTagVisibility(String team, String visibility) { + teamNameTagVisibilities.put(team, visibility); + } + + public String getTeamNameTagVisibility(String team) { + return teamNameTagVisibilities.getOrDefault(team, "always"); + } + + public boolean isNametagHidden(String username) { + for (Map.Entry> entry : teams.entrySet()) { + if (entry.getValue().contains(username)) { + return "never".equalsIgnoreCase(teamNameTagVisibilities.getOrDefault(entry.getKey(), "always")); + } + } + return false; + } + + public List getTeamMembers(String team) { + return teams.getOrDefault(team, new ArrayList<>()); + } + public void addObjective(String name) { objectives.add(name); } From d0a1fa48504d35ac6cbf33ed1c961bcf019b7782 Mon Sep 17 00:00:00 2001 From: Beanes Date: Wed, 8 Apr 2026 02:33:25 +0200 Subject: [PATCH 2/5] Replace bat with age 0 magma so there is no invis hitbox above the players --- .../storage/EntityTracker1_8.java | 73 ++++++++++--------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java index 016ee987e..46424e517 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java @@ -56,7 +56,7 @@ public class EntityTracker1_8 extends EntityTrackerBase { private final Int2ObjectMap entityIdToUUID = new Int2ObjectArrayMap<>(); private final Object2IntMap entityUUIDToId = new Object2IntOpenHashMap<>(); private final Set invisiblePlayerEntities = new HashSet<>(); - private final Int2IntMap playerBats = new Int2IntArrayMap(); + private final Int2IntMap playerNametagHiderEntities = new Int2IntArrayMap(); private final List entityData = new ArrayList<>(); @@ -85,8 +85,8 @@ public void removeEntity(int entityId) { holograms.remove(entityId); } - if (playerBats.containsKey(entityId)) { - despawnBat(entityId); + if (playerNametagHiderEntities.containsKey(entityId)) { + despawnNametagHiderEntity(entityId); } invisiblePlayerEntities.remove(entityId); @@ -102,7 +102,7 @@ public void removeEntity(int entityId) { public void clearEntities() { super.clearEntities(); vehicles.clear(); - playerBats.clear(); + playerNametagHiderEntities.clear(); invisiblePlayerEntities.clear(); } @@ -225,12 +225,12 @@ public void checkNametagVisibility(final int entityId) { if (!entityIdToUUID.containsKey(entityId)) return; final boolean shouldHide = isPlayerNametagHidden(entityId); final boolean hasServerPassenger = getPassenger(entityId) != -1; - final boolean hasBat = playerBats.containsKey(entityId); + final boolean hasSkull = playerNametagHiderEntities.containsKey(entityId); - if (shouldHide && !hasServerPassenger && !hasBat) { - spawnBat(entityId); - } else if ((!shouldHide || hasServerPassenger) && hasBat) { - despawnBat(entityId); + if (shouldHide && !hasServerPassenger && !hasSkull) { + spawnNametagHiderEntity(entityId); + } else if ((!shouldHide || hasServerPassenger) && hasSkull) { + despawnNametagHiderEntity(entityId); } } @@ -255,46 +255,47 @@ private boolean isPlayerNametagHidden(final int entityId) { return user().get(ScoreboardTracker.class).isNametagHidden(profile.name); } - private int getBatEntityId(final int playerEntityId) { + private int getNametagHiderEntityId(final int playerEntityId) { return Integer.MAX_VALUE - 32000 - playerEntityId; } - private void spawnBat(final int playerEntityId) { - final int batId = getBatEntityId(playerEntityId); - playerBats.put(playerEntityId, batId); - - final List batData = new ArrayList<>(); - batData.add(new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0x20)); // Invisible - - final PacketWrapper spawnBat = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user()); - spawnBat.write(Types.VAR_INT, batId); - spawnBat.write(Types.UNSIGNED_BYTE, (short) EntityTypes1_8.EntityType.BAT.getId()); - spawnBat.write(Types.INT, 0); // X - spawnBat.write(Types.INT, 0); // Y - spawnBat.write(Types.INT, 0); // Z - spawnBat.write(Types.BYTE, (byte) 0); // Yaw - spawnBat.write(Types.BYTE, (byte) 0); // Pitch - spawnBat.write(Types.BYTE, (byte) 0); // Head yaw - spawnBat.write(Types.SHORT, (short) 0); // Velocity x - spawnBat.write(Types.SHORT, (short) 0); // Velocity y - spawnBat.write(Types.SHORT, (short) 0); // Velocity z - spawnBat.write(RewindTypes.ENTITY_DATA_LIST1_7, batData); - spawnBat.scheduleSend(Protocol1_8To1_7_6_10.class); + private void spawnNametagHiderEntity(final int playerEntityId) { + final int entityId = getNametagHiderEntityId(playerEntityId); + playerNametagHiderEntities.put(playerEntityId, entityId); + + final List mobData = new ArrayList<>(); + mobData.add(new EntityData(0, EntityDataTypes1_7_6_10.BYTE, (byte) 0x20)); + mobData.add(new EntityData(16, EntityDataTypes1_7_6_10.BYTE, (byte) 0)); + + final PacketWrapper spawnMob = PacketWrapper.create(ClientboundPackets1_7_2_5.ADD_MOB, user()); + spawnMob.write(Types.VAR_INT, entityId); + spawnMob.write(Types.UNSIGNED_BYTE, (short) EntityTypes1_8.EntityType.MAGMA_CUBE.getId()); + spawnMob.write(Types.INT, 0); // X + spawnMob.write(Types.INT, 0); // Y + spawnMob.write(Types.INT, 0); // Z + spawnMob.write(Types.BYTE, (byte) 0); // Yaw + spawnMob.write(Types.BYTE, (byte) 0); // Pitch + spawnMob.write(Types.BYTE, (byte) 0); // Head yaw + spawnMob.write(Types.SHORT, (short) 0); // Velocity x + spawnMob.write(Types.SHORT, (short) 0); // Velocity y + spawnMob.write(Types.SHORT, (short) 0); // Velocity z + spawnMob.write(RewindTypes.ENTITY_DATA_LIST1_7, mobData); + spawnMob.scheduleSend(Protocol1_8To1_7_6_10.class); final PacketWrapper attach = PacketWrapper.create(ClientboundPackets1_7_2_5.SET_ENTITY_LINK, user()); - attach.write(Types.INT, batId); + attach.write(Types.INT, entityId); attach.write(Types.INT, playerEntityId); attach.write(Types.BOOLEAN, false); attach.scheduleSend(Protocol1_8To1_7_6_10.class); } - private void despawnBat(final int playerEntityId) { - if (!playerBats.containsKey(playerEntityId)) return; - final int batId = playerBats.remove(playerEntityId); + private void despawnNametagHiderEntity(final int playerEntityId) { + if (!playerNametagHiderEntities.containsKey(playerEntityId)) return; + final int mobId = playerNametagHiderEntities.remove(playerEntityId); final PacketWrapper despawn = PacketWrapper.create(ClientboundPackets1_7_2_5.REMOVE_ENTITIES, user()); despawn.write(Types.BYTE, (byte) 1); - despawn.write(Types.INT, batId); + despawn.write(Types.INT, mobId); despawn.scheduleSend(Protocol1_8To1_7_6_10.class); } From f103ef602c025bdc6aca8d999e3d9f7c6343431c Mon Sep 17 00:00:00 2001 From: Beanes Date: Thu, 9 Apr 2026 02:44:14 +0200 Subject: [PATCH 3/5] Fix edge case where entity bitmask is not send --- .../v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java | 5 ++++- .../v1_8to1_7_6_10/storage/EntityTracker1_8.java | 9 +++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java index 2dd01c2b1..1681fa069 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java @@ -117,7 +117,9 @@ public void register() { handleEntityData(entityId, entityData, wrapper.user()); // Check invisible flag updates for player entities if (tracker.entityType(entityId) == EntityTypes1_8.EntityType.PLAYER) { - tracker.handlePlayerEntityFlags(entityId, entityData); + if (tracker.handlePlayerEntityFlags(entityId, entityData)) { + tracker.checkNametagVisibility(entityId);; + } } } else { wrapper.cancel(); @@ -346,6 +348,7 @@ public void register() { final List entityData = wrapper.get(RewindTypes.ENTITY_DATA_LIST1_7, 0); final EntityTracker1_8 tracker = tracker(wrapper.user()); tracker.handlePlayerEntityFlags(entityId, entityData); + tracker.checkNametagVisibility(entityId); }); } }); diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java index 46424e517..d07ef5a8a 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java @@ -205,8 +205,8 @@ public void setSpectating(int spectating) { } } - public void handlePlayerEntityFlags(final int entityId, final List entityData) { - if (!entityIdToUUID.containsKey(entityId)) return; + public boolean handlePlayerEntityFlags(final int entityId, final List entityData) { + if (!entityIdToUUID.containsKey(entityId)) return false; for (EntityData data : entityData) { if (data.id() == 0) { // Entity flags final byte flags = ((Number) data.getValue()).byteValue(); @@ -215,10 +215,11 @@ public void handlePlayerEntityFlags(final int entityId, final List e } else { invisiblePlayerEntities.remove(entityId); } - checkNametagVisibility(entityId); - break; + return true; } } + + return false; } public void checkNametagVisibility(final int entityId) { From ded53ef0766e29e9c7d37ec1528c6390630df06e Mon Sep 17 00:00:00 2001 From: Beanes Date: Sun, 12 Apr 2026 17:27:51 +0200 Subject: [PATCH 4/5] Invisibility tracking is not needed for nametag hiding --- .../rewriter/EntityPacketRewriter1_8.java | 13 ------------ .../storage/EntityTracker1_8.java | 21 ------------------- 2 files changed, 34 deletions(-) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java index 1681fa069..51fc9e8f3 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java @@ -115,12 +115,6 @@ public void register() { tracker.getHolograms().get(entityId).syncState(EntityPacketRewriter1_8.this, entityData); } else if (tracker.hasEntity(entityId)) { handleEntityData(entityId, entityData, wrapper.user()); - // Check invisible flag updates for player entities - if (tracker.entityType(entityId) == EntityTypes1_8.EntityType.PLAYER) { - if (tracker.handlePlayerEntityFlags(entityId, entityData)) { - tracker.checkNametagVisibility(entityId);; - } - } } else { wrapper.cancel(); } @@ -343,13 +337,6 @@ public void register() { map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data handler(getTrackerAndDataHandler(RewindTypes.ENTITY_DATA_LIST1_7, EntityTypes1_8.EntityType.PLAYER)); - handler(wrapper -> { - final int entityId = wrapper.get(Types.VAR_INT, 0); - final List entityData = wrapper.get(RewindTypes.ENTITY_DATA_LIST1_7, 0); - final EntityTracker1_8 tracker = tracker(wrapper.user()); - tracker.handlePlayerEntityFlags(entityId, entityData); - tracker.checkNametagVisibility(entityId); - }); } }); protocol.registerClientbound(ClientboundPackets1_8.SET_EQUIPPED_ITEM, new PacketHandlers() { diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java index d07ef5a8a..07ae15967 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/storage/EntityTracker1_8.java @@ -55,7 +55,6 @@ public class EntityTracker1_8 extends EntityTrackerBase { private final Int2IntMap vehicles = new Int2IntArrayMap(); private final Int2ObjectMap entityIdToUUID = new Int2ObjectArrayMap<>(); private final Object2IntMap entityUUIDToId = new Object2IntOpenHashMap<>(); - private final Set invisiblePlayerEntities = new HashSet<>(); private final Int2IntMap playerNametagHiderEntities = new Int2IntArrayMap(); private final List entityData = new ArrayList<>(); @@ -88,7 +87,6 @@ public void removeEntity(int entityId) { if (playerNametagHiderEntities.containsKey(entityId)) { despawnNametagHiderEntity(entityId); } - invisiblePlayerEntities.remove(entityId); if (entityIdToUUID.containsKey(entityId)) { final UUID playerId = entityIdToUUID.remove(entityId); @@ -103,7 +101,6 @@ public void clearEntities() { super.clearEntities(); vehicles.clear(); playerNametagHiderEntities.clear(); - invisiblePlayerEntities.clear(); } @Override @@ -205,23 +202,6 @@ public void setSpectating(int spectating) { } } - public boolean handlePlayerEntityFlags(final int entityId, final List entityData) { - if (!entityIdToUUID.containsKey(entityId)) return false; - for (EntityData data : entityData) { - if (data.id() == 0) { // Entity flags - final byte flags = ((Number) data.getValue()).byteValue(); - if ((flags & 0x20) != 0) { - invisiblePlayerEntities.add(entityId); - } else { - invisiblePlayerEntities.remove(entityId); - } - return true; - } - } - - return false; - } - public void checkNametagVisibility(final int entityId) { if (!entityIdToUUID.containsKey(entityId)) return; final boolean shouldHide = isPlayerNametagHidden(entityId); @@ -247,7 +227,6 @@ public void checkNametagVisbility(final String username) { } private boolean isPlayerNametagHidden(final int entityId) { - if (invisiblePlayerEntities.contains(entityId)) return true; final UUID uuid = entityIdToUUID.get(entityId); if (uuid == null) return false; final GameProfileStorage profileStorage = user().get(GameProfileStorage.class); From 8571e9de0ebaf8e87eda1485a616f0a31118b7e9 Mon Sep 17 00:00:00 2001 From: Beanes Date: Sun, 12 Apr 2026 17:30:21 +0200 Subject: [PATCH 5/5] Add back nametag invisibility checking at spawn player --- .../v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java index 51fc9e8f3..c7b783056 100644 --- a/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java +++ b/common/src/main/java/com/viaversion/viarewind/protocol/v1_8to1_7_6_10/rewriter/EntityPacketRewriter1_8.java @@ -337,6 +337,11 @@ public void register() { map(Types.ENTITY_DATA_LIST1_8, RewindTypes.ENTITY_DATA_LIST1_7); // Entity data handler(getTrackerAndDataHandler(RewindTypes.ENTITY_DATA_LIST1_7, EntityTypes1_8.EntityType.PLAYER)); + handler(wrapper -> { + final int entityId = wrapper.get(Types.VAR_INT, 0); + final EntityTracker1_8 tracker = tracker(wrapper.user()); + tracker.checkNametagVisibility(entityId);; + }); } }); protocol.registerClientbound(ClientboundPackets1_8.SET_EQUIPPED_ITEM, new PacketHandlers() {