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:
- *
- * - 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.
*/
@@ -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;
+ }
+}