diff --git a/src/intents/network/ForceDisconnectIntent.java b/src/intents/network/ForceDisconnectIntent.java new file mode 100644 index 000000000..2a973681f --- /dev/null +++ b/src/intents/network/ForceDisconnectIntent.java @@ -0,0 +1,58 @@ +package intents.network; + +import network.packets.soe.Disconnect.DisconnectReason; +import resources.control.Intent; +import resources.player.Player; + +public class ForceDisconnectIntent extends Intent { + + public static final String TYPE = "ForceDisconnectIntent"; + + private Player player; + private DisconnectReason reason; + private boolean disappearImmediately; + + public ForceDisconnectIntent(Player player) { + this(player, false); + } + + public ForceDisconnectIntent(Player player, DisconnectReason reason) { + this(player, reason, false); + } + + public ForceDisconnectIntent(Player player, boolean disappearImmediately) { + this(player, DisconnectReason.APPLICATION, disappearImmediately); + } + + public ForceDisconnectIntent(Player player, DisconnectReason reason, boolean disappearImmediately) { + super(TYPE); + setPlayer(player); + setDisconnectReason(reason); + setDisappearImmediately(disappearImmediately); + } + + public void setPlayer(Player player) { + this.player = player; + } + + public void setDisconnectReason(DisconnectReason reason) { + this.reason = reason; + } + + public void setDisappearImmediately(boolean disappearImmediately) { + this.disappearImmediately = disappearImmediately; + } + + public Player getPlayer() { + return player; + } + + public DisconnectReason getDisconnectReason() { + return reason; + } + + public boolean getDisappearImmediately() { + return disappearImmediately; + } + +} diff --git a/src/services/galaxy/ConnectionService.java b/src/services/galaxy/ConnectionService.java index 7cf353120..355ad3a9d 100644 --- a/src/services/galaxy/ConnectionService.java +++ b/src/services/galaxy/ConnectionService.java @@ -40,6 +40,7 @@ import network.packets.soe.Disconnect.DisconnectReason; import network.packets.swg.zone.HeartBeatMessage; import intents.PlayerEventIntent; import intents.network.CloseConnectionIntent; +import intents.network.ForceDisconnectIntent; import intents.network.GalacticPacketIntent; import resources.control.Intent; import resources.control.Service; @@ -92,6 +93,7 @@ public class ConnectionService extends Service { public boolean initialize() { registerForIntent(PlayerEventIntent.TYPE); registerForIntent(GalacticPacketIntent.TYPE); + registerForIntent(ForceDisconnectIntent.TYPE); return super.initialize(); } @@ -115,39 +117,59 @@ public class ConnectionService extends Service { @Override public void onIntentReceived(Intent i) { - if (i instanceof PlayerEventIntent) { - if (((PlayerEventIntent)i).getEvent() == PlayerEvent.PE_ZONE_IN) { - Player p = ((PlayerEventIntent)i).getPlayer(); + if (i instanceof PlayerEventIntent) + onPlayerEventIntent((PlayerEventIntent) i); + else if (i instanceof GalacticPacketIntent) + onGalacticPacketIntent((GalacticPacketIntent) i); + else if (i instanceof ForceDisconnectIntent) + onForceDisconnectIntent((ForceDisconnectIntent) i); + } + + private void onPlayerEventIntent(PlayerEventIntent pei) { + switch (pei.getEvent()) { + case PE_ZONE_IN: { + Player p = pei.getPlayer(); synchronized (zonedInPlayers) { removeOld(p); zonedInPlayers.add(p); } - } else if (((PlayerEventIntent)i).getEvent() == PlayerEvent.PE_DISAPPEAR) { - synchronized (zonedInPlayers) { - zonedInPlayers.remove(((PlayerEventIntent)i).getPlayer()); - } + break; } - } else if (i instanceof GalacticPacketIntent) { - if (((GalacticPacketIntent)i).getPacket() instanceof HeartBeatMessage) { - GalacticPacketIntent gpi = (GalacticPacketIntent) i; - Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); - if (p != null) - p.sendPacket(gpi.getPacket()); - } else if (((GalacticPacketIntent)i).getPacket() instanceof Disconnect) { - GalacticPacketIntent gpi = (GalacticPacketIntent) i; - Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); - if (p != null) { - if (p.getPlayerState() != PlayerState.DISCONNECTED) { - logOut(p); - disconnect(p, DisconnectReason.TIMEOUT); - } else { - disconnect(p, DisconnectReason.OTHER_SIDE_TERMINATED); - } + case PE_DISAPPEAR: + synchronized (zonedInPlayers) { + zonedInPlayers.remove(pei.getPlayer()); + } + break; + default: + break; + } + } + + private void onGalacticPacketIntent(GalacticPacketIntent gpi) { + if (gpi.getPacket() instanceof HeartBeatMessage) { + Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); + if (p != null) + p.sendPacket(gpi.getPacket()); + } else if (gpi.getPacket() instanceof Disconnect) { + Player p = gpi.getPlayerManager().getPlayerFromNetworkId(gpi.getNetworkId()); + if (p != null) { + if (p.getPlayerState() != PlayerState.DISCONNECTED) { + logOut(p); + disconnect(p, DisconnectReason.TIMEOUT); + } else { + disconnect(p, DisconnectReason.OTHER_SIDE_TERMINATED); } } } } + private void onForceDisconnectIntent(ForceDisconnectIntent fdi) { + logOut(fdi.getPlayer(), !fdi.getDisappearImmediately()); + disconnect(fdi.getPlayer(), fdi.getDisconnectReason()); + if (fdi.getDisappearImmediately()) + disappear(fdi.getPlayer()); + } + private void removeOld(Player nPlayer) { synchronized (zonedInPlayers) { Iterator zonedIterator = zonedInPlayers.iterator(); @@ -162,14 +184,20 @@ public class ConnectionService extends Service { } private void logOut(Player p) { + logOut(p, true); + } + + private void logOut(Player p, boolean addToDisappear) { updatePlayTime(p); if (p.getPlayerState() != PlayerState.LOGGED_OUT) System.out.println("[" + p.getUsername() +"] Logged out " + p.getCharacterName()); if (p.getPlayerObject() != null) p.getPlayerObject().setFlagBitmask(PlayerFlags.LD); p.setPlayerState(PlayerState.LOGGED_OUT); - disappearPlayers.add(p); - updateService.schedule(disappearRunnable, (long) DISAPPEAR_THRESHOLD, TimeUnit.MILLISECONDS); + if (addToDisappear) { + disappearPlayers.add(p); + updateService.schedule(disappearRunnable, (long) DISAPPEAR_THRESHOLD, TimeUnit.MILLISECONDS); + } } private void disappear(Player p) { diff --git a/src/services/player/PlayerManager.java b/src/services/player/PlayerManager.java index 0f7225110..55a73f57c 100644 --- a/src/services/player/PlayerManager.java +++ b/src/services/player/PlayerManager.java @@ -35,10 +35,12 @@ import java.util.Locale; import java.util.Map; import network.packets.Packet; +import network.packets.soe.Disconnect.DisconnectReason; import network.packets.swg.login.ClientIdMsg; import network.packets.swg.zone.insertion.SelectCharacter; import intents.NotifyPlayersPacketIntent; import intents.PlayerEventIntent; +import intents.network.ForceDisconnectIntent; import intents.network.GalacticPacketIntent; import intents.network.InboundPacketIntent; import resources.Terrain; @@ -153,7 +155,9 @@ public class PlayerManager extends Manager { } public Player getPlayerFromNetworkId(long networkId) { - return players.get(networkId); + synchronized (players) { + return players.get(networkId); + } } private void removeDuplicatePlayers(Player player, long charId) { @@ -161,8 +165,10 @@ public class PlayerManager extends Manager { Iterator it = players.values().iterator(); while (it.hasNext()) { Player p = it.next(); - if (p != player && p.getCreatureObject() != null && p.getCreatureObject().getObjectId() == charId) + if (p != player && p.getCreatureObject() != null && p.getCreatureObject().getObjectId() == charId) { + new ForceDisconnectIntent(p, DisconnectReason.NEW_CONNECTION_ATTEMPT, true).broadcast(); it.remove(); + } } } } @@ -192,17 +198,18 @@ public class PlayerManager extends Manager { } private void onPlayerEventIntent(PlayerEventIntent pei) { - if (pei.getEvent() == PlayerEvent.PE_DISAPPEAR) { - Player p = pei.getPlayer(); - if (p.getPlayerState() == PlayerState.DISCONNECTED) { - players.remove(p.getNetworkId()); + synchronized (players) { + if (pei.getEvent() == PlayerEvent.PE_DISAPPEAR) { + Player p = pei.getPlayer(); + if (p.getPlayerState() == PlayerState.DISCONNECTED) { + players.remove(p.getNetworkId()); + } } } } private void onInboundPacketIntent(InboundPacketIntent ipi) { - long networkId = ipi.getNetworkId(); - Player player = players.get(networkId); + Player player = getPlayerFromNetworkId(ipi.getNetworkId()); if (player != null) player.updateLastPacketTimestamp(); } @@ -215,12 +222,14 @@ public class PlayerManager extends Manager { if (type == ServerType.ZONE && packet instanceof ClientIdMsg) player = transitionLoginToZone(networkId, gpi.getGalaxy().getId(), (ClientIdMsg) packet); else - player = players.get(networkId); + player = getPlayerFromNetworkId(networkId); if (player != null && type == ServerType.ZONE && packet instanceof SelectCharacter) removeDuplicatePlayers(player, ((SelectCharacter)packet).getCharacterId()); if (type == ServerType.LOGIN && player == null) { player = new Player(this, networkId); - players.put(networkId, player); + synchronized (players) { + players.put(networkId, player); + } } if (player != null) { if (type == ServerType.LOGIN)