diff --git a/CHANGELOG.md b/CHANGELOG.md index e0a4a2626..00f3902d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ Unless otherwise specified, any version comparison below is the comparison of se - Main thread will sleep a short time if gui is enabled when the server exits abnormally. This gives user time to see what goes wrong. - Server won't crash if failed to load the descriptor of a plugin now. An error message will be print to the console instead. - Server won't crash if failed to create world generator. Void world generator will be used instead. +- It is not allowed to reset the dimension of player back to null now, and doing such thing will result in an exception. ### Fixed @@ -42,6 +43,7 @@ Unless otherwise specified, any version comparison below is the comparison of se initializing the dimension. - Explosion now calculates entity exposure correctly. In previous version any non-air block will block the explosion ray. - Explosion damage now scales with game difficulty, and a bug was fixed that cause the damage two times bigger than the correct damage. +- Fixed a rare NPE exception that may occur if player disconnect when joining the server. ### Removed diff --git a/server/src/main/java/org/allaymc/server/AllayServer.java b/server/src/main/java/org/allaymc/server/AllayServer.java index 666b35f6e..f0d2198cf 100644 --- a/server/src/main/java/org/allaymc/server/AllayServer.java +++ b/server/src/main/java/org/allaymc/server/AllayServer.java @@ -300,9 +300,15 @@ public void onDisconnect(EntityPlayer player) { // the server without waiting for the status change to IN_GAME, which is why the session remains and the // server thinks that the player is still on the server, but after such manipulations, the player client // will crash every time he logs on to the server - player.getDimension().removePlayer(player); - playerStorage.savePlayerData(player); - removeFromPlayerList(player); + if (player.getDimension() != null) { + // The dimension of the player may be null, that because the client is still handling resource packs + // and is not added or going to be added (willBeSpawnedNextTick == true) to any dimension. After handled + // resources packs, the dimension of the player should always be non-null regardless the status of the + // player because there is a check in EntityPlayerBaseComponentImpl#setLocationBeforeSpawn() + player.getDimension().removePlayer(player); + playerStorage.savePlayerData(player); + removeFromPlayerList(player); + } } ((AllayNetworkInterface) networkInterface).setPlayerCount(players.size()); diff --git a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java index 6e44d5b3a..532dd9e0a 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/EntityBaseComponentImpl.java @@ -290,6 +290,7 @@ protected void setLocation(Location3fc location, boolean calculateFallDistance) if (MathUtils.hasNaN(location)) { throw new IllegalArgumentException("Trying to set the location of entity " + runtimeId + " to a new location which contains NaN: " + location); } + if (calculateFallDistance && !this.onGround) { if (this.fallDistance < 0) { // Entity start falling diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java index 897ca3c6c..89190d003 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerBaseComponentImpl.java @@ -941,6 +941,16 @@ public void setMotion(Vector3fc motion) { networkComponent.sendPacket(packet); } + @Override + public void setLocationBeforeSpawn(Location3fc location) { + if (this.location.dimension() != null && location.dimension() == null) { + // Different from normal entity, reset the dimension of player entity back to null is not allowed + throw new IllegalArgumentException("Reset dimension back to null is not allowed for player!"); + } + + super.setLocationBeforeSpawn(location); + } + @Override public void sendMetadata() { super.sendMetadata(); diff --git a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java index e1bcd52a8..c571ad065 100644 --- a/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java +++ b/server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerNetworkComponentImpl.java @@ -220,7 +220,8 @@ protected void onFullyJoin() { world.getWorldData().sendTimeOfDay(thisPlayer); ((AllayWorld) world).sendWeather(thisPlayer); - // Save player data the first time + + // Save player data the first time it joins server.getPlayerStorage().savePlayerData(thisPlayer); }