From c5b6a0d7c96372e92b64ce337a6ef9dc19d36660 Mon Sep 17 00:00:00 2001 From: MobiusDev <8391001+MobiusDevelopment@users.noreply.github.com> Date: Sun, 1 Apr 2018 17:23:59 +0000 Subject: [PATCH] Addition of Disconnection class. Adapted from: L2jUnity free files. --- .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ .../AdminChangeAccessLevel.java | 3 +- .../admincommandhandlers/AdminDisconnect.java | 3 +- .../admincommandhandlers/AdminKick.java | 10 +- .../admincommandhandlers/AdminMenu.java | 8 +- .../punishmenthandlers/BanHandler.java | 5 +- .../handlers/telnethandlers/player/Kick.java | 3 +- .../gameserver/LoginServerThread.java | 11 +- .../com/l2jmobius/gameserver/Shutdown.java | 25 +- .../data/sql/impl/OfflineTradersTable.java | 11 +- .../instancemanager/AntiFeedManager.java | 8 +- .../l2jmobius/gameserver/model/L2World.java | 5 +- .../gameserver/model/actor/L2Character.java | 3 +- .../model/actor/instance/L2PcInstance.java | 155 +++---- .../tasks/player/IllegalPlayerActionTask.java | 3 +- .../gameserver/network/Disconnection.java | 189 ++++++++ .../gameserver/network/L2GameClient.java | 413 +++--------------- .../network/clientpackets/AuthLogin.java | 2 +- .../clientpackets/CharacterCreate.java | 3 +- .../clientpackets/CharacterRestore.java | 2 +- .../clientpackets/CharacterSelect.java | 5 +- .../network/clientpackets/EnterWorld.java | 5 +- .../network/clientpackets/Logout.java | 41 +- .../clientpackets/ProtocolVersion.java | 2 +- .../clientpackets/RequestBypassToServer.java | 3 +- .../clientpackets/RequestHardWareInfo.java | 3 +- .../network/clientpackets/RequestRestart.java | 44 +- .../network/clientpackets/Say2.java | 5 +- .../security/SecondaryPasswordAuth.java | 5 +- .../taskmanager/AttackStanceTaskManager.java | 4 +- .../gameserver/util/FloodProtectorAction.java | 10 +- .../gameserver/util/OfflineTradeUtil.java | 151 +++++++ 186 files changed, 3372 insertions(+), 3468 deletions(-) create mode 100644 L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java create mode 100644 L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java create mode 100644 L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java create mode 100644 L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java create mode 100644 L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/Disconnection.java create mode 100644 L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/LoginServerThread.java index 257cddeda9..67a2386a5a 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -562,15 +562,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index f88260f46a..9a1a01c8a6 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -33,6 +33,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -49,6 +50,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -300,7 +305,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -470,11 +475,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index c6b3f15765..71a30d2323 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -257,6 +257,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -292,7 +293,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -311,7 +311,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -803,6 +802,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1253,38 +1254,6 @@ public final class L2PcInstance extends L2Playable _inCraftMode = b; } - /** - * Manage Logout Task: - * - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - * - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3975,33 +3944,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6824,6 +6766,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8102,6 +8046,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
* Actions: @@ -10691,28 +10690,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11093,6 +11083,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11102,6 +11101,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..8c839bb573 --- /dev/null +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/L2GameClient.java index 1ac8293de7..f51a2ac473 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 7157284859..d04cb02aff 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -57,6 +57,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -137,7 +138,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -648,7 +649,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index 281601ab37..5ab9bf7732 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..7394f489e8 --- /dev/null +++ b/L2J_Mobius_1.0_Ertheia/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +} diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/LoginServerThread.java index 257cddeda9..67a2386a5a 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -562,15 +562,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index f88260f46a..9a1a01c8a6 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -33,6 +33,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -49,6 +50,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -300,7 +305,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -470,11 +475,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index aea3179d98..be088f6ea3 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -259,6 +259,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -294,7 +295,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -313,7 +313,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -805,6 +804,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1259,38 +1260,6 @@ public final class L2PcInstance extends L2Playable _inCraftMode = b; } - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3981,33 +3950,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6831,6 +6773,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8109,6 +8053,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
    * Actions: @@ -10698,28 +10697,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11100,6 +11090,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11109,6 +11108,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..8c839bb573 --- /dev/null +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/L2GameClient.java index 1ac8293de7..f51a2ac473 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index ff2ce606c0..901665ac2a 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -58,6 +58,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -142,7 +143,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -681,7 +682,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index 281601ab37..5ab9bf7732 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..7394f489e8 --- /dev/null +++ b/L2J_Mobius_2.5_Underground/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +} diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/LoginServerThread.java index d30e398c7d..694dc6dc8d 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -565,15 +565,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index f88260f46a..9a1a01c8a6 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -33,6 +33,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -49,6 +50,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -300,7 +305,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -470,11 +475,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index 09a8acbe69..c4975ad737 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -260,6 +260,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -296,7 +297,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -315,7 +315,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -807,6 +806,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1261,38 +1262,6 @@ public final class L2PcInstance extends L2Playable _inCraftMode = b; } - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3983,33 +3952,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6833,6 +6775,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8111,6 +8055,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
    * Actions: @@ -10708,28 +10707,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11110,6 +11100,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11119,6 +11118,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..8c839bb573 --- /dev/null +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/L2GameClient.java index 1ac8293de7..f51a2ac473 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index ff2ce606c0..901665ac2a 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -58,6 +58,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -142,7 +143,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -681,7 +682,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index cbf5d5e6bd..a6beb4572f 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..7394f489e8 --- /dev/null +++ b/L2J_Mobius_3.0_Helios/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +} diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/LoginServerThread.java index d30e398c7d..694dc6dc8d 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -565,15 +565,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index d34129376f..bd32b469ac 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -35,6 +35,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -51,6 +52,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -304,7 +309,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -474,11 +479,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index 3e4062b751..e0c1850edb 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -263,6 +263,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -299,7 +300,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -318,7 +318,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -814,6 +813,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1272,38 +1273,6 @@ public final class L2PcInstance extends L2Playable _isCrafting = isCrafting; } - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3974,33 +3943,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6830,6 +6772,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8108,6 +8052,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
    * Actions: @@ -10701,28 +10700,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11093,6 +11083,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11102,6 +11101,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..98b74379c3 --- /dev/null +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/L2GameClient.java index 0e654350b3..f51a2ac473 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isCrafting(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index f39ce62420..c92b8e36c5 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -58,6 +58,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -142,7 +143,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -681,7 +682,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index cbf5d5e6bd..a6beb4572f 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..5fea4905d6 --- /dev/null +++ b/L2J_Mobius_4.0_GrandCrusade/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isCrafting(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +} diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/LoginServerThread.java index d30e398c7d..694dc6dc8d 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -565,15 +565,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index f88260f46a..9a1a01c8a6 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -33,6 +33,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -49,6 +50,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -300,7 +305,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -470,11 +475,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index d79a0d0f90..8b346479f5 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -259,6 +259,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -294,7 +295,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -313,7 +313,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -801,6 +800,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1235,38 +1236,6 @@ public final class L2PcInstance extends L2Playable _inCraftMode = b; } - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3951,33 +3920,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6800,6 +6742,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8058,6 +8002,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
    * Actions: @@ -10636,28 +10635,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11038,6 +11028,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11047,6 +11046,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..8c839bb573 --- /dev/null +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/L2GameClient.java index 1ac8293de7..f51a2ac473 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index 604e5728cd..b539956ee8 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -58,6 +58,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -141,7 +142,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -679,7 +680,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index 281601ab37..5ab9bf7732 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..7394f489e8 --- /dev/null +++ b/L2J_Mobius_Classic_2.0_Saviors/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +} diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java index d34b4302c7..0e7065aee0 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminChangeAccessLevel.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2AccessLevel; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -129,7 +130,7 @@ public final class AdminChangeAccessLevel implements IAdminCommandHandler { player.setAccessLevel(lvl, false, true); player.sendMessage("Your character has been banned. Bye."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java index ef50200374..e12f7ef2dc 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminDisconnect.java @@ -19,6 +19,7 @@ package handlers.admincommandhandlers; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2Object; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; /** * This class handles following admin commands: - character_disconnect = disconnects target player @@ -68,7 +69,7 @@ public class AdminDisconnect implements IAdminCommandHandler { activeChar.sendMessage("Character " + player.getName() + " disconnected from server."); - player.logout(); + Disconnection.of(player).defaultSequence(false); } } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java index 7e2e74e819..ed04b1f770 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminKick.java @@ -18,10 +18,10 @@ package handlers.admincommandhandlers; import java.util.StringTokenizer; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; public class AdminKick implements IAdminCommandHandler { @@ -44,11 +44,7 @@ public class AdminKick implements IAdminCommandHandler final L2PcInstance plyr = L2World.getInstance().getPlayer(player); if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); activeChar.sendMessage("You kicked " + plyr.getName() + " from the game."); } } @@ -61,7 +57,7 @@ public class AdminKick implements IAdminCommandHandler if (!player.isGM()) { counter++; - player.logout(); + Disconnection.of(player).defaultSequence(false); } } activeChar.sendMessage("Kicked " + counter + " players."); diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java index c7d395af30..549035d177 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/admincommandhandlers/AdminMenu.java @@ -21,7 +21,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.l2jmobius.Config; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.AdminData; import com.l2jmobius.gameserver.handler.AdminCommandHandler; import com.l2jmobius.gameserver.handler.IAdminCommandHandler; @@ -31,6 +30,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; /** @@ -170,11 +170,7 @@ public class AdminMenu implements IAdminCommandHandler String text; if (plyr != null) { - if (plyr.getOfflineStartTime() > 0) - { - OfflineTradersTable.removeTrader(plyr.getObjectId()); - } - plyr.logout(); + Disconnection.of(plyr).defaultSequence(false); text = "You kicked " + plyr.getName() + " from the game."; } else diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java index 80d6df69e3..640d1919fb 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/punishmenthandlers/BanHandler.java @@ -22,6 +22,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -58,7 +59,7 @@ public class BanHandler implements IPunishmentHandler } else { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); } } break; @@ -90,7 +91,7 @@ public class BanHandler implements IPunishmentHandler */ private static void applyToPlayer(L2PcInstance player) { - player.logout(); + Disconnection.of(player).defaultSequence(false); } @Override diff --git a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java index 6d1b59fe5a..b053496854 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java +++ b/L2J_Mobius_Classic_2.0_Zaken/dist/game/data/scripts/handlers/telnethandlers/player/Kick.java @@ -18,6 +18,7 @@ package handlers.telnethandlers.player; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.telnet.ITelnetCommand; import io.netty.channel.ChannelHandlerContext; @@ -49,7 +50,7 @@ public class Kick implements ITelnetCommand final L2PcInstance player = L2World.getInstance().getPlayer(args[0]); if (player != null) { - player.logout(); + Disconnection.of(player).defaultSequence(false); return "Player has been successfully kicked."; } return "Couldn't find player with such name."; diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/LoginServerThread.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/LoginServerThread.java index d30e398c7d..694dc6dc8d 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/LoginServerThread.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/LoginServerThread.java @@ -565,15 +565,8 @@ public class LoginServerThread extends Thread final L2GameClient client = _accountsInGameServer.get(account); if (client != null) { - if (client.isDetached()) - { - client.getActiveChar().logout(); - } - else - { - client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); - } - ACCOUNTING_LOGGER.info(getClass().getSimpleName() + ": Kicked by login, " + client); + ACCOUNTING_LOGGER.info("Kicked by login, " + client); + client.close(SystemMessage.getSystemMessage(SystemMessageId.YOU_ARE_LOGGED_IN_TO_TWO_PLACES_IF_YOU_SUSPECT_ACCOUNT_THEFT_WE_RECOMMEND_CHANGING_YOUR_PASSWORD_SCANNING_YOUR_COMPUTER_FOR_VIRUSES_AND_USING_AN_ANTI_VIRUS_SOFTWARE)); } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/Shutdown.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/Shutdown.java index 369510db24..2878a9df1b 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/Shutdown.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/Shutdown.java @@ -38,11 +38,10 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.entity.Hero; import com.l2jmobius.gameserver.model.olympiad.Olympiad; import com.l2jmobius.gameserver.network.ClientNetworkManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.EventLoopGroupManager; -import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.loginserverpackets.game.ServerStatus; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.network.telnet.TelnetServer; import com.l2jmobius.gameserver.util.Broadcast; @@ -610,27 +609,7 @@ public class Shutdown extends Thread { for (L2PcInstance player : L2World.getInstance().getPlayers()) { - // Logout Character - try - { - final L2GameClient client = player.getClient(); - if ((client != null) && !client.isDetached()) - { - client.close(ServerClose.STATIC_PACKET); - client.setActiveChar(null); - player.setClient(null); - } - else if ((client == null) || client.isDetached()) - // player is probably a bot - force logout - { - player.logout(); - } - player.deleteMe(); - } - catch (Throwable t) - { - LOGGER.log(Level.WARNING, "Failed logour char " + player, t); - } + Disconnection.of(player).defaultSequence(true); } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java index f88260f46a..9a1a01c8a6 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/data/sql/impl/OfflineTradersTable.java @@ -33,6 +33,7 @@ import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.TradeItem; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.SellBuffHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; public class OfflineTradersTable @@ -49,6 +50,10 @@ public class OfflineTradersTable private static final String LOAD_OFFLINE_STATUS = "SELECT * FROM character_offline_trade"; private static final String LOAD_OFFLINE_ITEMS = "SELECT * FROM character_offline_trade_items WHERE `charId`=?"; + protected OfflineTradersTable() + { + } + public void storeOffliners() { try (Connection con = DatabaseFactory.getInstance().getConnection(); @@ -300,7 +305,7 @@ public class OfflineTradersTable LOGGER.log(Level.WARNING, getClass().getSimpleName() + ": Error loading trader: " + player, e); if (player != null) { - player.deleteMe(); + Disconnection.of(player).defaultSequence(false); } } } @@ -470,11 +475,11 @@ public class OfflineTradersTable */ public static OfflineTradersTable getInstance() { - return SingletonHolder._instance; + return SingletonHolder.INSTANCE; } private static class SingletonHolder { - protected static final OfflineTradersTable _instance = new OfflineTradersTable(); + protected static final OfflineTradersTable INSTANCE = new OfflineTradersTable(); } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java index 62cb2ff7f2..87c082bbab 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/instancemanager/AntiFeedManager.java @@ -72,6 +72,12 @@ public final class AntiFeedManager return false; } + // Players in offline mode should't be valid targets. + if (targetPlayer.getClient().isDetached()) + { + return false; + } + if ((Config.ANTIFEED_INTERVAL > 0) && _lastDeathTimes.containsKey(targetPlayer.getObjectId())) { if ((System.currentTimeMillis() - _lastDeathTimes.get(targetPlayer.getObjectId())) < Config.ANTIFEED_INTERVAL) @@ -211,7 +217,7 @@ public final class AntiFeedManager */ public final void onDisconnect(L2GameClient client) { - if ((client == null) || client.isDetached()) + if ((client == null) || (client.getConnectionAddress() == null)) { return; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/L2World.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/L2World.java index 0cfd65f6d5..bf6b018b8c 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/L2World.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/L2World.java @@ -39,6 +39,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PetInstance; import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcCreatureSee; import com.l2jmobius.gameserver.model.interfaces.ILocational; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.serverpackets.DeleteObject; import com.l2jmobius.gameserver.util.Util; @@ -143,8 +144,8 @@ public final class L2World final L2PcInstance existingPlayer = _allPlayers.putIfAbsent(object.getObjectId(), newPlayer); if (existingPlayer != null) { - existingPlayer.logout(); - newPlayer.logout(); + Disconnection.of(existingPlayer).defaultSequence(false); + Disconnection.of(newPlayer).defaultSequence(false); LOGGER.warning(getClass().getSimpleName() + ": Duplicate character!? Disconnected both characters (" + newPlayer.getName() + ")"); } else if (Config.FACTION_SYSTEM_ENABLED) diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java index 6e143ff2d9..e39c93014d 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/L2Character.java @@ -131,6 +131,7 @@ import com.l2jmobius.gameserver.model.stats.MoveType; import com.l2jmobius.gameserver.model.stats.Stats; import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.model.zone.ZoneRegion; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.Attack; @@ -3287,7 +3288,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); if (isPlayer()) { - getActingPlayer().logout(); + Disconnection.of(getActingPlayer()).defaultSequence(false); } else if (isSummon()) { diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java index 0d795d8bf3..2741e75cbe 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/instance/L2PcInstance.java @@ -259,6 +259,7 @@ import com.l2jmobius.gameserver.model.variables.AccountVariables; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.L2ZoneType; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.AbstractHtmlPacket; @@ -294,7 +295,6 @@ import com.l2jmobius.gameserver.network.serverpackets.HennaInfo; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; import com.l2jmobius.gameserver.network.serverpackets.InventoryUpdate; import com.l2jmobius.gameserver.network.serverpackets.ItemList; -import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.MagicSkillUse; import com.l2jmobius.gameserver.network.serverpackets.MyTargetSelected; import com.l2jmobius.gameserver.network.serverpackets.NicknameChanged; @@ -313,7 +313,6 @@ import com.l2jmobius.gameserver.network.serverpackets.RecipeShopMsg; import com.l2jmobius.gameserver.network.serverpackets.RecipeShopSellList; import com.l2jmobius.gameserver.network.serverpackets.RelationChanged; import com.l2jmobius.gameserver.network.serverpackets.Ride; -import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SetupGauge; import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit; import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime; @@ -801,6 +800,8 @@ public final class L2PcInstance extends L2Playable private final Fishing _fishing = new Fishing(this); + private Future _autoSaveTask = null; + public void setPvpFlagLasts(long time) { _pvpFlagLasts = time; @@ -1235,38 +1236,6 @@ public final class L2PcInstance extends L2Playable _inCraftMode = b; } - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - */ - public void logout() - { - logout(true); - } - - /** - * Manage Logout Task: - *
      - *
    • Remove player from world
    • - *
    • Save player data into DB
    • - *
    - * @param closeClient - */ - public void logout(boolean closeClient) - { - try - { - closeNetConnection(closeClient); - } - catch (Exception e) - { - _log.log(Level.WARNING, "Exception on logout(): " + e.getMessage(), e); - } - } - /** * @return a table containing all Common L2RecipeList of the L2PcInstance. */ @@ -3951,33 +3920,6 @@ public final class L2PcInstance extends L2Playable return ip; } - /** - * Close the active connection with the client. - * @param closeClient - */ - private void closeNetConnection(boolean closeClient) - { - final L2GameClient client = _client; - if (client != null) - { - if (client.isDetached()) - { - client.cleanMe(true); - } - else if (client.getChannel().isActive()) - { - if (closeClient) - { - client.close(LeaveWorld.STATIC_PACKET); - } - else - { - client.close(ServerClose.STATIC_PACKET); - } - } - } - } - public Location getCurrentSkillWorldPosition() { return _currentSkillWorldPosition; @@ -6800,6 +6742,8 @@ public final class L2PcInstance extends L2Playable player.startOnlineTimeUpdateTask(); player.setOnlineStatus(true, false); + + player.startAutoSaveTask(); } catch (Exception e) { @@ -8058,6 +8002,61 @@ public final class L2PcInstance extends L2Playable return isInCategory(CategoryType.SIXTH_CLASS_GROUP); } + private void startAutoSaveTask() + { + if ((Config.CHAR_DATA_STORE_INTERVAL > 0) && (_autoSaveTask == null)) + { + _autoSaveTask = ThreadPoolManager.scheduleAtFixedRate(this::autoSave, 300_000L, TimeUnit.MINUTES.toMillis(Config.CHAR_DATA_STORE_INTERVAL)); + } + } + + private void stopAutoSaveTask() + { + if (_autoSaveTask != null) + { + _autoSaveTask.cancel(false); + _autoSaveTask = null; + } + } + + protected void autoSave() + { + storeMe(); + storeRecommendations(); + + if (Config.UPDATE_ITEMS_ON_CHAR_STORE) + { + getInventory().updateDatabase(); + getWarehouse().updateDatabase(); + } + } + + public boolean canLogout() + { + if (hasItemRequest()) + { + return false; + } + + if (isLocked()) + { + _log.warning("Player " + getName() + " tried to restart/logout during class change."); + return false; + } + + if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(this) && !(isGM() && Config.GM_RESTART_FIGHTING)) + { + return false; + } + + if (isBlockedFromExit()) + { + return false; + } + + return true; + } + /** * Return True if the L2PcInstance is autoAttackable.
    * Actions: @@ -10636,28 +10635,19 @@ public final class L2PcInstance extends L2Playable *
  • If the L2PcInstance is in observer mode, set its position to its position before entering in observer mode
  • *
  • Set the online Flag to True or False and update the characters table of the database with online status and lastAccess
  • *
  • Stop the HP/MP/CP Regeneration task
  • - *
  • Cancel Crafting, Attak or Cast
  • + *
  • Cancel Crafting, Attack or Cast
  • *
  • Remove the L2PcInstance from the world
  • *
  • Stop Party and Unsummon Pet
  • *
  • Update database with items in its inventory and remove them from the world
  • *
  • Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  • *
  • Close the connection with the client
  • * + *
    + * Remember this method is not to be used to half-ass disconnect players! This method is dedicated only to erase the player from the world.
    + * If you intend to disconnect a player please use {@link Disconnection} */ @Override public boolean deleteMe() - { - cleanup(); - storeMe(); - - // Stop all passives and augment options without broadcasting changes. - getEffectList().stopAllPassives(false, false); - getEffectList().stopAllOptions(false, false); - - return super.deleteMe(); - } - - private synchronized void cleanup() { EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(this), this); @@ -11038,6 +11028,15 @@ public final class L2PcInstance extends L2Playable EventDispatcher.getInstance().notifyEventAsync(new OnPlayerMentorStatus(this, false), this); } + // we store all data from players who are disconnected while in an event in order to restore it in the next login + if (L2Event.isParticipant(this)) + { + L2Event.savePlayerEventStatus(this); + } + + // Anti Feed + AntiFeedManager.getInstance().onDisconnect(getClient()); + try { notifyFriends(L2FriendStatus.MODE_OFFLINE); @@ -11047,6 +11046,14 @@ public final class L2PcInstance extends L2Playable { _log.log(Level.WARNING, "Exception on deleteMe() notifyFriends: " + e.getMessage(), e); } + + // Stop all passives and augment options + getEffectList().stopAllPassives(false, false); + getEffectList().stopAllOptions(false, false); + + stopAutoSaveTask(); + + return super.deleteMe(); } public int getInventoryLimit() diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java index ae997fd6ef..23cfffc2bb 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/model/actor/tasks/player/IllegalPlayerActionTask.java @@ -26,6 +26,7 @@ import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; +import com.l2jmobius.gameserver.network.Disconnection; /** * Task that handles illegal player actions. @@ -86,7 +87,7 @@ public final class IllegalPlayerActionTask implements Runnable } case KICK: { - _actor.logout(false); + Disconnection.of(_actor).defaultSequence(false); break; } case KICKBAN: diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/Disconnection.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/Disconnection.java new file mode 100644 index 0000000000..8c839bb573 --- /dev/null +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/Disconnection.java @@ -0,0 +1,189 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.network; + +import java.util.logging.Logger; + +import com.l2jmobius.gameserver.ThreadPoolManager; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.events.EventDispatcher; +import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerLogout; +import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * @author NB4L1 + */ +public final class Disconnection +{ + private static final Logger LOGGER = Logger.getLogger(Disconnection.class.getName()); + + public static L2GameClient getClient(L2GameClient client, L2PcInstance activeChar) + { + if (client != null) + { + return client; + } + + if (activeChar != null) + { + return activeChar.getClient(); + } + + return null; + } + + public static L2PcInstance getActiveChar(L2GameClient client, L2PcInstance activeChar) + { + if (activeChar != null) + { + return activeChar; + } + + if (client != null) + { + return client.getActiveChar(); + } + + return null; + } + + private final L2GameClient _client; + private final L2PcInstance _activeChar; + + private Disconnection(L2GameClient client) + { + this(client, null); + } + + public static Disconnection of(L2GameClient client) + { + return new Disconnection(client); + } + + private Disconnection(L2PcInstance activeChar) + { + this(null, activeChar); + } + + public static Disconnection of(L2PcInstance activeChar) + { + return new Disconnection(activeChar); + } + + private Disconnection(L2GameClient client, L2PcInstance activeChar) + { + _client = getClient(client, activeChar); + _activeChar = getActiveChar(client, activeChar); + + if (_client != null) + { + _client.setActiveChar(null); + } + + if (_activeChar != null) + { + _activeChar.setClient(null); + } + } + + public static Disconnection of(L2GameClient client, L2PcInstance activeChar) + { + return new Disconnection(client, activeChar); + } + + public Disconnection storeMe() + { + try + { + if (_activeChar != null) + { + _activeChar.storeMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection deleteMe() + { + try + { + if (_activeChar != null) + { + EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogout(_activeChar), _activeChar); + _activeChar.deleteMe(); + } + } + catch (RuntimeException e) + { + LOGGER.warning(e.getMessage()); + } + + return this; + } + + public Disconnection close(boolean toLoginScreen) + { + if (_client != null) + { + _client.close(toLoginScreen); + } + + return this; + } + + public Disconnection close(IClientOutgoingPacket packet) + { + if (_client != null) + { + _client.close(packet); + } + + return this; + } + + public void defaultSequence(boolean toLoginScreen) + { + defaultSequence(); + close(toLoginScreen); + } + + public void defaultSequence(IClientOutgoingPacket packet) + { + defaultSequence(); + close(packet); + } + + private void defaultSequence() + { + storeMe(); + deleteMe(); + } + + public void onDisconnection() + { + if (_activeChar != null) + { + ThreadPoolManager.schedule(() -> defaultSequence(), _activeChar.canLogout() ? 0 : AttackStanceTaskManager.COMBAT_TIME); + } + } +} \ No newline at end of file diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/L2GameClient.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/L2GameClient.java index 1ac8293de7..f51a2ac473 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/L2GameClient.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/L2GameClient.java @@ -21,9 +21,6 @@ import java.net.InetSocketAddress; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.concurrent.Future; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,36 +30,28 @@ import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.commons.network.ChannelInboundHandler; import com.l2jmobius.commons.network.ICrypt; import com.l2jmobius.commons.network.IIncomingPacket; -import com.l2jmobius.commons.network.IOutgoingPacket; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.LoginServerThread.SessionKey; -import com.l2jmobius.gameserver.ThreadPoolManager; import com.l2jmobius.gameserver.data.sql.impl.CharNameTable; import com.l2jmobius.gameserver.data.sql.impl.ClanTable; -import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; import com.l2jmobius.gameserver.enums.CharacterDeleteFailType; import com.l2jmobius.gameserver.idfactory.IdFactory; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.instancemanager.CommissionManager; import com.l2jmobius.gameserver.instancemanager.MailManager; import com.l2jmobius.gameserver.instancemanager.MentorManager; import com.l2jmobius.gameserver.model.CharSelectInfoPackage; import com.l2jmobius.gameserver.model.L2Clan; import com.l2jmobius.gameserver.model.L2World; -import com.l2jmobius.gameserver.model.actor.L2Summon; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; -import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; -import com.l2jmobius.gameserver.model.zone.ZoneId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket; +import com.l2jmobius.gameserver.network.serverpackets.LeaveWorld; import com.l2jmobius.gameserver.network.serverpackets.ServerClose; import com.l2jmobius.gameserver.network.serverpackets.SystemMessage; import com.l2jmobius.gameserver.security.SecondaryPasswordAuth; import com.l2jmobius.gameserver.util.FloodProtectors; -import com.l2jmobius.gameserver.util.Util; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; @@ -74,7 +63,7 @@ import io.netty.channel.ChannelHandlerContext; public final class L2GameClient extends ChannelInboundHandler { protected static final Logger LOGGER = Logger.getLogger(L2GameClient.class.getName()); - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); private final int _objectId; @@ -88,20 +77,15 @@ public final class L2GameClient extends ChannelInboundHandler private SecondaryPasswordAuth _secondaryAuth; private ClientHardwareInfoHolder _hardwareInfo; private boolean _isAuthedGG; - private final long _connectionStartTime = System.currentTimeMillis(); private CharSelectInfoPackage[] _charSlotMapping = null; // flood protectors private final FloodProtectors _floodProtectors = new FloodProtectors(this); - // Task - protected final ScheduledFuture _autoSaveInDB; - protected ScheduledFuture _cleanupTask = null; - // Crypt private final Crypt _crypt; - private boolean _isDetached = false; + private volatile boolean _isDetached = false; private boolean _protocol; @@ -111,14 +95,6 @@ public final class L2GameClient extends ChannelInboundHandler { _objectId = IdFactory.getInstance().getNextId(); _crypt = new Crypt(this); - if (Config.CHAR_DATA_STORE_INTERVAL > 0) - { - _autoSaveInDB = ThreadPoolManager.scheduleAtFixedRate(new AutoSaveTask(), 300000L, Config.CHAR_DATA_STORE_INTERVAL); - } - else - { - _autoSaveInDB = null; - } } public int getObjectId() @@ -135,23 +111,18 @@ public final class L2GameClient extends ChannelInboundHandler final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); _addr = address.getAddress(); _channel = ctx.channel(); - LOGGER.finer("Client Connected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Connected: " + ctx.channel()); } @Override public void channelInactive(ChannelHandlerContext ctx) { - LOGGER.finer("Client Disconnected: " + ctx.channel()); + LOG_ACCOUNTING.finer("Client Disconnected: " + ctx.channel()); - // no long running tasks here, do it async - try - { - ThreadPoolManager.execute(new DisconnectTask()); - } - catch (RejectedExecutionException e) - { - // server is closing - } + LoginServerThread.getInstance().sendLogout(getAccountName()); + IdFactory.getInstance().releaseId(getObjectId()); + + Disconnection.of(this).onDisconnection(); } @Override @@ -172,6 +143,25 @@ public final class L2GameClient extends ChannelInboundHandler { } + public void closeNow() + { + if (_channel != null) + { + _channel.close(); + } + } + + public void close(IClientOutgoingPacket packet) + { + sendPacket(packet); + closeNow(); + } + + public void close(boolean toLoginScreen) + { + close(toLoginScreen ? ServerClose.STATIC_PACKET : LeaveWorld.STATIC_PACKET); + } + public Channel getChannel() { return _channel; @@ -193,19 +183,14 @@ public final class L2GameClient extends ChannelInboundHandler return _addr; } - public long getConnectionStartTime() - { - return _connectionStartTime; - } - public L2PcInstance getActiveChar() { return _activeChar; } - public void setActiveChar(L2PcInstance pActiveChar) + public void setActiveChar(L2PcInstance activeChar) { - _activeChar = pActiveChar; + _activeChar = activeChar; } public ReentrantLock getActiveCharLock() @@ -228,9 +213,9 @@ public final class L2GameClient extends ChannelInboundHandler return _isAuthedGG; } - public void setAccountName(String pAccountName) + public void setAccountName(String activeChar) { - _accountName = pAccountName; + _accountName = activeChar; if (SecondaryAuthData.getInstance().isEnabled()) { @@ -287,16 +272,16 @@ public final class L2GameClient extends ChannelInboundHandler /** * Method to handle character deletion - * @param charslot + * @param characterSlot * @return a byte: *
  • -1: Error: No char was found for such charslot, caught exception, etc... *
  • 0: character is not member of any clan, proceed with deletion *
  • 1: character is member of a clan, but not clan leader *
  • 2: character is clan leader */ - public CharacterDeleteFailType markToDeleteChar(int charslot) + public CharacterDeleteFailType markToDeleteChar(int characterSlot) { - final int objectId = getObjectIdForSlot(charslot); + final int objectId = getObjectIdForSlot(characterSlot); if (objectId < 0) { return CharacterDeleteFailType.UNKNOWN; @@ -354,38 +339,14 @@ public final class L2GameClient extends ChannelInboundHandler } } - _logAccounting.info("Delete, " + objectId + ", " + this); + LOG_ACCOUNTING.info("Delete, " + objectId + ", " + this); return CharacterDeleteFailType.NONE; } - /** - * Save the L2PcInstance to the database. - */ - public void saveCharToDisk() + public void restore(int characterSlot) { - try - { - if (getActiveChar() != null) - { - getActiveChar().storeMe(); - getActiveChar().storeRecommendations(); - if (Config.UPDATE_ITEMS_ON_CHAR_STORE) - { - getActiveChar().getInventory().updateDatabase(); - getActiveChar().getWarehouse().updateDatabase(); - } - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error saving character..", e); - } - } - - public void markRestoredChar(int charslot) - { - final int objid = getObjectIdForSlot(charslot); - if (objid < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return; } @@ -393,7 +354,7 @@ public final class L2GameClient extends ChannelInboundHandler try (Connection con = DatabaseFactory.getInstance().getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE characters SET deletetime=0 WHERE charId=?")) { - statement.setInt(1, objid); + statement.setInt(1, objectId); statement.execute(); } catch (Exception e) @@ -401,7 +362,7 @@ public final class L2GameClient extends ChannelInboundHandler LOGGER.log(Level.SEVERE, "Error restoring character.", e); } - _logAccounting.info("Restore, " + objid + ", " + this); + LOG_ACCOUNTING.info("Restore, " + objectId + ", " + this); } public static void deleteCharByObjId(int objid) @@ -555,38 +516,30 @@ public final class L2GameClient extends ChannelInboundHandler } } - public L2PcInstance loadCharFromDisk(int charslot) + public L2PcInstance load(int characterSlot) { - final int objId = getObjectIdForSlot(charslot); - if (objId < 0) + final int objectId = getObjectIdForSlot(characterSlot); + if (objectId < 0) { return null; } - L2PcInstance character = L2World.getInstance().getPlayer(objId); - if (character != null) + L2PcInstance player = L2World.getInstance().getPlayer(objectId); + if (player != null) { // exploit prevention, should not happens in normal way - LOGGER.severe("Attempt of double login: " + character.getName() + "(" + objId + ") " + getAccountName()); - if (character.getClient() != null) - { - character.getClient().closeNow(); - } - else - { - character.deleteMe(); - } + LOGGER.severe("Attempt of double login: " + player.getName() + "(" + objectId + ") " + getAccountName()); + Disconnection.of(player).defaultSequence(false); return null; } - character = L2PcInstance.load(objId); - if (character == null) + player = L2PcInstance.load(objectId); + if (player == null) { - LOGGER.severe("could not restore in slot: " + charslot); + LOGGER.severe("Could not restore in slot: " + characterSlot); } - // setCharacter(character); - return character; + return player; } /** @@ -611,47 +564,21 @@ public final class L2GameClient extends ChannelInboundHandler return _secondaryAuth; } - public void close(IOutgoingPacket packet) - { - if (packet != null) - { - _channel.writeAndFlush(packet); - } - _channel.close(); - } - /** - * @param charslot + * @param characterSlot * @return */ - private int getObjectIdForSlot(int charslot) + private int getObjectIdForSlot(int characterSlot) { - final CharSelectInfoPackage info = getCharSelection(charslot); + final CharSelectInfoPackage info = getCharSelection(characterSlot); if (info == null) { - LOGGER.warning(toString() + " tried to delete Character in slot " + charslot + " but no characters exits at that slot."); + LOGGER.warning(toString() + " tried to delete Character in slot " + characterSlot + " but no characters exits at that slot."); return -1; } return info.getObjectId(); } - /** - * Close client connection with {@link ServerClose} packet - */ - public void closeNow() - { - _isDetached = true; // prevents more packets execution - close(ServerClose.STATIC_PACKET); - synchronized (this) - { - if (_cleanupTask != null) - { - cancelCleanup(); - } - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), 0); // instant - } - } - /** * Produces the best possible string representation of this client. */ @@ -688,209 +615,6 @@ public final class L2GameClient extends ChannelInboundHandler } } - protected class DisconnectTask implements Runnable - { - @Override - public void run() - { - boolean fast = true; - try - { - if ((getActiveChar() != null) && !isDetached()) - { - setDetached(true); - if (offlineMode(getActiveChar())) - { - getActiveChar().leaveParty(); - OlympiadManager.getInstance().unRegisterNoble(getActiveChar()); - - // If the L2PcInstance has Pet, unsummon it - L2Summon pet = getActiveChar().getPet(); - if (pet != null) - { - pet.setRestoreSummon(true); - - pet.unSummon(getActiveChar()); - pet = getActiveChar().getPet(); - // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) - if (pet != null) - { - pet.broadcastNpcInfo(0); - } - } - - getActiveChar().getServitors().values().forEach(s -> - { - s.setRestoreSummon(true); - s.unSummon(getActiveChar()); - }); - - if (Config.OFFLINE_SET_NAME_COLOR) - { - getActiveChar().getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); - getActiveChar().broadcastUserInfo(); - } - - if (getActiveChar().getOfflineStartTime() == 0) - { - getActiveChar().setOfflineStartTime(System.currentTimeMillis()); - } - - // Store trade on exit, if realtime saving is enabled. - if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) - { - OfflineTradersTable.onTransaction(getActiveChar(), false, true); - } - - _logAccounting.info("Entering offline mode, " + L2GameClient.this); - return; - } - fast = !getActiveChar().isInCombat() && !getActiveChar().isLocked(); - } - cleanMe(fast); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while disconnecting client.", e1); - } - - IdFactory.getInstance().releaseId(getObjectId()); - } - } - - /** - * @param player the player to be check. - * @return {@code true} if the player is allowed to remain as off-line shop. - */ - protected boolean offlineMode(L2PcInstance player) - { - if (player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) - { - return false; - } - - boolean canSetShop = false; - switch (player.getPrivateStoreType()) - { - case SELL: - case PACKAGE_SELL: - case BUY: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - case MANUFACTURE: - { - canSetShop = Config.OFFLINE_TRADE_ENABLE; - break; - } - default: - { - canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); - break; - } - } - - if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) - { - canSetShop = false; - } - return canSetShop; - } - - public void cleanMe(boolean fast) - { - try - { - synchronized (this) - { - if (_cleanupTask == null) - { - _cleanupTask = ThreadPoolManager.schedule(new CleanupTask(), fast ? 5 : 15000L); - } - } - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error during cleanup.", e1); - } - } - - protected class CleanupTask implements Runnable - { - @Override - public void run() - { - try - { - // we are going to manually save the char bellow thus we can force the cancel - if (_autoSaveInDB != null) - { - _autoSaveInDB.cancel(true); - // ThreadPoolManager.getInstance().removeGeneral((Runnable) _autoSaveInDB); - } - - if (getActiveChar() != null) // this should only happen on connection loss - { - if (getActiveChar().isLocked()) - { - LOGGER.warning("Player " + getActiveChar().getName() + " still performing subclass actions during disconnect."); - } - - // we store all data from players who are disconnected while in an event in order to restore it in the next login - if (L2Event.isParticipant(getActiveChar())) - { - L2Event.savePlayerEventStatus(getActiveChar()); - } - - if (getActiveChar().isOnline()) - { - getActiveChar().deleteMe(); - AntiFeedManager.getInstance().onDisconnect(L2GameClient.this); - } - - // prevent closing again - getActiveChar().setClient(null); - } - setActiveChar(null); - } - catch (Exception e1) - { - LOGGER.log(Level.WARNING, "Error while cleanup client.", e1); - } - finally - { - LoginServerThread.getInstance().sendLogout(getAccountName()); - } - } - } - - protected class AutoSaveTask implements Runnable - { - @Override - public void run() - { - try - { - final L2PcInstance player = getActiveChar(); - if ((player != null) && player.isOnline()) // safety precaution - { - saveCharToDisk(); - final L2Summon pet = player.getPet(); - if (pet != null) - { - pet.storeMe(); - } - player.getServitors().values().forEach(L2Summon::storeMe); - } - } - catch (Exception e) - { - LOGGER.log(Level.SEVERE, "Error on AutoSaveTask.", e); - } - } - } - public boolean isProtocolOk() { return _protocol; @@ -901,20 +625,6 @@ public final class L2GameClient extends ChannelInboundHandler _protocol = b; } - public boolean handleCheat(String punishment) - { - if (_activeChar != null) - { - Util.handleIllegalPlayerAction(_activeChar, toString() + ": " + punishment, Config.DEFAULT_PUNISH); - return true; - } - - final Logger logAudit = Logger.getLogger("audit"); - logAudit.info("AUDIT: Client " + toString() + " kicked for reason: " + punishment); - closeNow(); - return false; - } - public void setClientTracert(int[][] tracert) { trace = tracert; @@ -925,17 +635,6 @@ public final class L2GameClient extends ChannelInboundHandler return trace; } - private boolean cancelCleanup() - { - final Future task = _cleanupTask; - if (task != null) - { - _cleanupTask = null; - return task.cancel(true); - } - return false; - } - public void sendActionFailed() { sendPacket(ActionFailed.STATIC_PACKET); diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java index 22dfca0017..e9d948cec2 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/AuthLogin.java @@ -54,7 +54,7 @@ public final class AuthLogin implements IClientIncomingPacket { if (_loginName.isEmpty() || !client.isProtocolOk()) { - client.close(null); + client.closeNow(); return; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java index 4c50fd6574..bc34b88687 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterCreate.java @@ -41,6 +41,7 @@ import com.l2jmobius.gameserver.model.events.EventDispatcher; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerCreate; import com.l2jmobius.gameserver.model.items.PcItemTemplate; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharCreateFail; import com.l2jmobius.gameserver.network.serverpackets.CharCreateOk; @@ -333,7 +334,7 @@ public final class CharacterCreate implements IClientIncomingPacket { newChar.getVariables().set("intro_god_video", true); } - newChar.deleteMe(); + Disconnection.of(client, newChar).storeMe().deleteMe(); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java index 88fcec95d0..2766eabebd 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterRestore.java @@ -47,7 +47,7 @@ public final class CharacterRestore implements IClientIncomingPacket return; } - client.markRestoredChar(_charSlot); + client.restore(_charSlot); final CharSelectionInfo cl = new CharSelectionInfo(client.getAccountName(), client.getSessionId().playOkID1, 0); client.sendPacket(cl); client.setCharSelection(cl.getCharInfo()); diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java index 579b270fb4..8f059a4481 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/CharacterSelect.java @@ -34,6 +34,7 @@ import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.CharSelected; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -146,7 +147,7 @@ public class CharacterSelect implements IClientIncomingPacket } // load up character from disk - final L2PcInstance cha = client.loadCharFromDisk(_charSlot); + final L2PcInstance cha = client.load(_charSlot); if (cha == null) { return; // handled in L2GameClient @@ -161,7 +162,7 @@ public class CharacterSelect implements IClientIncomingPacket final TerminateReturn terminate = EventDispatcher.getInstance().notifyEvent(new OnPlayerSelect(cha, cha.getObjectId(), cha.getName(), client), Containers.Players(), TerminateReturn.class); if ((terminate != null) && terminate.terminate()) { - cha.deleteMe(); + Disconnection.of(cha).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java index bf85a9eec1..7d34624d7a 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java @@ -58,6 +58,7 @@ import com.l2jmobius.gameserver.model.quest.Quest; import com.l2jmobius.gameserver.model.skills.AbnormalVisualEffect; import com.l2jmobius.gameserver.model.variables.PlayerVariables; import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.CreatureSay; @@ -141,7 +142,7 @@ public class EnterWorld implements IClientIncomingPacket if (activeChar == null) { _log.warning("EnterWorld failed! activeChar returned 'null'."); - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } @@ -679,7 +680,7 @@ public class EnterWorld implements IClientIncomingPacket { if (client.getHardwareInfo() == null) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } }, 5000); diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java index 3f98b0bb06..8b2f68f220 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Logout.java @@ -18,14 +18,12 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; -import com.l2jmobius.gameserver.model.entity.L2Event; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -33,7 +31,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class Logout implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -47,42 +45,21 @@ public final class Logout implements IClientIncomingPacket final L2PcInstance player = client.getActiveChar(); if (player == null) { + client.closeNow(); return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to logout during class change."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; + Disconnection.of(client, player).defaultSequence(false); } - - // Don't allow leaving if player is fighting - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) - { - if (!player.isGM() || (player.isGM() && !Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_EXIT_THE_GAME_WHILE_IN_COMBAT); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - } - - if (L2Event.isParticipant(player)) - { - player.sendMessage("A superior power doesn't allow you to leave the event."); - player.sendPacket(ActionFailed.STATIC_PACKET); - return; - } - - _logAccounting.info("Disconnected, " + client); - - player.logout(); } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java index f4aeb72ea3..660c50cda8 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/ProtocolVersion.java @@ -47,7 +47,7 @@ public final class ProtocolVersion implements IClientIncomingPacket if (_version == -2) { // this is just a ping attempt from the new C2 client - client.close(null); + client.closeNow(); } else if (!Config.PROTOCOL_LIST.contains(_version)) { diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java index 942135b6d3..a85b1019cc 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestBypassToServer.java @@ -38,6 +38,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.npc.OnNpcMenuSelect; import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerBypass; import com.l2jmobius.gameserver.model.events.returns.TerminateReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage; @@ -86,7 +87,7 @@ public final class RequestBypassToServer implements IClientIncomingPacket if (_command.isEmpty()) { _log.warning("Player " + activeChar.getName() + " sent empty bypass!"); - activeChar.logout(); + Disconnection.of(client, activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java index 5a9fc6b97c..9c7b39a171 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java @@ -21,6 +21,7 @@ import com.l2jmobius.commons.network.PacketReader; import com.l2jmobius.gameserver.model.L2World; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -93,7 +94,7 @@ public final class RequestHardWareInfo implements IClientIncomingPacket } if (count >= Config.MAX_PLAYERS_PER_HWID) { - client.closeNow(); + Disconnection.of(client).defaultSequence(false); return; } } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java index a1fdeb2cf3..23c4edd13c 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/RequestRestart.java @@ -18,16 +18,15 @@ package com.l2jmobius.gameserver.network.clientpackets; import java.util.logging.Logger; -import com.l2jmobius.Config; import com.l2jmobius.commons.network.PacketReader; -import com.l2jmobius.gameserver.instancemanager.AntiFeedManager; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; -import com.l2jmobius.gameserver.network.SystemMessageId; +import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; import com.l2jmobius.gameserver.network.serverpackets.CharSelectionInfo; import com.l2jmobius.gameserver.network.serverpackets.RestartResponse; -import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; +import com.l2jmobius.gameserver.util.OfflineTradeUtil; /** * This class ... @@ -35,7 +34,7 @@ import com.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager; */ public final class RequestRestart implements IClientIncomingPacket { - protected static final Logger _logAccounting = Logger.getLogger("accounting"); + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); @Override public boolean read(L2GameClient client, PacketReader packet) @@ -52,43 +51,20 @@ public final class RequestRestart implements IClientIncomingPacket return; } - if (player.hasItemRequest()) + if (!player.canLogout()) { client.sendPacket(RestartResponse.FALSE); + player.sendPacket(ActionFailed.STATIC_PACKET); return; } - if (player.isLocked()) + LOG_ACCOUNTING.info("Logged out, " + client); + + if (!OfflineTradeUtil.enteredOfflineMode(player)) { - _log.warning("Player " + player.getName() + " tried to restart during class change."); - client.sendPacket(RestartResponse.FALSE); - return; + Disconnection.of(client, player).storeMe().deleteMe(); } - if (AttackStanceTaskManager.getInstance().hasAttackStanceTask(player) && !(player.isGM() && Config.GM_RESTART_FIGHTING)) - { - player.sendPacket(SystemMessageId.YOU_CANNOT_RESTART_WHILE_IN_COMBAT); - client.sendPacket(RestartResponse.FALSE); - return; - } - - if (player.isBlockedFromExit()) - { - client.sendPacket(RestartResponse.FALSE); - return; - } - - _logAccounting.info("Logged out, " + client); - - player.deleteMe(); - - client.setActiveChar(null); - - // detach the client from the char so that the connection isnt closed in the deleteMe - player.setClient(null); - - AntiFeedManager.getInstance().onDisconnect(client); - // return the client to the authed status client.setConnectionState(ConnectionState.AUTHENTICATED); diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java index 281601ab37..5ab9bf7732 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/network/clientpackets/Say2.java @@ -31,6 +31,7 @@ import com.l2jmobius.gameserver.model.events.impl.character.player.OnPlayerChat; import com.l2jmobius.gameserver.model.events.returns.ChatFilterReturn; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.SystemMessageId; import com.l2jmobius.gameserver.network.serverpackets.ActionFailed; @@ -110,7 +111,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning("Say2: Invalid type: " + _type + " Player : " + activeChar.getName() + " text: " + _text); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } @@ -118,7 +119,7 @@ public final class Say2 implements IClientIncomingPacket { _log.warning(activeChar.getName() + ": sending empty text. Possible packet hack!"); activeChar.sendPacket(ActionFailed.STATIC_PACKET); - activeChar.logout(); + Disconnection.of(activeChar).defaultSequence(false); return; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java index 60019030ed..1779779829 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/security/SecondaryPasswordAuth.java @@ -29,6 +29,7 @@ import java.util.logging.Logger; import com.l2jmobius.commons.database.DatabaseFactory; import com.l2jmobius.gameserver.LoginServerThread; import com.l2jmobius.gameserver.data.xml.impl.SecondaryAuthData; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordAck; import com.l2jmobius.gameserver.network.serverpackets.Ex2ndPasswordCheck; @@ -104,7 +105,7 @@ public class SecondaryPasswordAuth if (passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced savePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } @@ -157,7 +158,7 @@ public class SecondaryPasswordAuth if (!passwordExist()) { _log.warning("[SecondaryPasswordAuth]" + _activeClient.getAccountName() + " forced changePassword"); - _activeClient.closeNow(); + Disconnection.of(_activeClient).defaultSequence(false); return false; } diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java index 9612f78257..9cd2ebed02 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/taskmanager/AttackStanceTaskManager.java @@ -38,6 +38,8 @@ public class AttackStanceTaskManager protected static final Map _attackStanceTasks = new ConcurrentHashMap<>(); + public static final long COMBAT_TIME = 15_000; + /** * Instantiates a new attack stance task manager. */ @@ -106,7 +108,7 @@ public class AttackStanceTaskManager while (iter.hasNext()) { e = iter.next(); - if ((current - e.getValue()) > 15000) + if ((current - e.getValue()) > COMBAT_TIME) { actor = e.getKey(); if (actor != null) diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java index e8089917ed..e23716eba1 100644 --- a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/FloodProtectorAction.java @@ -28,6 +28,7 @@ import com.l2jmobius.gameserver.model.punishment.PunishmentAffect; import com.l2jmobius.gameserver.model.punishment.PunishmentTask; import com.l2jmobius.gameserver.model.punishment.PunishmentType; import com.l2jmobius.gameserver.network.ConnectionState; +import com.l2jmobius.gameserver.network.Disconnection; import com.l2jmobius.gameserver.network.L2GameClient; /** @@ -142,14 +143,7 @@ public final class FloodProtectorAction */ private void kickPlayer() { - if (_client.getActiveChar() != null) - { - _client.getActiveChar().logout(false); - } - else - { - _client.closeNow(); - } + Disconnection.of(_client).defaultSequence(false); if (_log.getLevel() == Level.WARNING) { diff --git a/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java new file mode 100644 index 0000000000..7394f489e8 --- /dev/null +++ b/L2J_Mobius_Classic_2.0_Zaken/java/com/l2jmobius/gameserver/util/OfflineTradeUtil.java @@ -0,0 +1,151 @@ +/* + * This file is part of the L2J Mobius project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.l2jmobius.gameserver.util; + +import java.util.logging.Logger; + +import com.l2jmobius.Config; +import com.l2jmobius.gameserver.data.sql.impl.OfflineTradersTable; +import com.l2jmobius.gameserver.model.actor.L2Summon; +import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; +import com.l2jmobius.gameserver.model.olympiad.OlympiadManager; +import com.l2jmobius.gameserver.model.zone.ZoneId; +import com.l2jmobius.gameserver.network.Disconnection; +import com.l2jmobius.gameserver.network.L2GameClient; + +/** + * @author lord_rex + */ +public final class OfflineTradeUtil +{ + protected static final Logger LOG_ACCOUNTING = Logger.getLogger("accounting"); + + private OfflineTradeUtil() + { + // utility class + } + + /** + * Check whether player is able to enter offline mode. + * @param player the player to be check. + * @return {@code true} if the player is allowed to remain as off-line shop. + */ + private static boolean offlineMode(L2PcInstance player) + { + if ((player == null) || player.isInOlympiadMode() || player.isBlockedFromExit() || player.isJailed() || (player.getVehicle() != null)) + { + return false; + } + + boolean canSetShop = false; + switch (player.getPrivateStoreType()) + { + case SELL: + case PACKAGE_SELL: + case BUY: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + case MANUFACTURE: + { + canSetShop = Config.OFFLINE_TRADE_ENABLE; + break; + } + default: + { + canSetShop = Config.OFFLINE_CRAFT_ENABLE && player.isInCraftMode(); + break; + } + } + + if (Config.OFFLINE_MODE_IN_PEACE_ZONE && !player.isInsideZone(ZoneId.PEACE)) + { + canSetShop = false; + } + + // Check whether client is null or player is already in offline mode. + final L2GameClient client = player.getClient(); + if ((client == null) || client.isDetached()) + { + return false; + } + + return canSetShop; + } + + /** + * Manages the disconnection process of offline traders. + * @param player + * @return {@code true} when player entered offline mode, otherwise {@code false} + */ + public static boolean enteredOfflineMode(L2PcInstance player) + { + if (!OfflineTradeUtil.offlineMode(player)) + { + return false; + } + + final L2GameClient client = player.getClient(); + client.setDetached(true); + + player.leaveParty(); + OlympiadManager.getInstance().unRegisterNoble(player); + + // If the L2PcInstance has Pet, unsummon it + L2Summon pet = player.getPet(); + if (pet != null) + { + pet.setRestoreSummon(true); + + pet.unSummon(player); + pet = player.getPet(); + // Dead pet wasn't unsummoned, broadcast npcinfo changes (pet will be without owner name - means owner offline) + if (pet != null) + { + pet.broadcastNpcInfo(0); + } + } + + player.getServitors().values().forEach(s -> + { + s.setRestoreSummon(true); + s.unSummon(player); + }); + + if (Config.OFFLINE_SET_NAME_COLOR) + { + player.getAppearance().setNameColor(Config.OFFLINE_NAME_COLOR); + player.broadcastUserInfo(); + } + + if (player.getOfflineStartTime() == 0) + { + player.setOfflineStartTime(System.currentTimeMillis()); + } + + // Store trade on exit, if realtime saving is enabled. + if (Config.STORE_OFFLINE_TRADE_IN_REALTIME) + { + OfflineTradersTable.onTransaction(player, false, true); + } + + Disconnection.of(player).storeMe().close(false); + LOG_ACCOUNTING.info("Entering offline mode, " + client); + return true; + } +}