diff --git a/src/services/ConnectionService.java b/src/services/ConnectionService.java index 8619f799..ef84dbc0 100644 --- a/src/services/ConnectionService.java +++ b/src/services/ConnectionService.java @@ -25,7 +25,13 @@ import java.nio.ByteOrder; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import main.NGECore; @@ -42,9 +48,13 @@ import protocol.swg.HeartBeatMessage; import engine.clients.Client; import engine.resources.database.DatabaseConnection; +import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; import resources.common.*; +import resources.common.collidables.AbstractCollidable; +import resources.objects.creature.CreatureObject; +import resources.objects.player.PlayerObject; @SuppressWarnings("unused") @@ -53,12 +63,96 @@ public class ConnectionService implements INetworkDispatch { private NGECore core; private DatabaseConnection databaseConnection; private DatabaseConnection databaseConnection2; + + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - public ConnectionService(NGECore core) { + public ConnectionService(final NGECore core) { this.core = core; this.databaseConnection = core.getDatabase1(); this.databaseConnection2 = core.getDatabase2(); + + scheduler.scheduleAtFixedRate(new Runnable() { + + public void run() { + synchronized(core.getActiveConnectionsMap()) { + for(Client c : core.getActiveConnectionsMap().values()) { + if(c.getParent() != null) { + if ((System.currentTimeMillis() - c.getSession().getLastReadTime()) > 300000) { + disconnect(c.getSession()); + } + } + } + } + } + + public void disconnect(IoSession session) { + Client client = core.getClient((Integer) session.getAttribute("connectionId")); + + if(client == null) + return; + + if(client.getParent() == null) + return; + + CreatureObject object = (CreatureObject) client.getParent(); + object.setInviteCounter(0); + object.setInviteSenderId(0); + object.setInviteSenderName(""); + object.setClient(null); + PlayerObject ghost = (PlayerObject) object.getSlottedObject("ghost"); + + if(object.getGroupId() != 0) + core.groupService.handleGroupDisband(object); + + Point3D objectPos = object.getWorldPosition(); + + List collidables = core.simulationService.getCollidables(object.getPlanet(), objectPos.x, objectPos.z, 512); + + for(AbstractCollidable collidable : collidables) { + collidables.remove(object); + } + + + if (ghost != null) { + String objectShortName = object.getCustomName(); + + if (object.getCustomName().contains(" ")) { + String[] splitName = object.getCustomName().toLowerCase().split(" "); + objectShortName = splitName[0]; + } + + core.chatService.playerStatusChange(objectShortName, (byte) 0); + } + + session.suspendWrite(); + + boolean remove = core.simulationService.remove(object, object.getPosition().x, object.getPosition().z); + if(remove) + System.out.println("Successful quadtree remove"); + + //if(object.getContainer() == null) { + HashSet oldObservers = new HashSet(object.getObservers()); + for(Iterator it = oldObservers.iterator(); it.hasNext();) { + Client observerClient = it.next(); + if(observerClient.getParent() != null && !(observerClient.getSession() == session)) { + observerClient.getParent().makeUnaware(object); + } + } + //} else { + // object.getContainer().remove(object); + //} + + + object.createTransaction(core.getCreatureODB().getEnvironment()); + core.getCreatureODB().put(object, Long.class, CreatureObject.class, object.getTransaction()); + object.getTransaction().commitSync(); + core.objectService.destroyObject(object); + + core.getActiveConnectionsMap().remove((Integer) session.getAttribute("connectionId")); + } + + }, 15, 15, TimeUnit.MINUTES); } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index b671f380..2de96612 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -536,9 +536,17 @@ public class SimulationService implements INetworkDispatch { } - + /* + * Moved this to ConnectionService which will disconnect them + * from the server if they don't send packets for 5 minutes or more + * like on live. + * + * We had significant issues with client nulls due to us taking + * client disconnect requests too seriously. It has a weird tendency + * to bluff and send a disconnect packet when it's not disconnecting + * and continues sending packets. + */ public void handleDisconnect(IoSession session) { - Client client = core.getClient((Integer) session.getAttribute("connectionId")); if(client == null) @@ -554,55 +562,9 @@ public class SimulationService implements INetworkDispatch { object.setClient(null); PlayerObject ghost = (PlayerObject) object.getSlottedObject("ghost"); - if(object.getGroupId() != 0) - core.groupService.handleGroupDisband(object); - - Point3D objectPos = object.getWorldPosition(); - - List collidables = getCollidables(object.getPlanet(), objectPos.x, objectPos.z, 512); - - for(AbstractCollidable collidable : collidables) { - collidables.remove(object); - } - - - if (ghost != null) { - String objectShortName = object.getCustomName(); - - if (object.getCustomName().contains(" ")) { - String[] splitName = object.getCustomName().toLowerCase().split(" "); - objectShortName = splitName[0]; - } - - core.chatService.playerStatusChange(objectShortName, (byte) 0); - } - - session.suspendWrite(); - - boolean remove = remove(object, object.getPosition().x, object.getPosition().z); - if(remove) - System.out.println("Successful quadtree remove"); - - //if(object.getContainer() == null) { - HashSet oldObservers = new HashSet(object.getObservers()); - for(Iterator it = oldObservers.iterator(); it.hasNext();) { - Client observerClient = it.next(); - if(observerClient.getParent() != null && !(observerClient.getSession() == session)) { - observerClient.getParent().makeUnaware(object); - } - } - //} else { - // object.getContainer().remove(object); - //} - - object.createTransaction(core.getCreatureODB().getEnvironment()); core.getCreatureODB().put(object, Long.class, CreatureObject.class, object.getTransaction()); object.getTransaction().commitSync(); - core.objectService.destroyObject(object); - - core.getActiveConnectionsMap().remove((Integer) session.getAttribute("connectionId")); - } public void handleZoneIn(Client client) {