Make Techhider more robust

This commit is contained in:
2026-11-04 21:11:45 +01:00
parent a5bfc2fa44
commit 1eef62add3
7 changed files with 60 additions and 55 deletions
+14 -8
View File
@@ -53,6 +53,7 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.logging.Level;
@@ -81,8 +82,9 @@ public class Hull {
private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
private final Viewers viewers;
private final HashSet<Entity> entities = new HashSet<>();
private final HashSet<REntity> rentities = new HashSet<>();
// Concurrent as it is read on netty threads, keyed by entity id
private final Map<Integer, Entity> entities = new ConcurrentHashMap<>();
private final Set<REntity> rentities = ConcurrentHashMap.newKeySet();
/**
* @param groundVisible whether the bottom layer of the region is uncovered (if the region does not reach the ground)
@@ -162,6 +164,10 @@ public class Hull {
return region.contains(x, y, z) && !isViewer(player) && !visibility.get(region.toIndex(x, y, z));
}
public boolean isEntityHidden(Player player, int entityId) {
return player.getEntityId() != entityId && entities.containsKey(entityId) && !isViewer(player);
}
public boolean isViewer(Player player) {
return player != null && viewers.isViewer(player);
}
@@ -187,13 +193,13 @@ public class Hull {
private void updateEntities(Player player, boolean wasViewer) {
if (isViewer(player)) {
if (!wasViewer) {
for (Entity entity : entities) {
for (Entity entity : entities.values()) {
trackEntity(player, entity);
}
}
} else {
// Also hides the entities from players that joined after they were hidden
for (Entity entity : entities) {
for (Entity entity : entities.values()) {
if (!player.equals(entity)) untrackEntity(player, entity);
}
}
@@ -210,13 +216,13 @@ public class Hull {
public void checkEntity(Entity entity) {
Location location = entity.getLocation();
if (region.contains(location) && !visibility.get(new IntVector(location).toId(region))) {
if (entities.add(entity)) {
if (entities.put(entity.getEntityId(), entity) == null) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (!isViewer(player) && !player.equals(entity)) untrackEntity(player, entity);
}
}
} else {
if (entities.remove(entity)) {
if (entities.remove(entity.getEntityId()) != null) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (!isViewer(player) && !player.equals(entity)) trackEntity(player, entity);
}
@@ -241,7 +247,7 @@ public class Hull {
}
public void removeEntity(Entity entity) {
entities.remove(entity);
entities.remove(entity.getEntityId());
}
public void checkREntity(REntity entity) {
@@ -264,7 +270,7 @@ public class Hull {
for (Player player : Bukkit.getOnlinePlayers()) {
if (isViewer(player)) continue;
for (Entity entity : entities) {
for (Entity entity : entities.values()) {
if (!player.equals(entity)) trackEntity(player, entity);
}
}
@@ -146,6 +146,16 @@ public class HullHider<K> implements Listener {
return false;
}
public boolean isEntityHidden(Player player, int entityId) {
for (Hull hull : hulls) {
if (hull.isEntityHidden(player, entityId)) {
return true;
}
}
return false;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPhysic(BlockPhysicsEvent e) {
if (e.getBlock() == e.getSourceBlock() || e.getChangedType() == Material.AIR) {
@@ -30,7 +30,8 @@ import net.minecraft.util.SimpleBitStorage;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.Arrays;
@@ -48,6 +49,15 @@ public class ChunkHider {
private final int BLOCKS_PER_SECTION = 4096;
private final int BIOMES_PER_SECTION = 64;
private final int worldMinHeight;
private final int worldMaxHeight;
public ChunkHider() {
World world = Bukkit.getWorlds().getFirst();
worldMinHeight = world.getMinHeight();
worldMaxHeight = world.getMaxHeight();
}
private int getLongsRequiredToEncodeEntries(int bitsPerEntry, int entryCount) {
int entriesPerLong = Long.SIZE / bitsPerEntry;
int dataLengthAsLongCount = (entryCount + entriesPerLong - 1) / entriesPerLong;
@@ -67,7 +77,6 @@ public class ChunkHider {
}
public ClientboundLevelChunkWithLightPacket processLevelChunkWithLightPacket(ForPlayer access, ClientboundLevelChunkWithLightPacket packet) {
Player player = access.getPlayer();
int chunkX = packet.getX();
int chunkZ = packet.getZ();
ClientboundLevelChunkPacketData chunkData = packet.getChunkData();
@@ -75,9 +84,6 @@ public class ChunkHider {
ByteBuf in = Unpooled.wrappedBuffer(chunkData.getReadBuffer());
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
int worldMinHeight = player.getWorld().getMinHeight();
int worldMaxHeight = player.getWorld().getMaxHeight();
for (int yOffset = worldMinHeight; yOffset < worldMaxHeight; yOffset += SECTION_SPAN_SIZE) {
short blockCount = in.readShort();