diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java index ae32e0c1..a046ad22 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/world/SpectatorListener.java @@ -108,7 +108,7 @@ public class SpectatorListener implements Listener { } public void addHidingRules(Player player, List rules) { - if (!(Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player))) { + if (!NO_TECHHIDER.contains(player)) { rules.add(SPECTATOR_RULE); } } @@ -138,6 +138,9 @@ public class SpectatorListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { + if (Permission.BUILD.hasPermission(event.getPlayer())) { + NO_TECHHIDER.add(event.getPlayer()); + } if (BauSystem.DEV_SERVER) return; if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) { return; @@ -159,17 +162,20 @@ public class SpectatorListener implements Listener { @EventHandler public void onBauMemberUpdate(BauMemberUpdateEvent event) { + event.getChanged().forEach(player -> { + if (Permission.BUILD.hasPermission(player)) { + NO_TECHHIDER.add(player); + } else { + NO_TECHHIDER.remove(player); + } + resendChunks(player); + }); if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) { Bukkit.getOnlinePlayers().forEach(player -> { player.kickPlayer(""); }); return; } - - event.getChanged().forEach(player -> { - NO_TECHHIDER.remove(player); - resendChunks(player); - }); } @EventHandler diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java index c8f01679..09001a89 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java @@ -19,7 +19,6 @@ package de.steamwar.bausystem.features.xray; -import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.features.hullhider.HullHiderCommand; import de.steamwar.bausystem.features.techhider.HidingRule; @@ -30,12 +29,10 @@ import de.steamwar.core.CraftbukkitWrapper; import de.steamwar.linkage.Linked; import de.steamwar.linkage.LinkedInstance; import de.steamwar.techhider.ObfuscationConfig; +import io.papermc.paper.event.player.PlayerFailMoveEvent; +import io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason; import net.md_5.bungee.api.ChatMessageType; -import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; -import net.minecraft.server.level.ServerPlayer; -import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -45,7 +42,6 @@ import org.bukkit.event.player.PlayerQuitEvent; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiFunction; @Linked public class XrayCommand extends SWCommand implements Listener { @@ -103,27 +99,12 @@ public class XrayCommand extends SWCommand implements Listener { }); } - { - BiFunction positionSetter = (player, packet) -> { - Region region = Region.getRegion(player.getLocation()); - if (hidden.containsKey(region) && hidden.get(region).contains(player)) { - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle(); - if (packet.hasPos) { - serverPlayer.setPosRaw(packet.x, packet.y, packet.z); - } - if (packet.hasRot) { - serverPlayer.setXRot(packet.xRot); - serverPlayer.setYRot(packet.yRot); - } - }, 0); - return null; - } - return packet; - }; - - TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, positionSetter); - TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, positionSetter); + @EventHandler + public void onFailMove(PlayerFailMoveEvent event) { + if (event.getFailReason() != FailReason.CLIPPED_INTO_BLOCK) return; + Region region = Region.getRegion(event.getTo()); + if (!hidden.containsKey(region) || !hidden.get(region).contains(event.getPlayer())) return; + event.setAllowed(true); } @EventHandler 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 fd961d96..ed56d1b9 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/FightHullHider.java @@ -132,6 +132,10 @@ public class FightHullHider { return hullHider.isBlockHidden(player, x, y, z); } + public boolean isEntityHidden(Player player, int entityId) { + return hullHider.isEntityHidden(player, entityId); + } + private void onTick() { Recording.iterateOverEntities(Objects::nonNull, hullHider::checkEntity); hullHider.sendUncoveredBlocks(); 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 534e7cee..58cd1a45 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -39,7 +39,6 @@ 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.GameMode; -import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -133,16 +132,9 @@ public class TechHiderWrapper extends StateDependent implements Listener { return !isHidden(blockX, blockY, blockZ) || !obfuscation.hidesBlockState(blockState); } - // TODO will require entity tracking on the netty thread to prevent future race conditions @Override public boolean canAccessEntity(int entityId) { - net.minecraft.world.entity.Entity nmsEntity = ((CraftWorld) player.getWorld()).getHandle().moonrise$getEntityLookup().get(entityId); - - if (nmsEntity != null) { - return !hullHider.isBlockHidden(player, nmsEntity.getBlockX(), nmsEntity.getBlockY(), nmsEntity.getBlockZ()); - } else { - return true; - } + return !hullHider.isEntityHidden(player, entityId); } @Override diff --git a/HiderCore/src/de/steamwar/hullhider/Hull.java b/HiderCore/src/de/steamwar/hullhider/Hull.java index 02f8c56c..a05765f9 100644 --- a/HiderCore/src/de/steamwar/hullhider/Hull.java +++ b/HiderCore/src/de/steamwar/hullhider/Hull.java @@ -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 uncoveredSurface = new HashSet<>(); private final Viewers viewers; - private final HashSet entities = new HashSet<>(); - private final HashSet rentities = new HashSet<>(); + // Concurrent as it is read on netty threads, keyed by entity id + private final Map entities = new ConcurrentHashMap<>(); + private final Set 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); } } diff --git a/HiderCore/src/de/steamwar/hullhider/HullHider.java b/HiderCore/src/de/steamwar/hullhider/HullHider.java index c2a5d1b7..3793fd0e 100644 --- a/HiderCore/src/de/steamwar/hullhider/HullHider.java +++ b/HiderCore/src/de/steamwar/hullhider/HullHider.java @@ -146,6 +146,16 @@ public class HullHider 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) { diff --git a/HiderCore/src/de/steamwar/techhider/ChunkHider.java b/HiderCore/src/de/steamwar/techhider/ChunkHider.java index ab4eb45e..77bd672b 100644 --- a/HiderCore/src/de/steamwar/techhider/ChunkHider.java +++ b/HiderCore/src/de/steamwar/techhider/ChunkHider.java @@ -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();