Skip to content

Commit

Permalink
fix: fix a rare NPE exception that may occur if player disconnect whe…
Browse files Browse the repository at this point in the history
…n joining the server.
  • Loading branch information
smartcmd committed Jan 23, 2025
1 parent 1cd6c4d commit ba1fb19
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ 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

- Plugins are able to create their own world generator implementation now. In previous versions a ClassCastException would be thrown when
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

Expand Down
12 changes: 9 additions & 3 deletions server/src/main/java/org/allaymc/server/AllayServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit ba1fb19

Please sign in to comment.