From de8c31702317c80487ecef781131f1559d4b064e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 30 Dec 2025 23:20:54 +0000 Subject: [PATCH] Add mount edge case handling for dismount scenarios - Player logout: Dismount from NPC mount before logout to prevent orphaned mount state (ServerTickHandler) - Teleportation: Dismount before cross-dimension teleport to prevent mount being left behind in old dimension (NoppesUtilPlayer) - Dead rider: Validate rider is alive, dismount dead/invalid riders to prevent stuck mount state (NPCMountUtil) - Role disable: Dismount rider when mount role is disabled to prevent mounted player on non-mount NPC (RoleMount) --- src/main/java/noppes/npcs/NoppesUtilPlayer.java | 12 ++++++++++-- src/main/java/noppes/npcs/ServerTickHandler.java | 6 ++++++ src/main/java/noppes/npcs/roles/RoleMount.java | 4 ++++ src/main/java/noppes/npcs/util/NPCMountUtil.java | 11 +++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/noppes/npcs/NoppesUtilPlayer.java b/src/main/java/noppes/npcs/NoppesUtilPlayer.java index 2c9c3b647..c78ffdf46 100644 --- a/src/main/java/noppes/npcs/NoppesUtilPlayer.java +++ b/src/main/java/noppes/npcs/NoppesUtilPlayer.java @@ -123,8 +123,12 @@ public class NoppesUtilPlayer { } public static void teleportPlayer(EntityPlayerMP player, double posX, double posY, double posZ, int dimension) { + // Dismount from NPC mount before teleportation to prevent mount desync + if (player.ridingEntity instanceof EntityNPCInterface) { + player.mountEntity(null); + } + if (player.dimension != dimension) { - int dim = player.dimension; MinecraftServer server = MinecraftServer.getServer(); WorldServer wor = server.worldServerForDimension(dimension); if (wor == null) { @@ -144,8 +148,12 @@ public class NoppesUtilPlayer { } public static void teleportPlayer(EntityPlayerMP player, double posX, double posY, double posZ, float yaw, float pitch, int dimension) { + // Dismount from NPC mount before teleportation to prevent mount desync + if (player.ridingEntity instanceof EntityNPCInterface) { + player.mountEntity(null); + } + if (player.dimension != dimension) { - int dim = player.dimension; MinecraftServer server = MinecraftServer.getServer(); WorldServer wor = server.worldServerForDimension(dimension); if (wor == null) { diff --git a/src/main/java/noppes/npcs/ServerTickHandler.java b/src/main/java/noppes/npcs/ServerTickHandler.java index 62f53399b..3648f00d7 100644 --- a/src/main/java/noppes/npcs/ServerTickHandler.java +++ b/src/main/java/noppes/npcs/ServerTickHandler.java @@ -11,6 +11,7 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.world.WorldServer; import noppes.npcs.client.AnalyticsTracking; import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.controllers.data.action.ActionManager; import java.net.InetAddress; @@ -68,6 +69,11 @@ public class ServerTickHandler { @SubscribeEvent public void playerLogout(PlayerEvent.PlayerLoggedOutEvent event) { + // Dismount player from NPC mount before logout to prevent orphaned mount state + if (event.player.ridingEntity instanceof EntityNPCInterface) { + event.player.mountEntity(null); + } + PlayerData playerData = PlayerData.get(event.player); if (playerData != null) { playerData.onLogout(); diff --git a/src/main/java/noppes/npcs/roles/RoleMount.java b/src/main/java/noppes/npcs/roles/RoleMount.java index f930a4975..dd1ec0ca7 100644 --- a/src/main/java/noppes/npcs/roles/RoleMount.java +++ b/src/main/java/noppes/npcs/roles/RoleMount.java @@ -192,6 +192,10 @@ public class RoleMount extends RoleInterface { } public void onDisable() { + // Dismount any rider when mount role is disabled + if (npc.riddenByEntity != null) { + npc.riddenByEntity.mountEntity(null); + } npc.ais.returnToStart = storedReturnToStart; } diff --git a/src/main/java/noppes/npcs/util/NPCMountUtil.java b/src/main/java/noppes/npcs/util/NPCMountUtil.java index b83ef00a7..6303f67b9 100644 --- a/src/main/java/noppes/npcs/util/NPCMountUtil.java +++ b/src/main/java/noppes/npcs/util/NPCMountUtil.java @@ -177,6 +177,17 @@ public final class NPCMountUtil { RoleMount mount = (RoleMount) npc.roleInterface; Entity currentRider = npc.riddenByEntity; + + // Validate rider is alive and valid - dismount dead/invalid riders + if (currentRider != null && !currentRider.isEntityAlive()) { + currentRider.mountEntity(null); + stabilizeDismountedRider(currentRider); + haltMountedMotion(npc, state); + applyUnriddenFlightDescent(npc, state, mount); + currentRider = null; + } + + // Only allow EntityPlayer as riders if (currentRider != null && !(currentRider instanceof EntityPlayer)) { Entity dismount = currentRider; dismount.mountEntity(null);