From ec60a9bb21a8b9c4b3381615b02e64e578654853 Mon Sep 17 00:00:00 2001 From: Kam Date: Sun, 22 Feb 2026 18:24:36 -0500 Subject: [PATCH] Request Client Packet Fix NPC [Invisibility Patch] --- .../kamkeel/npcs/network/PacketHandler.java | 2 +- .../npcs/network/enums/EnumDataPacket.java | 1 - .../npcs/network/enums/EnumPlayerPacket.java | 3 + .../packets/data/RequestProperSpawnData.java | 250 +++++++++--------- .../noppes/npcs/client/ClientTickHandler.java | 7 +- .../npcs/entity/EntityNPCInterface.java | 32 ++- 6 files changed, 153 insertions(+), 142 deletions(-) diff --git a/src/main/java/kamkeel/npcs/network/PacketHandler.java b/src/main/java/kamkeel/npcs/network/PacketHandler.java index e6a525952..b71021b37 100644 --- a/src/main/java/kamkeel/npcs/network/PacketHandler.java +++ b/src/main/java/kamkeel/npcs/network/PacketHandler.java @@ -569,7 +569,6 @@ public class PacketHandler { DATA_PACKET.registerPacket(new DialogPacket()); DATA_PACKET.registerPacket(new RolePacket()); DATA_PACKET.registerPacket(new WeaponNpcPacket()); -// DATA_PACKET.registerPacket(new RequestProperSpawnData()); // Data | Script Packets DATA_PACKET.registerPacket(new ScriptedParticlePacket()); @@ -628,6 +627,7 @@ public class PacketHandler { PLAYER_PACKET.registerPacket(new SpecialKeyStatePacket()); PLAYER_PACKET.registerPacket(new SyncRevisionInfoPacket()); + PLAYER_PACKET.registerPacket(new RequestProperSpawnData()); // CustomGUI Packets PLAYER_PACKET.registerPacket(new CustomGuiButtonPacket()); diff --git a/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java b/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java index 181956757..10ae639e9 100644 --- a/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java +++ b/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java @@ -23,7 +23,6 @@ public enum EnumDataPacket { DELETE_NPC, CLONE_NPC, WEAPON_NPC, - // REQUEST_SPAWN_DATA, // Data SCROLL_LIST, diff --git a/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java b/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java index e1587467b..3453b6eb4 100644 --- a/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java +++ b/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java @@ -42,4 +42,7 @@ public enum EnumPlayerPacket { AbilityHotbarSave, AbilityHotbarSelect, AbilityToggle, + + // NPC Spawn Data Fix + RequestSpawnData, } diff --git a/src/main/java/kamkeel/npcs/network/packets/data/RequestProperSpawnData.java b/src/main/java/kamkeel/npcs/network/packets/data/RequestProperSpawnData.java index d2ad045d1..386a9000b 100644 --- a/src/main/java/kamkeel/npcs/network/packets/data/RequestProperSpawnData.java +++ b/src/main/java/kamkeel/npcs/network/packets/data/RequestProperSpawnData.java @@ -1,125 +1,125 @@ -//package kamkeel.npcs.network.packets.data; -// -//import cpw.mods.fml.relauncher.Side; -//import cpw.mods.fml.relauncher.SideOnly; -//import io.netty.buffer.ByteBuf; -//import kamkeel.npcs.network.AbstractPacket; -//import kamkeel.npcs.network.PacketChannel; -//import kamkeel.npcs.network.PacketClient; -//import kamkeel.npcs.network.PacketHandler; -//import kamkeel.npcs.network.enums.EnumDataPacket; -//import kamkeel.npcs.network.packets.data.npc.UpdateNpcPacket; -//import net.minecraft.client.Minecraft; -//import net.minecraft.entity.Entity; -//import net.minecraft.entity.player.EntityPlayer; -//import net.minecraft.entity.player.EntityPlayerMP; -//import net.minecraft.nbt.NBTTagCompound; -//import noppes.npcs.entity.EntityNPCInterface; -// -//import java.io.IOException; -//import java.util.HashSet; -//import java.util.Iterator; -//import java.util.Set; -// -//public class RequestProperSpawnData extends AbstractPacket { -// public static final String packetName = "Data|SpawnData"; -// private static final int BATCH_LIMIT = 5; -// -// @SideOnly(Side.CLIENT) -// private static final Set entitiesToFix = new HashSet<>(); -// -// @SideOnly(Side.CLIENT) -// private static long lastBatchAttemptMillis = 0L; -// -// private int entityId; -// -// public RequestProperSpawnData() {} -// -// @SideOnly(Side.CLIENT) -// public RequestProperSpawnData(int entityId) { -// this.entityId = entityId; -// } -// -// @SideOnly(Side.CLIENT) -// public static void clear() { -// entitiesToFix.clear(); -// lastBatchAttemptMillis = 0L; -// } -// -// @Override -// public Enum getType() { -// return EnumDataPacket.REQUEST_SPAWN_DATA; -// } -// -// @Override -// public PacketChannel getChannel() { -// return PacketHandler.DATA_PACKET; -// } -// -// @Override -// @SideOnly(Side.CLIENT) -// public void sendData(ByteBuf out) throws IOException { -// out.writeInt(this.entityId); -// } -// -// @Override -// public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { -// if (!(player instanceof EntityPlayerMP) || player.worldObj == null || player.worldObj.isRemote) -// return; -// -// int entityId = in.readInt(); -// Entity entity = player.worldObj.getEntityByID(entityId); -// if (entity instanceof EntityNPCInterface) { -// EntityNPCInterface npc = (EntityNPCInterface) entity; -// NBTTagCompound compound = npc.writeSpawnData(); -// compound.setInteger("EntityId", npc.getEntityId()); -// PacketHandler.Instance.sendToPlayer(new UpdateNpcPacket(compound), (EntityPlayerMP) player); -// } -// } -// -// @SideOnly(Side.CLIENT) -// public static void reportMissingData(EntityNPCInterface npc) { -// if (npc == null || npc.worldObj == null || !npc.worldObj.isRemote) -// return; -// -// int entityID = npc.getEntityId(); -// if (entityID <= 0) -// return; -// -// if (npc.immediateSpawnDataFixAttempts++ < 3) { -// PacketClient.sendClient(new RequestProperSpawnData(entityID)); -// } else { -// entitiesToFix.add(entityID); -// } -// } -// -// @SideOnly(Side.CLIENT) -// public static boolean canDoBatchUpdate() { -// return System.currentTimeMillis() - lastBatchAttemptMillis >= 5000; -// } -// -// @SideOnly(Side.CLIENT) -// public static void handleBacklog() { -// Minecraft mc = Minecraft.getMinecraft(); -// if (mc == null || mc.theWorld == null || mc.thePlayer == null) -// return; -// -// if (entitiesToFix.isEmpty()) -// return; -// // Remove entity checks if they're no longer loaded -// entitiesToFix.removeIf(value -> !(mc.theWorld.getEntityByID(value) instanceof EntityNPCInterface)); -// -// Iterator it = entitiesToFix.iterator(); -// int count = 0; -// -// while (it.hasNext() && count < BATCH_LIMIT) { -// PacketClient.sendClient(new RequestProperSpawnData(it.next())); -// it.remove(); -// count++; -// } -// -// if (count != 0) { -// lastBatchAttemptMillis = System.currentTimeMillis(); -// } -// } -//} +package kamkeel.npcs.network.packets.data; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import kamkeel.npcs.network.AbstractPacket; +import kamkeel.npcs.network.PacketChannel; +import kamkeel.npcs.network.PacketClient; +import kamkeel.npcs.network.PacketHandler; +import kamkeel.npcs.network.enums.EnumPlayerPacket; +import kamkeel.npcs.network.packets.data.npc.UpdateNpcPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.entity.EntityNPCInterface; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class RequestProperSpawnData extends AbstractPacket { + public static final String packetName = "Player|SpawnData"; + private static final int BATCH_LIMIT = 5; + + @SideOnly(Side.CLIENT) + private static final Set entitiesToFix = new HashSet<>(); + + @SideOnly(Side.CLIENT) + private static long lastBatchAttemptMillis = 0L; + + private int entityId; + + public RequestProperSpawnData() {} + + @SideOnly(Side.CLIENT) + public RequestProperSpawnData(int entityId) { + this.entityId = entityId; + } + + @SideOnly(Side.CLIENT) + public static void clear() { + entitiesToFix.clear(); + lastBatchAttemptMillis = 0L; + } + + @Override + public Enum getType() { + return EnumPlayerPacket.RequestSpawnData; + } + + @Override + public PacketChannel getChannel() { + return PacketHandler.PLAYER_PACKET; + } + + @Override + @SideOnly(Side.CLIENT) + public void sendData(ByteBuf out) throws IOException { + out.writeInt(this.entityId); + } + + @Override + public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { + if (!(player instanceof EntityPlayerMP) || player.worldObj == null || player.worldObj.isRemote) + return; + + int entityId = in.readInt(); + Entity entity = player.worldObj.getEntityByID(entityId); + if (entity instanceof EntityNPCInterface) { + EntityNPCInterface npc = (EntityNPCInterface) entity; + NBTTagCompound compound = npc.writeSpawnData(); + compound.setInteger("EntityId", npc.getEntityId()); + PacketHandler.Instance.sendToPlayer(new UpdateNpcPacket(compound), (EntityPlayerMP) player); + } + } + + @SideOnly(Side.CLIENT) + public static void reportMissingData(EntityNPCInterface npc) { + if (npc == null || npc.worldObj == null || !npc.worldObj.isRemote) + return; + + int entityID = npc.getEntityId(); + if (entityID <= 0) + return; + + if (npc.clientFixAttempts++ < 3) { + PacketClient.sendClient(new RequestProperSpawnData(entityID)); + } else { + entitiesToFix.add(entityID); + } + } + + @SideOnly(Side.CLIENT) + public static boolean canDoBatchUpdate() { + return System.currentTimeMillis() - lastBatchAttemptMillis >= 5000; + } + + @SideOnly(Side.CLIENT) + public static void handleBacklog() { + Minecraft mc = Minecraft.getMinecraft(); + if (mc == null || mc.theWorld == null || mc.thePlayer == null) + return; + + if (entitiesToFix.isEmpty()) + return; + // Remove entity checks if they're no longer loaded + entitiesToFix.removeIf(value -> !(mc.theWorld.getEntityByID(value) instanceof EntityNPCInterface)); + + Iterator it = entitiesToFix.iterator(); + int count = 0; + + while (it.hasNext() && count < BATCH_LIMIT) { + PacketClient.sendClient(new RequestProperSpawnData(it.next())); + it.remove(); + count++; + } + + if (count != 0) { + lastBatchAttemptMillis = System.currentTimeMillis(); + } + } +} diff --git a/src/main/java/noppes/npcs/client/ClientTickHandler.java b/src/main/java/noppes/npcs/client/ClientTickHandler.java index bfd3b0cae..3636f48fa 100644 --- a/src/main/java/noppes/npcs/client/ClientTickHandler.java +++ b/src/main/java/noppes/npcs/client/ClientTickHandler.java @@ -10,6 +10,7 @@ import kamkeel.npcs.client.renderer.lightning.LightningBolt; import kamkeel.npcs.controllers.data.energycharge.EnergyChargePreviewManager; import kamkeel.npcs.controllers.data.telegraph.TelegraphManager; import kamkeel.npcs.network.PacketClient; +import kamkeel.npcs.network.packets.data.RequestProperSpawnData; import kamkeel.npcs.network.packets.player.CheckPlayerValue; import kamkeel.npcs.network.packets.player.InputDevicePacket; import kamkeel.npcs.network.packets.player.ScreenSizePacket; @@ -61,7 +62,7 @@ public class ClientTickHandler { if (mc.theWorld == null) { ClientCacheHandler.clearCache(); ClientAbilityState.reset(); -// RequestProperSpawnData.clear(); + RequestProperSpawnData.clear(); if (EnergyChargePreviewManager.ClientInstance != null) { EnergyChargePreviewManager.ClientInstance.clear(); } @@ -216,8 +217,8 @@ public class ClientTickHandler { return; if (mc.theWorld.getTotalWorldTime() % 20 == 0) { // Update every second -// if (RequestProperSpawnData.canDoBatchUpdate()) -// RequestProperSpawnData.handleBacklog(); + if (RequestProperSpawnData.canDoBatchUpdate()) + RequestProperSpawnData.handleBacklog(); updateCompassMarks(); } } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index 24579e4ab..fb1c1c6f8 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -11,6 +11,7 @@ import kamkeel.npcs.network.PacketHandler; import kamkeel.npcs.network.enums.EnumSoundOperation; import kamkeel.npcs.network.packets.data.ChatBubblePacket; import kamkeel.npcs.network.packets.data.QuestCompletionPacket; +import kamkeel.npcs.network.packets.data.RequestProperSpawnData; import kamkeel.npcs.network.packets.data.SoundManagementPacket; import kamkeel.npcs.network.packets.data.npc.UpdateNpcPacket; import kamkeel.npcs.network.packets.data.npc.WeaponNpcPacket; @@ -230,8 +231,8 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti public FlyingMoveHelper flyMoveHelper = new FlyingMoveHelper(this); public PathNavigate flyNavigator = new PathNavigateFlying(this, worldObj); -// @SideOnly(Side.CLIENT) -// public int immediateSpawnDataFixAttempts = 0; + // For Client-Side Use Only + public int clientFixAttempts = 0; public EntityNPCInterface(World world) { super(world); @@ -1836,20 +1837,18 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti try { readSpawnData(ByteBufUtils.readNBT(buf)); } catch (IOException e) { -// if (this.worldObj != null && this.worldObj.isRemote) { -// RequestProperSpawnData.reportMissingData(this); -// } + if (this.worldObj != null && this.worldObj.isRemote) { + RequestProperSpawnData.reportMissingData(this); + } } } public void readSpawnData(NBTTagCompound compound) { -// if (this.worldObj != null && this.worldObj.isRemote && -// (compound.hasNoTags() || !compound.hasKey("MaxHealth", Constants.NBT.TAG_DOUBLE))) { -// RequestProperSpawnData.reportMissingData(this); -// return; -// } -// -// immediateSpawnDataFixAttempts = 0; + if (this.worldObj != null && this.worldObj.isRemote) { + if(requestClientFix(compound)) + return; + } + stats.maxHealth = compound.getDouble("MaxHealth"); ais.setWalkingSpeed(compound.getInteger("Speed")); stats.hideKilledBody = compound.getBoolean("DeadBody"); @@ -1927,6 +1926,15 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } } + public boolean requestClientFix(NBTTagCompound compound){ + if((compound.hasNoTags() || !compound.hasKey("MaxHealth", Constants.NBT.TAG_DOUBLE))){ + RequestProperSpawnData.reportMissingData(this); + return true; + } + clientFixAttempts = 0; + return false; + } + public boolean canBreatheUnderwater() { return stats.drowningType != 1; }