From a00607f9cc92b299052f37b2eab191e06e26dbad Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Mon, 4 May 2026 04:05:24 +0800 Subject: [PATCH] fix almost everything 1. proper sync based on vanilla entity tracker 2. try catch around onPlayerLoad() 3. player reference updating and stale InventoryBaubles pruning --- src/main/java/baubles/common/Baubles.java | 4 ++ .../container/ContainerPlayerExpanded.java | 5 ++ .../common/container/InventoryBaubles.java | 6 +-- .../common/event/EventHandlerCleanup.java | 24 ++++++++++ .../common/event/EventHandlerEntity.java | 10 ++++ .../common/event/EventHandlerNetwork.java | 10 +--- .../baubles/common/lib/PlayerHandler.java | 48 +++++++++++++++++-- .../baubles/common/network/PacketHandler.java | 20 ++++++++ .../common/network/PacketSyncAllBauble.java | 8 +++- 9 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 src/main/java/baubles/common/event/EventHandlerCleanup.java diff --git a/src/main/java/baubles/common/Baubles.java b/src/main/java/baubles/common/Baubles.java index c92bd79..1f54192 100644 --- a/src/main/java/baubles/common/Baubles.java +++ b/src/main/java/baubles/common/Baubles.java @@ -8,6 +8,7 @@ import cpw.mods.fml.common.Loader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import baubles.common.event.EventHandlerCleanup; import baubles.common.event.EventHandlerEntity; import baubles.common.event.EventHandlerNetwork; import baubles.common.network.PacketHandler; @@ -38,6 +39,7 @@ public class Baubles { public EventHandlerEntity entityEventHandler; public EventHandlerNetwork entityEventNetwork; + public EventHandlerCleanup cleanupEventHandler; public static final Logger log = LogManager.getLogger("Baubles"); public static final int GUI = 0; @@ -52,9 +54,11 @@ public class Baubles { entityEventHandler = new EventHandlerEntity(); entityEventNetwork = new EventHandlerNetwork(); + cleanupEventHandler = new EventHandlerCleanup(); MinecraftForge.EVENT_BUS.register(entityEventHandler); FMLCommonHandler.instance().bus().register(entityEventNetwork); + FMLCommonHandler.instance().bus().register(cleanupEventHandler); proxy.registerHandlers(); } diff --git a/src/main/java/baubles/common/container/ContainerPlayerExpanded.java b/src/main/java/baubles/common/container/ContainerPlayerExpanded.java index ac2ffb9..e06b8fa 100644 --- a/src/main/java/baubles/common/container/ContainerPlayerExpanded.java +++ b/src/main/java/baubles/common/container/ContainerPlayerExpanded.java @@ -129,6 +129,11 @@ public class ContainerPlayerExpanded extends Container { @Override public void onContainerClosed(EntityPlayer player) { super.onContainerClosed(player); + + if (baubles != null && baubles.getEventHandler() == this) { + baubles.setEventHandler(null); + } + if (useOldGuiRendering) { return; } diff --git a/src/main/java/baubles/common/container/InventoryBaubles.java b/src/main/java/baubles/common/container/InventoryBaubles.java index f42e1ff..780d9a7 100644 --- a/src/main/java/baubles/common/container/InventoryBaubles.java +++ b/src/main/java/baubles/common/container/InventoryBaubles.java @@ -7,13 +7,13 @@ import baubles.api.BaubleType; import baubles.api.IBauble; import baubles.api.expanded.BaubleExpandedSlots; import baubles.api.expanded.IBaubleExpanded; -import baubles.common.Baubles; import baubles.common.lib.ItemStackHelper; import baubles.common.network.PacketHandler; import baubles.common.network.PacketSyncBauble; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; @@ -296,8 +296,8 @@ public class InventoryBaubles implements IInventory { public void syncSlotToClients(int slot) { try { EntityPlayer entityPlayer = player.get(); - if (entityPlayer != null && !entityPlayer.worldObj.isRemote) { - PacketHandler.INSTANCE.sendToAll(new PacketSyncBauble(player.get(), slot)); + if (entityPlayer instanceof EntityPlayerMP playerMP && !entityPlayer.worldObj.isRemote) { + PacketHandler.sendToTracking(new PacketSyncBauble(playerMP, slot), playerMP, true); } } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/java/baubles/common/event/EventHandlerCleanup.java b/src/main/java/baubles/common/event/EventHandlerCleanup.java new file mode 100644 index 0000000..7b43ea5 --- /dev/null +++ b/src/main/java/baubles/common/event/EventHandlerCleanup.java @@ -0,0 +1,24 @@ +package baubles.common.event; + +import baubles.common.lib.PlayerHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; + +public class EventHandlerCleanup { + private int serverTickCount; + private int clientTickCount; + + @SubscribeEvent + public void onServerTick(TickEvent.ServerTickEvent event) { + if (event.phase == TickEvent.Phase.END && serverTickCount++ % 200 == 120) { + PlayerHandler.pruneServerSide(); + } + } + + @SubscribeEvent + public void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.END && clientTickCount++ % 200 == 52) { + PlayerHandler.pruneClientSide(); + } + } +} diff --git a/src/main/java/baubles/common/event/EventHandlerEntity.java b/src/main/java/baubles/common/event/EventHandlerEntity.java index f94e5e0..1e1876b 100644 --- a/src/main/java/baubles/common/event/EventHandlerEntity.java +++ b/src/main/java/baubles/common/event/EventHandlerEntity.java @@ -9,8 +9,11 @@ import baubles.api.IBauble; import baubles.common.Baubles; import baubles.common.container.InventoryBaubles; import baubles.common.lib.PlayerHandler; +import baubles.common.network.PacketHandler; +import baubles.common.network.PacketSyncAllBauble; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.event.entity.player.PlayerDropsEvent; import net.minecraftforge.event.entity.player.PlayerEvent; @@ -99,4 +102,11 @@ public class EventHandlerEntity { getPlayerFile("baubback", directory, player.getCommandSenderName())); } + @SubscribeEvent + public void startTracking(PlayerEvent.StartTracking event) { + // no need to check for isRemote: this event is server only + if (event.target instanceof EntityPlayer otherPlayer) { + PacketHandler.INSTANCE.sendTo(new PacketSyncAllBauble(otherPlayer), ((EntityPlayerMP) event.entityPlayer)); + } + } } diff --git a/src/main/java/baubles/common/event/EventHandlerNetwork.java b/src/main/java/baubles/common/event/EventHandlerNetwork.java index 1548758..82937d3 100644 --- a/src/main/java/baubles/common/event/EventHandlerNetwork.java +++ b/src/main/java/baubles/common/event/EventHandlerNetwork.java @@ -13,22 +13,16 @@ import cpw.mods.fml.relauncher.Side; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; -import net.minecraft.server.MinecraftServer; public class EventHandlerNetwork { @SubscribeEvent public void playerLoggedInEvent(PlayerEvent.PlayerLoggedInEvent event) { Side side = FMLCommonHandler.instance().getEffectiveSide(); - if (side == Side.SERVER) { + if (side == Side.SERVER) { // Apply all baubles InventoryBaubles baubles = PlayerHandler.getPlayerBaubles(event.player); - PacketHandler.INSTANCE.sendToAll(new PacketSyncAllBauble(event.player)); - for (Object o : MinecraftServer.getServer().getConfigurationManager().playerEntityList) { - if (o == event.player) continue; - EntityPlayerMP player = (EntityPlayerMP) o; - PacketHandler.INSTANCE.sendTo(new PacketSyncAllBauble(player), (EntityPlayerMP) event.player); - } + PacketHandler.INSTANCE.sendTo(new PacketSyncAllBauble(event.player), ((EntityPlayerMP) event.player)); for (int i = 0; i < baubles.getSizeInventory(); i++) { ItemStack stack = baubles.getStackInSlot(i); if (stack != null && stack.getItem() instanceof IBauble itemBauble) { diff --git a/src/main/java/baubles/common/lib/PlayerHandler.java b/src/main/java/baubles/common/lib/PlayerHandler.java index 66b3f7e..420bef8 100644 --- a/src/main/java/baubles/common/lib/PlayerHandler.java +++ b/src/main/java/baubles/common/lib/PlayerHandler.java @@ -3,6 +3,7 @@ package baubles.common.lib; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.lang.ref.WeakReference; import java.util.HashMap; import com.google.common.io.Files; @@ -12,22 +13,59 @@ import baubles.common.container.InventoryBaubles; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; public class PlayerHandler { - private static HashMap playerBaublesServer = new HashMap<>(); - private static HashMap playerBaublesClient = new HashMap<>(); + private static final HashMap playerBaublesServer = new HashMap<>(); + private static final HashMap playerBaublesClient = new HashMap<>(); public static void clearPlayerBaubles(EntityPlayer player) { - playerBaublesServer.remove(player.getCommandSenderName()); + clearPlayerBaubles(player.getCommandSenderName(), player.worldObj.isRemote); } public static void clearClientPlayerBaubles() { playerBaublesClient.clear(); } - public static void clearClientPlayerBaubles(EntityPlayer player) { - playerBaublesClient.remove(player.getCommandSenderName()); + public static void pruneServerSide() { + baublesPrune(playerBaublesServer, false); + } + + public static void pruneClientSide() { + baublesPrune(playerBaublesClient, true); + } + + private static void baublesPrune(HashMap map, boolean isClient) { + for (var iter = map.entrySet().iterator(); iter.hasNext(); ) { + var e = iter.next(); + String playerName = e.getKey(); + InventoryBaubles baubles = e.getValue(); + EntityPlayer player = baubles.player.get(); + if (player != null && !player.isDead) continue; + EntityPlayer newPlayer = null; + if (isClient) { + for (Object o : Baubles.proxy.getClientWorld().playerEntities) { + EntityPlayer playerEntity = (EntityPlayer) o; + if (playerEntity.getCommandSenderName().equals(playerName)) { + newPlayer = playerEntity; + break; + } + } + } else { + newPlayer = MinecraftServer.getServer().getConfigurationManager().func_152612_a(playerName); + } + if (newPlayer != null) { + baubles.player = new WeakReference<>(newPlayer); + continue; + } + iter.remove(); + } + } + + public static void clearPlayerBaubles(String playerName, boolean isClient) { + HashMap map = isClient ? playerBaublesClient : playerBaublesServer; + map.remove(playerName); } public static InventoryBaubles getPlayerBaubles(EntityPlayer player) { diff --git a/src/main/java/baubles/common/network/PacketHandler.java b/src/main/java/baubles/common/network/PacketHandler.java index e3205d0..088ddcd 100644 --- a/src/main/java/baubles/common/network/PacketHandler.java +++ b/src/main/java/baubles/common/network/PacketHandler.java @@ -2,8 +2,13 @@ package baubles.common.network; import baubles.common.Baubles; import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; import cpw.mods.fml.relauncher.Side; +import net.minecraft.entity.EntityTracker; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.Packet; +import net.minecraft.world.WorldServer; public class PacketHandler { public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(Baubles.MODID.toLowerCase()); @@ -14,4 +19,19 @@ public class PacketHandler { INSTANCE.registerMessage(PacketSyncBauble.class, PacketSyncBauble.class, 2, Side.CLIENT); INSTANCE.registerMessage(PacketSyncAllBauble.class, PacketSyncAllBauble.class, 3, Side.CLIENT); } + + public static void sendToTracking(IMessage message, EntityPlayer target, boolean sendToTarget) { + if (target.worldObj.isRemote) { + // won't work + Baubles.log.error("Sending message {} from wrong side: cannot find tracking players on client side.", message.getClass().getName()); + return; + } + Packet packet = INSTANCE.getPacketFrom(message); + EntityTracker tracker = ((WorldServer) target.worldObj).getEntityTracker(); + if (sendToTarget) { + tracker.func_151248_b(target, packet); + } else { + tracker.func_151247_a(target, packet); + } + } } diff --git a/src/main/java/baubles/common/network/PacketSyncAllBauble.java b/src/main/java/baubles/common/network/PacketSyncAllBauble.java index ac88a98..4afe966 100644 --- a/src/main/java/baubles/common/network/PacketSyncAllBauble.java +++ b/src/main/java/baubles/common/network/PacketSyncAllBauble.java @@ -63,12 +63,16 @@ public class PacketSyncAllBauble implements IMessage, IMessageHandler { baubles.stackList[a] = b; if (b.getItem() instanceof IBauble itemBauble) { - itemBauble.onPlayerLoad(b, player); + try { + itemBauble.onPlayerLoad(b, player); + } catch (Exception ex) { + Baubles.log.error("Error loading baubles {}", b, ex); + } } return true; });