diff --git a/Server/src/main/java/core/game/node/entity/player/Player.java b/Server/src/main/java/core/game/node/entity/player/Player.java index e2abd8bd8..88d88d352 100644 --- a/Server/src/main/java/core/game/node/entity/player/Player.java +++ b/Server/src/main/java/core/game/node/entity/player/Player.java @@ -350,7 +350,6 @@ public class Player extends Entity { if (!artificial) { getProperties().setSpawnLocation(ServerConstants.HOME_LOCATION); getDetails().getSession().setObject(this); - getDetails().getSession().setLastPing(System.currentTimeMillis() + 10_000L); } super.init(); LoginConfiguration.configureLobby(this); @@ -474,10 +473,6 @@ public class Player extends Entity { getAudioManager().send(2607); } } - if (!artificial && (System.currentTimeMillis() - getSession().getLastPing()) > 20_000L) { - details.getSession().disconnect(); - getSession().setLastPing(Long.MAX_VALUE); - } if(getAttribute("infinite-special", false)) { settings.setSpecialEnergy(100); } diff --git a/Server/src/main/java/core/game/node/entity/player/info/PlayerDetails.java b/Server/src/main/java/core/game/node/entity/player/info/PlayerDetails.java index 8924a1a08..2221223d4 100644 --- a/Server/src/main/java/core/game/node/entity/player/info/PlayerDetails.java +++ b/Server/src/main/java/core/game/node/entity/player/info/PlayerDetails.java @@ -40,6 +40,8 @@ public class PlayerDetails { */ private IoSession session; + public boolean saveParsed = false; + /** * Constructs a new {@code PlayerDetails}. * @param username the username to set. @@ -253,6 +255,7 @@ public class PlayerDetails { } public void save() { + if(!saveParsed) return; if(isBanned()) return; try { accountInfo.setContacts(communicationInfo.getContactString()); diff --git a/Server/src/main/java/core/game/node/entity/skill/hunter/HunterManager.java b/Server/src/main/java/core/game/node/entity/skill/hunter/HunterManager.java index a30f87f3c..357ac6423 100644 --- a/Server/src/main/java/core/game/node/entity/skill/hunter/HunterManager.java +++ b/Server/src/main/java/core/game/node/entity/skill/hunter/HunterManager.java @@ -54,6 +54,7 @@ public final class HunterManager implements LoginListener, LogoutListener, Event @Override public void logout(@NotNull Player player) { HunterManager instance = getInstance(player); + if (instance == null) return; Iterator iterator = instance.traps.iterator(); TrapWrapper wrapper = null; while (iterator.hasNext()) { diff --git a/Server/src/main/java/core/net/IoEventHandler.java b/Server/src/main/java/core/net/IoEventHandler.java index 93adb6918..dfcd684db 100644 --- a/Server/src/main/java/core/net/IoEventHandler.java +++ b/Server/src/main/java/core/net/IoEventHandler.java @@ -61,12 +61,19 @@ public class IoEventHandler { ReadableByteChannel channel = (ReadableByteChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(100_000); IoSession session = (IoSession) key.attachment(); - if (channel.read(buffer) == -1) { - if(session != null && session.getPlayer() != null){ - Repository.getDisconnectionQueue().add(session.getPlayer()); + try { + if (channel.read(buffer) == -1) { + if (session != null && session.getPlayer() != null) { + Repository.getDisconnectionQueue().add(session.getPlayer()); + } + key.cancel(); + return; } - key.cancel(); - return; + } catch (IOException e) { + if (e.getMessage().contains("reset by peer")) { + session.disconnect(); + session.getPlayer().clear(true); + } else e.printStackTrace(); } buffer.flip(); if (session == null) { diff --git a/Server/src/main/java/core/net/IoSession.java b/Server/src/main/java/core/net/IoSession.java index 1f2e74078..61c2e2f3c 100644 --- a/Server/src/main/java/core/net/IoSession.java +++ b/Server/src/main/java/core/net/IoSession.java @@ -9,6 +9,7 @@ import rs09.auth.AuthResponse; import rs09.game.world.GameWorld; import core.net.producer.HSEventProducer; import core.net.producer.LoginEventProducer; +import rs09.game.world.repository.Repository; import java.io.IOException; import java.nio.ByteBuffer; @@ -114,6 +115,8 @@ public class IoSession { */ private ClientInfo clientInfo; + public String associatedUsername; + /** * Constructs a new {@code IoSession}. * @param key The selection key. @@ -329,6 +332,9 @@ public class IoSession { * @return The player. */ public Player getPlayer() { + if (object == null) { + object = Repository.getPlayerByName(associatedUsername); + } return object instanceof Player ? ((Player) object) : null; } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/LoginParser.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/LoginParser.kt index 58e1d9201..f44e68f5b 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/LoginParser.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/LoginParser.kt @@ -25,6 +25,9 @@ import java.util.function.Consumer * Parses the login of a player. */ class LoginParser(val details: PlayerDetails, private val type: LoginType) { + companion object { + var monkeywrench = true + } /** * The player in the game, used for reconnect login type. */ @@ -39,10 +42,6 @@ class LoginParser(val details: PlayerDetails, private val type: LoginType) { */ fun initialize(player: Player, reconnect: Boolean) { if(!validateRequest()) return - if (reconnect) { - reconnect(player) - return - } lateinit var parser: PlayerSaveParser try { parser = PlayerParser.parse(player) @@ -65,8 +64,12 @@ class LoginParser(val details: PlayerDetails, private val type: LoginType) { loginListeners.forEach(Consumer { listener: LoginListener -> listener.login(player) }) //Run our login hooks parser.runContentHooks() //Run our saved-content-parsing hooks player.details.session.setObject(player) - flag(AuthResponse.Success) - player.init() + if (reconnect) { + reconnect(player) + } else { + flag(AuthResponse.Success) + player.init() + } player.monitor.log(player.details.ipAddress, PlayerMonitor.ADDRESS_LOG) player.monitor.log(player.details.serial, PlayerMonitor.ADDRESS_LOG) player.monitor.log(player.details.macAddress, PlayerMonitor.ADDRESS_LOG) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt index 55474e959..2af90200e 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaveParser.kt @@ -86,6 +86,7 @@ class PlayerSaveParser(val player: Player) { { if(read) contentHooks.forEach{it.parsePlayer(player, saveFile!!)} + player.details.saveParsed = true } fun parseVarps(){ diff --git a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt index cd75513c6..f7d9175fb 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/player/info/login/PlayerSaver.kt @@ -61,6 +61,7 @@ class PlayerSaver (val player: Player){ return saveFile } fun save() = runBlocking { + if (!player.details.saveParsed) return@runBlocking val manager = ScriptEngineManager() val scriptEngine = manager.getEngineByName("JavaScript") scriptEngine.put("jsonString", populate().toJSONString()) diff --git a/Server/src/main/kotlin/rs09/game/world/repository/Repository.kt b/Server/src/main/kotlin/rs09/game/world/repository/Repository.kt index 085bc4271..4e9cc7d6d 100644 --- a/Server/src/main/kotlin/rs09/game/world/repository/Repository.kt +++ b/Server/src/main/kotlin/rs09/game/world/repository/Repository.kt @@ -7,6 +7,7 @@ import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.repository.NodeList import rs09.ServerConstants +import rs09.game.world.update.UpdateSequence import java.util.* import java.util.concurrent.CopyOnWriteArrayList @@ -146,6 +147,7 @@ object Repository { players.remove(player) uid_map.remove(player.details.usernameHashcode) playerNames.remove(player.name) + UpdateSequence.renderablePlayers.remove(player) } /** diff --git a/Server/src/main/kotlin/rs09/net/event/LoginReadEvent.kt b/Server/src/main/kotlin/rs09/net/event/LoginReadEvent.kt index dee6dc961..92bc47236 100644 --- a/Server/src/main/kotlin/rs09/net/event/LoginReadEvent.kt +++ b/Server/src/main/kotlin/rs09/net/event/LoginReadEvent.kt @@ -33,6 +33,7 @@ class LoginReadEvent(session: IoSession?, buffer: ByteBuffer?) : IoReadEvent(ses details.communication.parse(accountInfo) session.clientInfo = ClientInfo(info.displayMode, info.windowMode, info.screenWidth, info.screenHeight) session.isaacPair = info.isaacPair + session.associatedUsername = info.username Login.proceedWith(session, details, info.opcode) } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/net/packet/in/Login.kt b/Server/src/main/kotlin/rs09/net/packet/in/Login.kt index 5641fec32..7c49b3778 100644 --- a/Server/src/main/kotlin/rs09/net/packet/in/Login.kt +++ b/Server/src/main/kotlin/rs09/net/packet/in/Login.kt @@ -121,11 +121,19 @@ object Login { details.session = session details.info.translate(UIDInfo(details.ipAddress, "DEPRECATED", "DEPRECATED", "DEPRECATED")) val player = Player(details) - if (!Repository.players.contains(player)) { + if (Repository.getPlayerByName(player.name) == null) { Repository.addPlayer(player) } - LoginParser(details, LoginType.fromType(opcode)).initialize(player, opcode == RECONNECT_LOGIN_OP) - sendMSEvents(details) + session.lastPing = System.currentTimeMillis() + try { + LoginParser(details, LoginType.fromType(opcode)).initialize(player, opcode == RECONNECT_LOGIN_OP) + sendMSEvents(details) + } catch (e: Exception) { + e.printStackTrace() + session.disconnect() + Repository.removePlayer(player) + player.clear(true) + } } private fun sendMSEvents(details: PlayerDetails) { diff --git a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt index 95f808039..1e82f3395 100644 --- a/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt +++ b/Server/src/main/kotlin/rs09/worker/MajorUpdateWorker.kt @@ -1,15 +1,8 @@ package rs09.worker import api.submitWorldPulse -import core.game.system.SystemManager -import core.game.system.SystemState import core.game.system.task.Pulse import core.plugin.CorePluginTypes.Managers -import gui.GuiEvent -import gui.ServerMonitor -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import rs09.Server import rs09.ServerConstants import rs09.ServerStore @@ -18,13 +11,10 @@ import rs09.game.system.SystemLogger import rs09.game.world.GameWorld import rs09.game.world.repository.Repository import rs09.game.world.update.UpdateSequence -import rs09.net.packet.PacketWriteQueue import rs09.tools.stringtools.colorize import java.lang.Long.max -import java.lang.Long.min import java.text.SimpleDateFormat import java.util.* -import kotlin.collections.ArrayList import kotlin.system.exitProcess /** @@ -46,6 +36,15 @@ class MajorUpdateWorker { handleTickActions() + for (player in Repository.players.filter {!it.isArtificial}) { + if (System.currentTimeMillis() - player.session.lastPing > 20000L) { + player?.details?.session?.disconnect() + player?.session?.lastPing = Long.MAX_VALUE + player?.clear(true) + Repository.removePlayer(player) + } + } + //Handle daily restart if enabled if(sdf.format(Date()).toInt() == 0){