forked from SteamWar/SteamWar
Make Techhider more robust
This commit is contained in:
+15
-8
@@ -41,6 +41,7 @@ import org.bukkit.event.entity.EntityPickupItemEvent;
|
|||||||
import org.bukkit.event.player.*;
|
import org.bukkit.event.player.*;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ import java.util.Set;
|
|||||||
public class SpectatorListener implements Listener {
|
public class SpectatorListener implements Listener {
|
||||||
|
|
||||||
private static final TechHider techHider;
|
private static final TechHider techHider;
|
||||||
private static final Set<Player> NO_TECHHIDER = new HashSet<>();
|
private static final Set<Player> NO_TECHHIDER = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Set<Material> materials = new HashSet<>();
|
Set<Material> materials = new HashSet<>();
|
||||||
@@ -100,14 +101,14 @@ public class SpectatorListener implements Listener {
|
|||||||
materials.remove(Material.BARRIER);
|
materials.remove(Material.BARRIER);
|
||||||
materials.remove(Material.STONE);
|
materials.remove(Material.STONE);
|
||||||
techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> {
|
techHider = new TechHider((TechHider.LocationEvaluator) (player, i, i1) -> {
|
||||||
return Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player);
|
return NO_TECHHIDER.contains(player);
|
||||||
}, Material.END_STONE, materials, new HashSet<>());
|
}, Material.END_STONE, materials, new HashSet<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void enableOrDisableTechhider() {
|
private static void enableOrDisableTechhider() {
|
||||||
boolean enable = Bukkit.getOnlinePlayers()
|
boolean enable = Bukkit.getOnlinePlayers()
|
||||||
.stream()
|
.stream()
|
||||||
.anyMatch(player -> !(Permission.BUILD.hasPermission(player) || NO_TECHHIDER.contains(player)));
|
.anyMatch(player -> !NO_TECHHIDER.contains(player));
|
||||||
if (enable) {
|
if (enable) {
|
||||||
techHider.enable();
|
techHider.enable();
|
||||||
} else {
|
} else {
|
||||||
@@ -141,6 +142,9 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
if (Permission.BUILD.hasPermission(event.getPlayer())) {
|
||||||
|
NO_TECHHIDER.add(event.getPlayer());
|
||||||
|
}
|
||||||
enableOrDisableTechhider();
|
enableOrDisableTechhider();
|
||||||
if (BauSystem.DEV_SERVER) return;
|
if (BauSystem.DEV_SERVER) return;
|
||||||
if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) {
|
if (event.getPlayer().getUniqueId().equals(BauServer.getInstance().getOwner())) {
|
||||||
@@ -163,6 +167,14 @@ public class SpectatorListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
|
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);
|
||||||
|
});
|
||||||
enableOrDisableTechhider();
|
enableOrDisableTechhider();
|
||||||
if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) {
|
if (!anySupervisorOnline(null) && !BauSystem.DEV_SERVER) {
|
||||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||||
@@ -170,11 +182,6 @@ public class SpectatorListener implements Listener {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.getChanged().forEach(player -> {
|
|
||||||
NO_TECHHIDER.remove(player);
|
|
||||||
resendChunks(player);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import de.steamwar.core.CraftbukkitWrapper;
|
|||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.LinkedInstance;
|
import de.steamwar.linkage.LinkedInstance;
|
||||||
import de.steamwar.techhider.legacy.TechHider;
|
import de.steamwar.techhider.legacy.TechHider;
|
||||||
|
import io.papermc.paper.event.player.PlayerFailMoveEvent;
|
||||||
|
import io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason;
|
||||||
import net.md_5.bungee.api.ChatMessageType;
|
import net.md_5.bungee.api.ChatMessageType;
|
||||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
@@ -96,27 +98,12 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
@EventHandler
|
||||||
BiFunction<Player, ServerboundMovePlayerPacket, Object> positionSetter = (player, packet) -> {
|
public void onFailMove(PlayerFailMoveEvent event) {
|
||||||
Region region = Region.getRegion(player.getLocation());
|
if (event.getFailReason() != FailReason.CLIPPED_INTO_BLOCK) return;
|
||||||
if (hidden.containsKey(region) && hidden.get(region).contains(player)) {
|
Region region = Region.getRegion(event.getTo());
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
if (!hidden.containsKey(region) || !hidden.get(region).contains(event.getPlayer())) return;
|
||||||
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
event.setAllowed(true);
|
||||||
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
|
@EventHandler
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import org.bukkit.entity.Entity;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
@@ -65,9 +66,9 @@ public class Hull {
|
|||||||
private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block
|
private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block
|
||||||
private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
|
private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
|
||||||
|
|
||||||
private final HashSet<Player> players = new HashSet<>();
|
private final Set<Player> players = ConcurrentHashMap.newKeySet();
|
||||||
private final HashSet<Entity> entities = new HashSet<>();
|
private final Map<Integer, Entity> entities = new ConcurrentHashMap<>();
|
||||||
private final HashSet<REntity> rentities = new HashSet<>();
|
private final Set<REntity> rentities = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
public Hull(FightTeam team) {
|
public Hull(FightTeam team) {
|
||||||
this.region = team.getSchemRegion();
|
this.region = team.getSchemRegion();
|
||||||
@@ -98,9 +99,13 @@ public class Hull {
|
|||||||
return players.contains(player) && region.inRegion(location) && !visibility.get(new IntVector(location).toId(region));
|
return players.contains(player) && region.inRegion(location) && !visibility.get(new IntVector(location).toId(region));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEntityHidden(Player player, int entityId) {
|
||||||
|
return players.contains(player) && entities.containsKey(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
public void addPlayer(Player player) {
|
public void addPlayer(Player player) {
|
||||||
if (players.add(player)) {
|
if (players.add(player)) {
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities.values()) {
|
||||||
untrackEntity(player, entity);
|
untrackEntity(player, entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +113,7 @@ public class Hull {
|
|||||||
|
|
||||||
public void removePlayer(Player player, boolean activeRemoval) {
|
public void removePlayer(Player player, boolean activeRemoval) {
|
||||||
if (players.remove(player) && activeRemoval) {
|
if (players.remove(player) && activeRemoval) {
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities.values()) {
|
||||||
trackEntity(player, entity);
|
trackEntity(player, entity);
|
||||||
}
|
}
|
||||||
// techhider triggers block change sending
|
// techhider triggers block change sending
|
||||||
@@ -118,13 +123,13 @@ public class Hull {
|
|||||||
public void checkEntity(Entity entity) {
|
public void checkEntity(Entity entity) {
|
||||||
Location location = entity.getLocation();
|
Location location = entity.getLocation();
|
||||||
if (region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) {
|
if (region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) {
|
||||||
if (entities.add(entity)) {
|
if (entities.put(entity.getEntityId(), entity) == null) {
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
untrackEntity(player, entity);
|
untrackEntity(player, entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entities.remove(entity)) {
|
if (entities.remove(entity.getEntityId()) != null) {
|
||||||
for (Player player : players) {
|
for (Player player : players) {
|
||||||
trackEntity(player, entity);
|
trackEntity(player, entity);
|
||||||
}
|
}
|
||||||
@@ -149,7 +154,7 @@ public class Hull {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeEntity(Entity entity) {
|
public void removeEntity(Entity entity) {
|
||||||
entities.remove(entity);
|
entities.remove(entity.getEntityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkREntity(REntity entity) {
|
public void checkREntity(REntity entity) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
import org.bukkit.event.entity.EntityRemoveEvent;
|
||||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
@@ -131,6 +131,18 @@ public class HullHider implements Listener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEntityHidden(Player player, int entityId) {
|
||||||
|
if (!TechHiderWrapper.ENABLED) return false;
|
||||||
|
|
||||||
|
for (Hull hull : hulls) {
|
||||||
|
if (hull.isEntityHidden(player, entityId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onSpawn(EntitySpawnEvent e) {
|
public void onSpawn(EntitySpawnEvent e) {
|
||||||
for (Hull hull : hulls) {
|
for (Hull hull : hulls) {
|
||||||
@@ -151,7 +163,7 @@ public class HullHider implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||||
public void onDeath(EntityDeathEvent e) {
|
public void onDeath(EntityRemoveEvent e) {
|
||||||
for (Hull hull : hulls) {
|
for (Hull hull : hulls) {
|
||||||
hull.removeEntity(e.getEntity());
|
hull.removeEntity(e.getEntity());
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-12
@@ -42,7 +42,6 @@ import net.minecraft.world.level.material.FluidState;
|
|||||||
import net.minecraft.world.level.material.Fluids;
|
import net.minecraft.world.level.material.Fluids;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
|
||||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -103,29 +102,22 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block) {
|
public boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block) {
|
||||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
return !hiddenRegion.getOrDefault(p, Config.ArenaRegion).inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState) {
|
public boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState) {
|
||||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState);
|
return !hiddenRegion.getOrDefault(p, Config.ArenaRegion).inRegion(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO will require entity tracking on the netty thread to prevent future race conditions
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId) {
|
public boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId) {
|
||||||
net.minecraft.world.entity.Entity nmsEntity = ((CraftWorld) p.getWorld()).getHandle().moonrise$getEntityLookup().get(entityId);
|
return !hullHider.isEntityHidden(p, entityId);
|
||||||
|
|
||||||
if (nmsEntity != null) {
|
|
||||||
return !hullHider.isBlockHidden(p, nmsEntity.getBlockX(), nmsEntity.getBlockY(), nmsEntity.getBlockZ());
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type) {
|
public boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type) {
|
||||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blockEntityTypeToObfuscate.contains(type);
|
return !hiddenRegion.getOrDefault(p, Config.ArenaRegion).inRegion(blockX, blockY, blockZ) || !blockEntityTypeToObfuscate.contains(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ import net.minecraft.util.SimpleBitStorage;
|
|||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -45,10 +48,15 @@ public class ChunkHider {
|
|||||||
|
|
||||||
private final int blockIdUsedForHiding;
|
private final int blockIdUsedForHiding;
|
||||||
private final AccessPrivilegeProvider accessPrivilegeProvider;
|
private final AccessPrivilegeProvider accessPrivilegeProvider;
|
||||||
|
private final int worldMinHeight;
|
||||||
|
private final int worldMaxHeight;
|
||||||
|
|
||||||
public ChunkHider(Block blockUsedForObfuscation, AccessPrivilegeProvider accessPrivilegeProvider) {
|
public ChunkHider(Block blockUsedForObfuscation, AccessPrivilegeProvider accessPrivilegeProvider) {
|
||||||
blockIdUsedForHiding = Block.BLOCK_STATE_REGISTRY.getId(blockUsedForObfuscation.defaultBlockState());
|
blockIdUsedForHiding = Block.BLOCK_STATE_REGISTRY.getId(blockUsedForObfuscation.defaultBlockState());
|
||||||
this.accessPrivilegeProvider = accessPrivilegeProvider;
|
this.accessPrivilegeProvider = accessPrivilegeProvider;
|
||||||
|
World world = Bukkit.getWorlds().getFirst();
|
||||||
|
worldMinHeight = world.getMinHeight();
|
||||||
|
worldMaxHeight = world.getMaxHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getLongsRequiredToEncodeEntries(int bitsPerEntry, int entryCount) {
|
private int getLongsRequiredToEncodeEntries(int bitsPerEntry, int entryCount) {
|
||||||
@@ -77,9 +85,6 @@ public class ChunkHider {
|
|||||||
ByteBuf in = Unpooled.wrappedBuffer(chunkData.getReadBuffer());
|
ByteBuf in = Unpooled.wrappedBuffer(chunkData.getReadBuffer());
|
||||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
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) {
|
for (int yOffset = worldMinHeight; yOffset < worldMaxHeight; yOffset += SECTION_SPAN_SIZE) {
|
||||||
short blockCount = in.readShort();
|
short blockCount = in.readShort();
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ public class TechHider {
|
|||||||
// 7.1.3 Entity Animation: entity id based signal, keep blocked until entity visibility is modeled.
|
// 7.1.3 Entity Animation: entity id based signal, keep blocked until entity visibility is modeled.
|
||||||
processors.put(ClientboundAnimatePacket.class, this.buildEntityPacketProcessor(ClientboundAnimatePacket::getId));
|
processors.put(ClientboundAnimatePacket.class, this.buildEntityPacketProcessor(ClientboundAnimatePacket::getId));
|
||||||
// 7.1.35 Entity Event: entity id based signal.
|
// 7.1.35 Entity Event: entity id based signal.
|
||||||
processors.put(ClientboundEntityEventPacket.class, this.buildEntityPacketProcessor(ClientboundEntityEventPacket::getEventId));
|
processors.put(ClientboundEntityEventPacket.class, this.buildEntityPacketProcessor((ClientboundEntityEventPacket p) -> p.entityId));
|
||||||
// 7.1.36 Teleport Entity: entity id and absolute position.
|
// 7.1.36 Teleport Entity: entity id and absolute position.
|
||||||
processors.put(ClientboundTeleportEntityPacket.class, this.buildEntityPacketProcessor(ClientboundTeleportEntityPacket::id));
|
processors.put(ClientboundTeleportEntityPacket.class, this.buildEntityPacketProcessor(ClientboundTeleportEntityPacket::id));
|
||||||
// 7.1.42 Hurt Animation: entity id based signal.
|
// 7.1.42 Hurt Animation: entity id based signal.
|
||||||
|
|||||||
Reference in New Issue
Block a user