From d1fb4ca67ea81c2f312cf4bafb1f14c734e87be7 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sat, 31 Oct 2026 15:09:04 +0100 Subject: [PATCH] Allow removing hulls and resend their chunks HullHider#removeHull stops hiding a hull: it shows the entities and REntities the hull hid and resends its chunks to everybody who could not view it. A hull is enabled again by adding and initialising it. Hull#resendChunks only resends chunks the player has loaded. HullHider now resends the chunks to non-viewers after initialising a hull itself, so FightHullHider no longer does it. --- .../fightsystem/utils/FightHullHider.java | 9 ----- HiderCore/src/de/steamwar/hullhider/Hull.java | 34 +++++++++++++++++ .../src/de/steamwar/hullhider/HullHider.java | 37 ++++++++++++++++++- .../src/de/steamwar/hullhider/HullRegion.java | 12 ++++++ 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java index 4175655b..6c1d9d1b 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java @@ -32,7 +32,6 @@ import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.fightsystem.states.StateDependentTask; import de.steamwar.hullhider.Hull; import de.steamwar.hullhider.HullHider; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; @@ -68,14 +67,6 @@ public class FightHullHider { public void initialize(FightTeam team) { if (!TechHiderWrapper.ENABLED) return; hullHider.initialize(team); - - // Chunks encoded while the hull was filled as hidden contain obfuscated blocks that are visible now, but no block update is generated for them - Hull hull = hullHider.getHull(team); - for (Player player : Bukkit.getOnlinePlayers()) { - if (!hull.isViewer(player)) { - FightSystem.getTechHider().reloadChunks(player, team.getExtendRegion(), Region.EMPTY); - } - } } public void fill(FightTeam team, boolean visible) { diff --git a/HiderCore/src/de/steamwar/hullhider/Hull.java b/HiderCore/src/de/steamwar/hullhider/Hull.java index 7344af14..04826401 100644 --- a/HiderCore/src/de/steamwar/hullhider/Hull.java +++ b/HiderCore/src/de/steamwar/hullhider/Hull.java @@ -21,6 +21,7 @@ package de.steamwar.hullhider; import com.comphenix.tinyprotocol.TinyProtocol; import com.mojang.authlib.GameProfile; +import de.steamwar.core.CraftbukkitWrapper; import de.steamwar.core.ProtocolWrapper; import de.steamwar.entity.REntity; import it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap; @@ -32,6 +33,7 @@ import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -180,6 +182,38 @@ public class Hull { rentities.remove(entity); } + /** + * Shows all entities hidden by this hull again, used when the hull is removed. + */ + public void reveal() { + for (Player player : Bukkit.getOnlinePlayers()) { + if (isViewer(player)) continue; + + for (Entity entity : entities) { + if (!player.equals(entity)) trackEntity(player, entity); + } + } + entities.clear(); + + for (REntity entity : rentities) { + entity.hide(false); + } + rentities.clear(); + } + + /** + * Resends the chunks of this hull the player has loaded, so they are encoded with the current visibility. + */ + public void resendChunks(Player player) { + if (player.getWorld() != world) return; + + region.forEachChunk((chunkX, chunkZ) -> { + if (player.isChunkSent(Chunk.getChunkKey(chunkX, chunkZ))) { + CraftbukkitWrapper.sendChunk(player, chunkX, chunkZ); + } + }); + } + public void fill(boolean visible) { visibility.set(0, visibility.size(), visible); occluding.set(0, occluding.size(), !visible); diff --git a/HiderCore/src/de/steamwar/hullhider/HullHider.java b/HiderCore/src/de/steamwar/hullhider/HullHider.java index 9bbc846f..fd37baa8 100644 --- a/HiderCore/src/de/steamwar/hullhider/HullHider.java +++ b/HiderCore/src/de/steamwar/hullhider/HullHider.java @@ -20,6 +20,7 @@ package de.steamwar.hullhider; import de.steamwar.entity.REntity; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Entity; @@ -45,11 +46,30 @@ public class HullHider implements Listener { // Read on netty threads, replaced on every change private volatile Hull[] hulls = new Hull[0]; + /** + * The hull hides everything from non-viewers until it is initialised. + */ public void addHull(K key, Hull hull) { hullMap.put(key, hull); hulls = hullMap.values().toArray(new Hull[0]); } + /** + * Stops hiding the hull: shows the entities it hid and resends its chunks to everybody who could not view it. + */ + public void removeHull(K key) { + Hull hull = hullMap.remove(key); + if (hull == null) return; + hulls = hullMap.values().toArray(new Hull[0]); + + hull.reveal(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (!hull.isViewer(player)) { + hull.resendChunks(player); + } + } + } + public Hull getHull(K key) { return hullMap.get(key); } @@ -59,7 +79,22 @@ public class HullHider implements Listener { } public void initialize(K key) { - hullMap.get(key).initialize(); + Hull hull = hullMap.get(key); + hull.initialize(); + + // Chunks encoded while the hull was filled as hidden contain obfuscated blocks that are visible now, but no block update is generated for them + for (Player player : Bukkit.getOnlinePlayers()) { + if (!hull.isViewer(player)) { + hull.resendChunks(player); + } + } + } + + /** + * Has to be called after the player became a viewer of the hull or stopped being one. + */ + public void resendChunks(Player player, K key) { + hullMap.get(key).resendChunks(player); } public void fill(K key, boolean visible) { diff --git a/HiderCore/src/de/steamwar/hullhider/HullRegion.java b/HiderCore/src/de/steamwar/hullhider/HullRegion.java index 0006a2af..7b5d30ab 100644 --- a/HiderCore/src/de/steamwar/hullhider/HullRegion.java +++ b/HiderCore/src/de/steamwar/hullhider/HullRegion.java @@ -90,10 +90,22 @@ public final class HullRegion { } } + public void forEachChunk(ChunkConsumer executor) { + for (int chunkX = minX >> 4; chunkX <= (maxX - 1) >> 4; chunkX++) { + for (int chunkZ = minZ >> 4; chunkZ <= (maxZ - 1) >> 4; chunkZ++) { + executor.accept(chunkX, chunkZ); + } + } + } + public interface BlockConsumer { void accept(int x, int y, int z); } + public interface ChunkConsumer { + void accept(int chunkX, int chunkZ); + } + @Override public String toString() { return minX + "," + minY + "," + minZ + "->" + maxX + "," + maxY + "," + maxZ;