From 41c724f31461baeab087e237d4646f598cc43f53 Mon Sep 17 00:00:00 2001 From: Neon Date: Sun, 12 Jan 2025 17:38:25 +0100 Subject: [PATCH] Fixed buff removal when leaving certain instances Leaving a solo instance while being in a group would not call onLeaveInstance, causing buffs not getting removed for example. Changed default instanced map handlers to fix undefined behavior when logging into an already destroyed instance. Because instance ID 1 is currently the fallback, not all handlers handle onLeaveInstance with unknown players gracefully (e.g. BasicPvpInstance). --- .../services/instance/InstanceService.java | 22 +++++++++---------- .../aionemu/gameserver/world/WorldMap.java | 6 ++++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/game-server/src/com/aionemu/gameserver/services/instance/InstanceService.java b/game-server/src/com/aionemu/gameserver/services/instance/InstanceService.java index 502942b3e..a0c6c03ef 100644 --- a/game-server/src/com/aionemu/gameserver/services/instance/InstanceService.java +++ b/game-server/src/com/aionemu/gameserver/services/instance/InstanceService.java @@ -95,7 +95,7 @@ public static void destroyInstance(WorldMapInstance instance) { map.removeWorldMapInstance(instanceId); - log.info("Destroying instance:" + worldId + " " + instanceId); + log.info("Destroying " + instance); TemporarySpawnEngine.onInstanceDestroy(instance); // first unregister all temporary spawns, then despawn mobs for (VisibleObject obj : instance) { @@ -257,17 +257,15 @@ public static void onEnterInstance(Player player) { } public static void onLeaveInstance(Player player) { - WorldMapInstance registeredInstance = getRegisteredInstance(player.getWorldId(), getLastRegisteredId(player)); - if (registeredInstance != null) { // don't get instance via player.getPosition since he maybe isn't registered with it anymore (login after dc) - registeredInstance.getInstanceHandler().onLeaveInstance(player); - if (!registeredInstance.isPersonal()) { - if (registeredInstance.getMaxPlayers() == 1) // solo instance - PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE(getDestroyDelaySeconds(registeredInstance) / 60)); - else if (registeredInstance.getRegisteredTeam() != null && registeredInstance.getRegisteredTeam().getMembers().isEmpty()) - PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(0)); - else if (registeredInstance.getPlayersInside().size() <= 1) - PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(getDestroyDelaySeconds(registeredInstance) / 60)); - } + WorldMapInstance instance = player.getWorldMapInstance(); + instance.getInstanceHandler().onLeaveInstance(player); + if (instance.getRegisteredCount() > 0) { + if (instance.getMaxPlayers() == 1) // solo instance + PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE(getDestroyDelaySeconds(instance) / 60)); + else if (instance.getRegisteredTeam() != null && instance.getRegisteredTeam().getMembers().isEmpty()) + PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(0)); + else if (instance.getPlayersInside().size() <= 1) + PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_LEAVE_INSTANCE_PARTY(getDestroyDelaySeconds(instance) / 60)); } removeRestrictedItemsFromInventoryAndStorage(player, item -> item.getItemTemplate().isItemRestrictedToWorld(player.getWorldId())); diff --git a/game-server/src/com/aionemu/gameserver/world/WorldMap.java b/game-server/src/com/aionemu/gameserver/world/WorldMap.java index 7a6e820ef..9cfa0dad5 100644 --- a/game-server/src/com/aionemu/gameserver/world/WorldMap.java +++ b/game-server/src/com/aionemu/gameserver/world/WorldMap.java @@ -6,6 +6,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import com.aionemu.gameserver.instance.handlers.GeneralInstanceHandler; import com.aionemu.gameserver.model.templates.world.WorldMapTemplate; import com.aionemu.gameserver.world.zone.ZoneAttributes; @@ -26,7 +27,10 @@ public WorldMap(WorldMapTemplate worldMapTemplate) { this.worldOptions = worldMapTemplate.getFlags(); for (int i = 1; i <= getInstanceCount(); i++) { - WorldMapInstanceFactory.createWorldMapInstance(this, 0); + if (isInstanceType()) // default instances are inaccessible but its handler methods are sometimes called via MainWorldMapInstance, e.g. on relog + WorldMapInstanceFactory.createWorldMapInstance(this, 0, GeneralInstanceHandler::new, 0); + else + WorldMapInstanceFactory.createWorldMapInstance(this, 0); } }