Handle disconnect solely in TransitionService
This commit is contained in:
@@ -1755,32 +1755,31 @@ public class Character extends AbstractCharacterObject {
|
||||
|
||||
sendPacket(warpPacket);
|
||||
map.removePlayer(this);
|
||||
if (client.getChannelServer().getPlayerStorage().getCharacterById(getId()) != null) {
|
||||
map = to;
|
||||
setPosition(pos);
|
||||
map.addPlayer(this);
|
||||
visitMap(map);
|
||||
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (party != null) {
|
||||
mpc.setMapId(to.getId());
|
||||
sendPacket(PacketCreator.updateParty(client.getChannel(), party, PartyOperation.SILENT_UPDATE, null));
|
||||
updatePartyMemberHPInternal();
|
||||
}
|
||||
} finally {
|
||||
prtLock.unlock();
|
||||
}
|
||||
if (Character.this.getParty() != null) {
|
||||
Character.this.getParty().setEnemy(k);
|
||||
}
|
||||
silentPartyUpdateInternal(getParty()); // EIM script calls inside
|
||||
} else {
|
||||
if (client.getChannelServer().getPlayerStorage().getCharacterById(id) == null) {
|
||||
log.warn("Chr {} got stuck when moving to map {}", getName(), map.getId());
|
||||
client.disconnect(true, false); // thanks BHB for noticing a player storage stuck case here
|
||||
return;
|
||||
}
|
||||
|
||||
map = to;
|
||||
setPosition(pos);
|
||||
map.addPlayer(this);
|
||||
visitMap(map);
|
||||
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (party != null) {
|
||||
mpc.setMapId(to.getId());
|
||||
sendPacket(PacketCreator.updateParty(client.getChannel(), party, PartyOperation.SILENT_UPDATE, null));
|
||||
updatePartyMemberHPInternal();
|
||||
}
|
||||
} finally {
|
||||
prtLock.unlock();
|
||||
}
|
||||
if (Character.this.getParty() != null) {
|
||||
Character.this.getParty().setEnemy(k);
|
||||
}
|
||||
silentPartyUpdateInternal(getParty()); // EIM script calls inside
|
||||
|
||||
notifyMapTransferToPartner(map.getId());
|
||||
|
||||
//alas, new map has been specified when a warping was being processed...
|
||||
@@ -8175,20 +8174,14 @@ public class Character extends AbstractCharacterObject {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: all callers should use CharacterSaver instead.
|
||||
// It's supposed to act as a proxy to these 2 methods (as a first step towards taking full ownership of character saving)
|
||||
public void saveCharToDB() {
|
||||
saveCharToDB(true);
|
||||
}
|
||||
|
||||
//ItemFactory saveItems and monsterbook.saveCards are the most time consuming here.
|
||||
public synchronized void saveCharToDB(boolean notAutosave) {
|
||||
public synchronized void saveCharToDB() {
|
||||
if (!loggedIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
log.debug("Attempting to {} chr {}", notAutosave ? "save" : "autosave", name);
|
||||
log.debug("Saving chr {}", name);
|
||||
|
||||
Server.getInstance().updateCharacterEntry(this);
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package client;
|
||||
|
||||
import config.YamlConfig;
|
||||
import constants.id.MapId;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.timeout.IdleStateEvent;
|
||||
@@ -41,34 +40,24 @@ import net.server.coordinator.login.LoginBypassCoordinator;
|
||||
import net.server.coordinator.session.Hwid;
|
||||
import net.server.coordinator.session.SessionCoordinator;
|
||||
import net.server.coordinator.session.SessionCoordinator.AntiMulticlientResult;
|
||||
import net.server.guild.Guild;
|
||||
import net.server.guild.GuildCharacter;
|
||||
import net.server.guild.GuildPackets;
|
||||
import net.server.world.MessengerCharacter;
|
||||
import net.server.world.Party;
|
||||
import net.server.world.PartyCharacter;
|
||||
import net.server.world.PartyOperation;
|
||||
import net.server.world.World;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import scripting.event.EventManager;
|
||||
import scripting.npc.NPCConversationManager;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
import scripting.quest.QuestActionManager;
|
||||
import scripting.quest.QuestScriptManager;
|
||||
import server.ThreadManager;
|
||||
import server.TimerManager;
|
||||
import server.life.Monster;
|
||||
import server.maps.MapleMap;
|
||||
import tools.BCrypt;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.HexTool;
|
||||
import tools.PacketCreator;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
@@ -212,7 +201,8 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
MonitoredChrLogger.logPacketIfMonitored(this, opcode, packet.getBytes());
|
||||
handler.handlePacket(packet, this);
|
||||
} catch (GameViolationException gve) {
|
||||
throw new DisconnectException(this, gve.getMessage());
|
||||
log.warn("Game violation (disconnecting): {}", gve.getMessage());
|
||||
throw new DisconnectException(this, true);
|
||||
} catch (final Throwable t) {
|
||||
final String chrInfo = player != null ? player.getName() + " on map " + player.getMapId() : "?";
|
||||
log.warn("Error in packet handler {}. Chr {}, account {}. Packet: {}", handler.getClass().getSimpleName(),
|
||||
@@ -232,15 +222,13 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
if (player != null) {
|
||||
log.warn("Exception caught by {}", player, cause);
|
||||
}
|
||||
|
||||
if (cause instanceof InvalidPacketHeaderException) {
|
||||
SessionCoordinator.getInstance().closeSession(this, true);
|
||||
} else if (cause instanceof IOException) {
|
||||
closeMapleSession();
|
||||
} else {
|
||||
ctx.fireExceptionCaught(cause);
|
||||
}
|
||||
@@ -248,10 +236,6 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) {
|
||||
closeMapleSession();
|
||||
}
|
||||
|
||||
private void closeMapleSession() {
|
||||
switch (type) {
|
||||
case LOGIN -> SessionCoordinator.getInstance().closeLoginSession(this);
|
||||
case CHANNEL -> SessionCoordinator.getInstance().closeSession(this, false);
|
||||
@@ -260,7 +244,7 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
try {
|
||||
// client freeze issues on session transition states found thanks to yolinlin, Omo Oppa, Nozphex
|
||||
if (!inTransition) {
|
||||
disconnect(false, false);
|
||||
ctx.fireExceptionCaught(new DisconnectException(this, false));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.warn("Account stuck", t);
|
||||
@@ -693,11 +677,6 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
public void updateLoginState(int newState) {
|
||||
// rules out possibility of multiple account entries
|
||||
if (newState == LOGIN_LOGGEDIN) {
|
||||
SessionCoordinator.getInstance().updateOnlineClient(this);
|
||||
}
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("UPDATE accounts SET loggedin = ?, lastlogin = ? WHERE id = ?")) {
|
||||
// using sql currenttime here could potentially break the login, thanks Arnah for pointing this out
|
||||
@@ -770,85 +749,6 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
return date.get(Calendar.YEAR) == birthday.get(Calendar.YEAR) && date.get(Calendar.MONTH) == birthday.get(Calendar.MONTH) && date.get(Calendar.DAY_OF_MONTH) == birthday.get(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
private void removePartyPlayer(World wserv) {
|
||||
MapleMap map = player.getMap();
|
||||
final Party party = player.getParty();
|
||||
final int idz = player.getId();
|
||||
|
||||
if (party != null) {
|
||||
final PartyCharacter chrp = new PartyCharacter(player);
|
||||
chrp.setOnline(false);
|
||||
wserv.updateParty(party.getId(), PartyOperation.LOG_ONOFF, chrp);
|
||||
if (party.getLeader().getId() == idz && map != null) {
|
||||
PartyCharacter lchr = null;
|
||||
for (PartyCharacter pchr : party.getMembers()) {
|
||||
if (pchr != null && pchr.getId() != idz && (lchr == null || lchr.getLevel() <= pchr.getLevel()) && map.getCharacterById(pchr.getId()) != null) {
|
||||
lchr = pchr;
|
||||
}
|
||||
}
|
||||
if (lchr != null) {
|
||||
wserv.updateParty(party.getId(), PartyOperation.CHANGE_LEADER, lchr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removePlayer(World wserv, boolean serverTransition) {
|
||||
try {
|
||||
player.setDisconnectedFromChannelWorld();
|
||||
player.notifyMapTransferToPartner(-1);
|
||||
player.removeIncomingInvites();
|
||||
player.cancelAllBuffs(true);
|
||||
|
||||
player.closePlayerInteractions();
|
||||
player.closePartySearchInteractions();
|
||||
|
||||
if (!serverTransition) { // thanks MedicOP for detecting an issue with party leader change on changing channels
|
||||
removePartyPlayer(wserv);
|
||||
|
||||
EventInstanceManager eim = player.getEventInstance();
|
||||
if (eim != null) {
|
||||
eim.playerDisconnected(player);
|
||||
}
|
||||
|
||||
if (player.getMonsterCarnival() != null) {
|
||||
player.getMonsterCarnival().playerDisconnected(getPlayer().getId());
|
||||
}
|
||||
|
||||
if (player.getAriantColiseum() != null) {
|
||||
player.getAriantColiseum().playerDisconnected(getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
if (player.getMap() != null) {
|
||||
int mapId = player.getMapId();
|
||||
player.getMap().removePlayer(player);
|
||||
if (MapId.isDojo(mapId)) {
|
||||
this.getChannelServer().freeDojoSectionIfEmpty(mapId);
|
||||
}
|
||||
|
||||
if (player.getMap().getHPDec() > 0) {
|
||||
getWorldServer().removePlayerHpDecrease(player);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (final Throwable t) {
|
||||
log.error("Account stuck", t);
|
||||
}
|
||||
}
|
||||
|
||||
public final void disconnect(final boolean shutdown, final boolean cashshop) {
|
||||
if (tryDisconnect()) {
|
||||
ThreadManager.getInstance().newTask(() -> disconnectInternal(shutdown, cashshop));
|
||||
}
|
||||
}
|
||||
|
||||
public final void forceDisconnect() {
|
||||
if (tryDisconnect()) {
|
||||
disconnectInternal(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean tryDisconnect() {
|
||||
if (disconnecting) {
|
||||
return false;
|
||||
@@ -858,88 +758,6 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void disconnectInternal(boolean shutdown, boolean cashshop) {//once per Client instance
|
||||
if (player != null && player.isLoggedin() && player.getClient() != null) {
|
||||
final int messengerid = player.getMessenger() == null ? 0 : player.getMessenger().getId();
|
||||
final BuddyList bl = player.getBuddylist();
|
||||
final MessengerCharacter messengerChr = new MessengerCharacter(player, 0);
|
||||
final GuildCharacter guildChr = player.getMGC();
|
||||
final Guild guild = player.getGuild();
|
||||
|
||||
player.cancelMagicDoor();
|
||||
|
||||
final World wserv = getWorldServer(); // obviously wserv is NOT null if this player was online on it
|
||||
try {
|
||||
removePlayer(wserv, this.serverTransition);
|
||||
|
||||
if (!(channel == -1 || shutdown)) {
|
||||
if (!cashshop) {
|
||||
if (!this.serverTransition) { // meaning not changing channels
|
||||
if (messengerid > 0) {
|
||||
wserv.leaveMessenger(messengerid, messengerChr);
|
||||
}
|
||||
|
||||
player.forfeitExpirableQuests(); //This is for those quests that you have to stay logged in for a certain amount of time
|
||||
|
||||
if (guild != null) {
|
||||
final Server server = Server.getInstance();
|
||||
server.setGuildMemberOnline(player, false, player.getClient().getChannel());
|
||||
player.sendPacket(GuildPackets.showGuildInfo(player));
|
||||
}
|
||||
if (bl != null) {
|
||||
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!this.serverTransition) { // if dc inside of cash shop.
|
||||
if (bl != null) {
|
||||
wserv.loggedOff(player.getName(), player.getId(), channel, player.getBuddylist().getBuddyIds());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Account stuck", e);
|
||||
} finally {
|
||||
if (!this.serverTransition) {
|
||||
if (guildChr != null) {
|
||||
guildChr.setCharacter(null);
|
||||
}
|
||||
wserv.removePlayer(player);
|
||||
//getChannelServer().removePlayer(player); already being done
|
||||
|
||||
player.cancelAllDebuffs();
|
||||
player.saveCharToDB();
|
||||
|
||||
player.logOff();
|
||||
if (YamlConfig.config.server.INSTANT_NAME_CHANGE) {
|
||||
player.doPendingNameChange();
|
||||
}
|
||||
clear();
|
||||
} else {
|
||||
getChannelServer().removePlayer(player);
|
||||
|
||||
player.cancelAllDebuffs();
|
||||
player.saveCharToDB();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SessionCoordinator.getInstance().closeSession(this, false);
|
||||
|
||||
if (!serverTransition && isLoggedIn()) {
|
||||
updateLoginState(Client.LOGIN_NOTLOGGEDIN);
|
||||
|
||||
clear();
|
||||
} else {
|
||||
if (!Server.getInstance().hasCharacteridInTransition(this)) {
|
||||
updateLoginState(Client.LOGIN_NOTLOGGEDIN);
|
||||
}
|
||||
|
||||
engines = null; // thanks Tochi for pointing out a NPE here
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
// player hard reference removal thanks to Steve (kaito1410)
|
||||
if (this.player != null) {
|
||||
@@ -956,6 +774,12 @@ public class Client extends ChannelInboundHandlerAdapter {
|
||||
this.player = null;
|
||||
}
|
||||
|
||||
public void clearEngines() {
|
||||
if (engines != null) {
|
||||
engines.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCharacterOnSessionTransitionState(int cid) {
|
||||
this.updateLoginState(Client.LOGIN_SERVER_TRANSITION);
|
||||
this.inTransition = true;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class DcCommand extends Command {
|
||||
victim = player.getMap().getCharacterByName(chrName);
|
||||
if (victim != null) {
|
||||
try {//sometimes bugged because the map = null
|
||||
ctx.transitionService().disconnect(victim.getClient(), true, false);
|
||||
ctx.transitionService().disconnect(victim.getClient(), true);
|
||||
player.getMap().removePlayer(victim);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -62,6 +62,6 @@ public class DcCommand extends Command {
|
||||
if (player.gmLevel() < victim.gmLevel()) {
|
||||
victim = player;
|
||||
}
|
||||
ctx.transitionService().disconnect(victim.getClient(), false, false);
|
||||
ctx.transitionService().disconnect(victim.getClient(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class BanCommand extends Command {
|
||||
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
|
||||
final Character rip = target;
|
||||
TimerManager.getInstance().schedule(
|
||||
() -> ctx.transitionService().disconnect(rip.getClient(), false, false),
|
||||
() -> ctx.transitionService().disconnect(rip.getClient(), false),
|
||||
TimeUnit.SECONDS.toMillis(5)
|
||||
);
|
||||
Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned."));
|
||||
|
||||
@@ -41,7 +41,7 @@ public class DCAllCommand extends Command {
|
||||
for (World world : Server.getInstance().getWorlds()) {
|
||||
for (Character chr : world.getPlayerStorage().getAllCharacters()) {
|
||||
if (!chr.isGM()) {
|
||||
ctx.transitionService().disconnect(chr.getClient(), false, false);
|
||||
ctx.transitionService().disconnect(chr.getClient(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class CharacterSaver {
|
||||
}
|
||||
|
||||
public void save(Character chr) {
|
||||
chr.saveCharToDB(false);
|
||||
chr.saveCharToDB();
|
||||
|
||||
// Saving monster cards to both MySQL and Postgres for now
|
||||
monsterCardDao.save(chr.getId(), chr.getMonsterBook().getCards());
|
||||
|
||||
@@ -4,13 +4,18 @@ import client.Client;
|
||||
|
||||
public class DisconnectException extends RuntimeException {
|
||||
private final Client client;
|
||||
private final boolean shutdown;
|
||||
|
||||
public DisconnectException(Client client, String message) {
|
||||
super(message);
|
||||
public DisconnectException(Client client, boolean shutdown) {
|
||||
this.client = client;
|
||||
this.shutdown = shutdown;
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public boolean isShutdown() {
|
||||
return shutdown;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class DisconnectHandler extends ChannelInboundHandlerAdapter {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||
if (cause instanceof DisconnectException de) {
|
||||
var client = de.getClient();
|
||||
transitionService.disconnect(client, true, false);
|
||||
transitionService.disconnect(client, true);
|
||||
} else {
|
||||
ctx.fireExceptionCaught(cause);
|
||||
}
|
||||
|
||||
@@ -1923,7 +1923,7 @@ public class Server {
|
||||
|
||||
for (Client c : toDisconnect) { // thanks Lei for pointing a deadlock issue with srvLock
|
||||
if (c.isLoggedIn()) {
|
||||
channelDependencies.transitionService().disconnect(c, false, false);
|
||||
channelDependencies.transitionService().disconnect(c, false);
|
||||
} else {
|
||||
SessionCoordinator.getInstance().closeSession(c, true);
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ public final class AdminCommandHandler extends AbstractPacketHandler {
|
||||
private void sendPolice(Client c, String reason) {
|
||||
c.sendPacket(PacketCreator.sendPolice(String.format("You have been blocked by the#b %s Police for %s.#k", "Cosmic", reason)));
|
||||
c.getPlayer().setBanned();
|
||||
TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false, false),
|
||||
TimerManager.getInstance().schedule(() -> transitionService.disconnect(c, false),
|
||||
TimeUnit.SECONDS.toMillis(6));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,24 +109,6 @@ public class SessionCoordinator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites any existing online client for the account id, making sure to disconnect it as well.
|
||||
*/
|
||||
public void updateOnlineClient(Client client) {
|
||||
if (client != null) {
|
||||
int accountId = client.getAccID();
|
||||
disconnectClientIfOnline(accountId);
|
||||
onlineClients.put(accountId, client);
|
||||
}
|
||||
}
|
||||
|
||||
private void disconnectClientIfOnline(int accountId) {
|
||||
Client ingameClient = onlineClients.get(accountId);
|
||||
if (ingameClient != null) { // thanks MedicOP for finding out a loss of loggedin account uniqueness when using the CMS "Unstuck" feature
|
||||
ingameClient.forceDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canStartLoginSession(Client client) {
|
||||
if (!YamlConfig.config.server.DETERRED_MULTICLIENT) {
|
||||
return true;
|
||||
|
||||
@@ -28,7 +28,7 @@ public class TimeoutTask extends BaseTask implements Runnable {
|
||||
for (Character chr : chars) {
|
||||
if (time - chr.getClient().getLastPacket() > YamlConfig.config.server.TIMEOUT_DURATION) {
|
||||
log.info("Chr {} auto-disconnected due to inactivity", chr.getName());
|
||||
transitionService.disconnect(chr.getClient(), true, chr.getCashShop().isOpened());
|
||||
transitionService.disconnect(chr.getClient(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class BanService {
|
||||
chr.ban(reason);
|
||||
|
||||
chr.sendPacket(PacketCreator.sendPolice("You have been blocked by the#b %s Police for HACK reason.#k".formatted("Cosmic")));
|
||||
TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false, false),
|
||||
TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false),
|
||||
TimeUnit.SECONDS.toMillis(5));
|
||||
|
||||
var bannedName = Character.makeMapleReadable(chr.getName());
|
||||
|
||||
@@ -6,7 +6,9 @@ import client.inventory.InventoryType;
|
||||
import config.YamlConfig;
|
||||
import constants.id.MapId;
|
||||
import database.character.CharacterSaver;
|
||||
import net.netty.LoginServer;
|
||||
import net.server.Server;
|
||||
import net.server.coordinator.session.SessionCoordinator;
|
||||
import net.server.guild.Guild;
|
||||
import net.server.guild.GuildCharacter;
|
||||
import net.server.guild.GuildPackets;
|
||||
@@ -39,7 +41,7 @@ public class TransitionService {
|
||||
public void changeChannel(Client c, int channel) {
|
||||
var chr = c.getPlayer();
|
||||
if (chr.isBanned()) {
|
||||
disconnect(c, false, false);
|
||||
disconnect(c, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -93,21 +95,19 @@ public class TransitionService {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: take code from Client#disconnect & forceDisconnect. Move it here.
|
||||
// It's not gonna be easy to move all instances of c.disconnect, but it has to be done.
|
||||
public void disconnect(final Client c, final boolean shutdown, final boolean cashShop) {
|
||||
public void disconnect(final Client c, final boolean shutdown) {
|
||||
if (c.tryDisconnect()) {
|
||||
ThreadManager.getInstance().newTask(() -> disconnectInternal(c, shutdown, cashShop));
|
||||
ThreadManager.getInstance().newTask(() -> disconnectInternal(c, shutdown));
|
||||
}
|
||||
}
|
||||
|
||||
public void forceDisconnect(Client c) {
|
||||
if (c.tryDisconnect()) {
|
||||
disconnectInternal(c, true, false);
|
||||
disconnectInternal(c, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void disconnectInternal(Client c, boolean shutdown, boolean cashShop) {
|
||||
private void disconnectInternal(Client c, boolean shutdown) {
|
||||
var chr = c.getPlayer();
|
||||
if (chr != null && chr.isLoggedin() && chr.getClient() != null) {
|
||||
final int messengerid = chr.getMessenger() == null ? 0 : chr.getMessenger().getId();
|
||||
@@ -123,29 +123,21 @@ public class TransitionService {
|
||||
removePlayer(c, wserv, c.isInTransition());
|
||||
|
||||
final int channel = c.getChannel();
|
||||
if (!(channel == -1 || shutdown)) {
|
||||
if (!cashShop) {
|
||||
if (!c.isInTransition()) { // meaning not changing channels
|
||||
if (messengerid > 0) {
|
||||
wserv.leaveMessenger(messengerid, messengerChr);
|
||||
}
|
||||
|
||||
chr.forfeitExpirableQuests(); //This is for those quests that you have to stay logged in for a certain amount of time
|
||||
|
||||
if (guild != null) {
|
||||
final Server server = Server.getInstance();
|
||||
server.setGuildMemberOnline(chr, false, chr.getClient().getChannel());
|
||||
chr.sendPacket(GuildPackets.showGuildInfo(chr));
|
||||
}
|
||||
if (bl != null) {
|
||||
wserv.loggedOff(chr.getName(), chr.getId(), channel, chr.getBuddylist().getBuddyIds());
|
||||
}
|
||||
if (!(channel == LoginServer.CHANNEL_ID || shutdown)) {
|
||||
if (!c.isInTransition()) { // meaning not changing channels
|
||||
if (messengerid > 0) {
|
||||
wserv.leaveMessenger(messengerid, messengerChr);
|
||||
}
|
||||
} else {
|
||||
if (!c.isInTransition()) { // if dc inside of cash shop.
|
||||
if (bl != null) {
|
||||
wserv.loggedOff(chr.getName(), chr.getId(), channel, chr.getBuddylist().getBuddyIds());
|
||||
}
|
||||
|
||||
chr.forfeitExpirableQuests(); //This is for those quests that you have to stay logged in for a certain amount of time
|
||||
|
||||
if (guild != null) {
|
||||
final Server server = Server.getInstance();
|
||||
server.setGuildMemberOnline(chr, false, chr.getClient().getChannel());
|
||||
chr.sendPacket(GuildPackets.showGuildInfo(chr));
|
||||
}
|
||||
if (bl != null) {
|
||||
wserv.loggedOff(chr.getName(), chr.getId(), channel, chr.getBuddylist().getBuddyIds());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +167,20 @@ public class TransitionService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SessionCoordinator.getInstance().closeSession(c, false);
|
||||
|
||||
|
||||
if (!c.isInTransition() && c.isLoggedIn()) {
|
||||
c.updateLoginState(Client.LOGIN_NOTLOGGEDIN);
|
||||
c.clear();
|
||||
} else {
|
||||
if (!Server.getInstance().hasCharacteridInTransition(c)) {
|
||||
c.updateLoginState(Client.LOGIN_NOTLOGGEDIN);
|
||||
}
|
||||
|
||||
c.clearEngines();
|
||||
}
|
||||
}
|
||||
|
||||
private void removePlayer(Client c, World world, boolean serverTransition) {
|
||||
|
||||
Reference in New Issue
Block a user