From 8381cacdf8ec3d09d025cd39bd6f63189361d71d Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Tue, 27 Oct 2026 09:28:05 +0100 Subject: [PATCH] Avoid NPE race when computing the TechHider hidden region getHiddenRegion looked the player up in FightTeam.players twice (team, then FightPlayer) on netty threads. A concurrent reset or removePlayer made the second lookup return null, the NPE was swallowed by the global filter and the packet was dropped. Resolve the FightPlayer once and derive team and canEntern from it. --- .../steamwar/fightsystem/utils/TechHiderWrapper.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index 7c4c9d77..e614cda7 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -25,6 +25,7 @@ import de.steamwar.fightsystem.events.BoardingEvent; import de.steamwar.fightsystem.events.TeamLeaveEvent; import de.steamwar.fightsystem.events.TeamSpawnEvent; import de.steamwar.fightsystem.fight.Fight; +import de.steamwar.fightsystem.fight.FightPlayer; import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependent; @@ -178,12 +179,13 @@ public class TechHiderWrapper extends StateDependent implements Listener { private Region getHiddenRegion(Player player) { if (Config.isReferee(player)) return Region.EMPTY; - FightTeam team = Fight.getPlayerTeam(player); - if (team == null) return Config.ArenaRegion; + // Single lookup: runs on netty threads, the player can leave the team at any time + FightPlayer fightPlayer = Fight.getFightPlayer(player); + if (fightPlayer == null) return Config.ArenaRegion; - if (team.canPlayerEntern(player)) return Region.EMPTY; + if (fightPlayer.canEntern()) return Region.EMPTY; - return Fight.getOpposite(team).getExtendRegion(); + return Fight.getOpposite(fightPlayer.getTeam()).getExtendRegion(); } private Stream getWaterloggedBlockStates() {