From 5fab7e540422059a2c13e9698115f50e2997de02 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 17 Dec 2023 16:18:20 +0100 Subject: [PATCH] Untested entity 1.18+ hullhiding Signed-off-by: Lixfel --- .../src/de/steamwar/fightsystem/Config.java | 4 +- .../steamwar/fightsystem/fight/FightTeam.java | 2 + .../fightsystem/listener/ArrowStopper.java | 2 +- .../fightsystem/record/PacketProcessor.java | 2 +- .../de/steamwar/fightsystem/utils/Hull.java | 325 ++++++++++++++++++ .../steamwar/fightsystem/utils/HullHider.java | 298 +++++----------- .../fightsystem/utils/TechHiderWrapper.java | 3 +- 7 files changed, 410 insertions(+), 226 deletions(-) create mode 100644 FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/Config.java b/FightSystem_Core/src/de/steamwar/fightsystem/Config.java index 331491f..b1030f7 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/Config.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/Config.java @@ -120,7 +120,7 @@ public class Config { //tech hider parameter public static final boolean TechhiderActive; - public static final Set HiddenBlocks; + public static final Set HiddenBlocks; public static final Set HiddenBlockEntities; public static final String ObfuscateWith; @@ -214,7 +214,7 @@ public class Config { TechhiderActive = config.getBoolean("Techhider.Active", false); ObfuscateWith = config.getString("Techhider.ObfuscateWith", "end_stone").toUpperCase(); - HiddenBlocks = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlocks"))); + HiddenBlocks = config.getStringList("Techhider.HiddenBlocks").stream().map(String::toUpperCase).map(Material::getMaterial).collect(Collectors.toSet()); HiddenBlockEntities = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlockEntities"))); if(schemsizeX < 0){ diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java b/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java index 54cad8e..6efb3fd 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/fight/FightTeam.java @@ -275,6 +275,7 @@ public class FightTeam { BountifulWrapper.impl.setAttackSpeed(player); player.setFoodLevel(20); player.getInventory().clear(); + FightSystem.getHullHider().removePlayer(this, player); if(FightState.Spectate.contains(FightState.getFightState())) { Fight.setPlayerGamemode(player, GameMode.SPECTATOR); @@ -318,6 +319,7 @@ public class FightTeam { player.getInventory().clear(); if(player.isOnline()){ + FightSystem.getHullHider().addPlayer(this, player); FightSystem.getTechHider().reloadChunks(player, chunksToReload, true); if(ArenaMode.VariableTeams.contains(Config.mode)) diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/listener/ArrowStopper.java b/FightSystem_Core/src/de/steamwar/fightsystem/listener/ArrowStopper.java index e7b4d01..3fd7f7d 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/listener/ArrowStopper.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/listener/ArrowStopper.java @@ -85,7 +85,7 @@ public class ArrowStopper { } private boolean checkBlock(Block block) { - return Config.HiddenBlocks.contains(block.getType().name().toLowerCase()); + return Config.HiddenBlocks.contains(block.getType()); } private boolean invalidEntity(Projectile entity) { diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java index d7c31fd..f50007a 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java @@ -88,7 +88,7 @@ public class PacketProcessor implements Listener { private final PacketSource source; private final BukkitTask task; private final LinkedList syncList = new LinkedList<>(); - private final Set hiddenBlockIds = Config.HiddenBlocks.stream().map(String::toUpperCase).map(Material::getMaterial).flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet()); + private final Set hiddenBlockIds = Config.HiddenBlocks.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet()); private final int obfuscateWith = BlockIds.impl.materialToId(Material.getMaterial(Config.ObfuscateWith.toUpperCase())); private final FreezeWorld freezer = new FreezeWorld(); private final REntityServer entityServer = new REntityServer(); diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java new file mode 100644 index 0000000..904c0cd --- /dev/null +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java @@ -0,0 +1,325 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.utils; + +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.FightSystem; +import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.techhider.BlockIds; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.logging.Level; + +public class Hull { + + private static boolean isOccluding(Material material) { + return material.isOccluding() || Config.HiddenBlocks.contains(material); + } + + private final Region region; + private final boolean groundVisible; + + private final BitSet occluding; + private final BitSet visibility; + private final Map> blockVisibility = new HashMap<>(); + + private final Set players = new HashSet<>(); + private final Set entities = new HashSet<>(); + + public Hull(FightTeam team) { + this.region = team.getSchemRegion(); + this.groundVisible = region.getMinY() != Config.PlayerRegion.getMinY(); + this.occluding = new BitSet(region.volume()); + this.visibility = new BitSet(region.volume()); + + IntVector[] directions; + if (groundVisible) { + directions = new IntVector[]{ + new IntVector(1, 0, 0), + new IntVector(-1, 0, 0), + new IntVector(0, 1, 0), + new IntVector(0, -1, 0), + new IntVector(0, 0, 1), + new IntVector(0, 0, -1) + }; + } else { + directions = new IntVector[]{ + new IntVector(1, 0, 0), + new IntVector(-1, 0, 0), + new IntVector(0, -1, 0), + new IntVector(0, 0, 1), + new IntVector(0, 0, -1) + }; + } + + // Generate quadrants for each direction + for (IntVector direction : directions) { + Map map = new HashMap<>(); + for (int z = (direction.z == 0 ? -1 : 0); z <= 1; z += 2) { + for (int y = (direction.y == 0 ? -1 : 0); y <= 1; y += 2) { + for (int x = (direction.x == 0 ? -1 : 0); x <= 1; x += 2) { + map.put(new IntVector(x, y, z), new BitSet(region.volume())); + } + } + } + blockVisibility.put(direction, map); + } + } + + @SuppressWarnings("deprecation") + public void addPlayer(Player player, boolean activeHiding) { + if(players.add(player) && activeHiding) { + for(Entity entity : entities) + player.hideEntity(FightSystem.getPlugin(), entity); //TODO 1.15- + } + } + + @SuppressWarnings("deprecation") + public void removePlayer(Player player, boolean activeRemoval) { + if(players.remove(player) && activeRemoval) { + for(Entity entity : entities) + player.showEntity(FightSystem.getPlugin(), entity); //TODO 1.15- + } + } + + public void checkEntity(Entity entity) { + Location location = entity.getLocation(); + if(region.inRegion(location) && !visibility.get(new IntVector(location).toId(region))) { //TODO more precise + if(entities.add(entity)) { + for(Player player : players) + player.hideEntity(FightSystem.getPlugin(), entity); //TODO 1.15- + } + } else { + if(entities.remove(entity)) { + for(Player player : players) + player.showEntity(FightSystem.getPlugin(), entity); //TODO 1.15- + } + } + } + + public void removeEntity(Entity entity) { + entities.remove(entity); + } + + public void initialize() { + visibility.clear(); + occluding.clear(); + for (Map direction : blockVisibility.values()) { + for (BitSet set : direction.values()) + set.clear(); + } + + long start = System.currentTimeMillis(); + region.forEach((x, y, z) -> { + IntVector block = new IntVector(x, y, z); + if (isOccluding(Config.world.getBlockAt(x, y, z).getType())) + occluding.set(block.toId(region)); + }); + forEachBorder((root, direction) -> { + for (Map.Entry quadrant : blockVisibility.get(direction).entrySet()) { + checkBlock(new NullList<>(), root, direction, quadrant.getKey(), quadrant.getValue()); + } + }); + FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality()); + + region.forEach(this::printDebug); + } + + public void updateBlockVisibility(Block b, Material changedType) { + IntVector root = new IntVector(b.getX(), b.getY(), b.getZ()); + if (root.notInRegion(region)) + return; + + int id = root.toId(region); + if (!occluding.get(id) || isOccluding(changedType)) + return; + + List uncovered = new ArrayList<>(); + occluding.clear(id); + for (Map.Entry> direction : blockVisibility.entrySet()) { + for (Map.Entry quadrant : direction.getValue().entrySet()) { + if (quadrant.getValue().get(id)) { + quadrant.getValue().clear(id); + checkBlock(uncovered, root, direction.getKey(), quadrant.getKey(), quadrant.getValue()); + } + } + } + + for (IntVector block : uncovered) + printDebug(block.x, block.y, block.z); + + //TODO uncover entities + } + + private final int air = BlockIds.impl.materialToId(Material.AIR); + private final int stone = BlockIds.impl.materialToId(Material.STONE); + private final int red = BlockIds.impl.materialToId(Material.RED_CONCRETE); + + private void printDebug(int x, int y, int z) { + int id = new IntVector(x, y, z).toId(region); + + BlockIdWrapper.impl.setBlock(Config.world, x, y + Config.BlueExtendRegion.getSizeY(), z, visibility.get(id) ? (occluding.get(id) ? red : air) : stone); + } + + private void forEachBorder(BiConsumer f) { + for (int x = region.getMinX(); x < region.getMaxX(); x++) { + for (int z = region.getMinZ(); z < region.getMaxZ(); z++) { + if (groundVisible) + f.accept(new IntVector(x, region.getMinY(), z), new IntVector(0, 1, 0)); + f.accept(new IntVector(x, region.getMaxY() - 1, z), new IntVector(0, -1, 0)); + } + } + + for (int x = region.getMinX(); x < region.getMaxX(); x++) { + for (int y = region.getMinY(); y < region.getMaxY(); y++) { + f.accept(new IntVector(x, y, region.getMinZ()), new IntVector(0, 0, 1)); + f.accept(new IntVector(x, y, region.getMaxZ() - 1), new IntVector(0, 0, -1)); + } + } + + for (int z = region.getMinZ(); z < region.getMaxZ(); z++) { + for (int y = region.getMinY(); y < region.getMaxY(); y++) { + f.accept(new IntVector(region.getMinX(), y, z), new IntVector(1, 0, 0)); + f.accept(new IntVector(region.getMaxX() - 1, y, z), new IntVector(-1, 0, 0)); + } + } + } + + private void checkBlock(List uncovered, IntVector block, IntVector direction, IntVector quadrant, BitSet quadVisibility) { + if (block.notInRegion(region)) + return; + + int id = block.toId(region); + if (quadVisibility.get(id)) + return; + + quadVisibility.set(id); + if (!visibility.get(id)) { + visibility.set(id); + uncovered.add(block); + } + + if (occluding.get(id)) + return; + + IntVector neighbour = block.add(direction); + checkBlock(uncovered, neighbour, direction, quadrant, quadVisibility); + boolean neigbourTransparent = boundedNonOccluding(neighbour); + boolean diagonalReachable = false; + if (direction.x == 0 && (neigbourTransparent || boundedNonOccluding(block.add(quadrant.x, 0, 0)))) { + checkBlock(uncovered, neighbour.add(quadrant.x, 0, 0), direction, quadrant, quadVisibility); + diagonalReachable = boundedNonOccluding(neighbour.add(quadrant.x, 0, 0)); + } + + if (direction.y == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, quadrant.y, 0)))) { + checkBlock(uncovered, neighbour.add(0, quadrant.y, 0), direction, quadrant, quadVisibility); + diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, quadrant.y, 0)); + } + + if (direction.z == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, 0, quadrant.z)))) { + checkBlock(uncovered, neighbour.add(0, 0, quadrant.z), direction, quadrant, quadVisibility); + diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, 0, quadrant.z)); + } + + if (diagonalReachable) + checkBlock(uncovered, neighbour.add(quadrant), direction, quadrant, quadVisibility); + } + + private boolean boundedNonOccluding(IntVector block) { + return !(block.notInRegion(region) || occluding.get(block.toId(region))); + } + + + private static class IntVector { + private final int x; + private final int y; + private final int z; + + public IntVector(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public IntVector(Location location) { + this.x = location.getBlockX(); + this.y = location.getBlockY(); + this.z = location.getBlockZ(); + } + + public boolean notInRegion(Region region) { + return !region.inRegion(x, y, z); + } + + public int toId(Region region) { + return ((y - region.getMinY()) * region.getSizeZ() + (z - region.getMinZ())) * region.getSizeX() + (x - region.getMinX()); + } + + public IntVector add(int x, int y, int z) { + return new IntVector(this.x + x, this.y + y, this.z + z); + } + + public IntVector add(IntVector v) { + return add(v.x, v.y, v.z); + } + + @Override + public int hashCode() { + return y << 24 ^ x << 12 ^ z; + } + + @Override + public boolean equals(Object o) { + if(o == null || this.getClass() != o.getClass()) + return false; + + IntVector v = (IntVector) o; + return x == v.x && y == v.y && z == v.z; + } + + @Override + public String toString() { + return x + "," + y + "," + z; + } + } + + private static class NullList extends AbstractList { + @Override + public void add(int index, E element) { + // Straight to /dev/null! + } + + @Override + public E get(int index) { + return null; + } + + @Override + public int size() { + return 0; + } + } +} diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java index 775c34d..1291202 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java @@ -19,23 +19,27 @@ package de.steamwar.fightsystem.utils; -import de.steamwar.fightsystem.Config; -import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.FightTeam; +import de.steamwar.fightsystem.listener.Recording; import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.states.StateDependentListener; -import de.steamwar.techhider.BlockIds; -import org.bukkit.Material; -import org.bukkit.block.Block; +import de.steamwar.fightsystem.states.StateDependentTask; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPhysicsEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; -import java.util.*; -import java.util.function.BiConsumer; -import java.util.logging.Level; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; public class HullHider implements Listener { @@ -51,7 +55,18 @@ public class HullHider implements Listener { Fight.teams().forEach(team -> hulls.put(team, new Hull(team))); new StateDependentListener(TechHiderWrapper.ENABLED, FightState.Schem, this); - //TODO player enters/leaves team + new StateDependent(TechHiderWrapper.ENABLED, FightState.Schem) { + @Override + public void enable() { + Bukkit.getOnlinePlayers().forEach(player -> addPlayer(player, true)); + } + + @Override + public void disable() { + Bukkit.getOnlinePlayers().forEach(player -> removePlayer(player, true)); + } + }; + new StateDependentTask(TechHiderWrapper.ENABLED, FightState.Schem, this::onTick, 0, 1); } public void initialize(FightTeam team) { @@ -61,226 +76,69 @@ public class HullHider implements Listener { hulls.get(team).initialize(); } + + public void addPlayer(FightTeam team, Player player) { + if(!TechHiderWrapper.ENABLED) + return; + + hulls.get(team).addPlayer(player, true); + } + + public void removePlayer(FightTeam team, Player player) { + if(!TechHiderWrapper.ENABLED) + return; + + hulls.get(team).removePlayer(player, true); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onJoin(PlayerJoinEvent e) { + addPlayer(e.getPlayer(), false); + } + + @EventHandler + public void onLeave(PlayerQuitEvent e) { + removePlayer(e.getPlayer(), false); + } + + private void addPlayer(Player player, boolean activeHiding) { + FightTeam team = Fight.getPlayerTeam(player); + for(Map.Entry hull : hulls.entrySet()) { + if(hull.getKey() == team) + continue; + + hull.getValue().addPlayer(player, activeHiding); + } + } + + private void removePlayer(Player player, boolean activeRemoval) { + hulls.values().forEach(hull -> hull.removePlayer(player, activeRemoval)); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockPhysic(BlockPhysicsEvent e) { if(FlatteningWrapper.impl.doRecord(e)) { - hulls.values().forEach(hull -> hull.updateBlockVisibility(e.getBlock(), e.getChangedType())); + for (Hull hull : hulls.values()) + hull.updateBlockVisibility(e.getBlock(), e.getChangedType()); } } - private static class Hull { - private final Region region; - private final boolean groundVisible; - private final BitSet occluding; - private final BitSet visibility; - private final Map> blockVisibility = new HashMap<>(); - - - public Hull(FightTeam team) { - this.region = team.getSchemRegion(); - this.groundVisible = region.getMinY() != Config.PlayerRegion.getMinY(); - this.occluding = new BitSet(region.volume()); - this.visibility = new BitSet(region.volume()); - - IntVector[] directions; - if(groundVisible) { - directions = new IntVector[] { - new IntVector(1, 0, 0), - new IntVector(-1, 0, 0), - new IntVector(0, 1, 0), - new IntVector(0, -1, 0), - new IntVector(0, 0, 1), - new IntVector(0, 0, -1) - }; - } else { - directions = new IntVector[] { - new IntVector(1, 0, 0), - new IntVector(-1, 0, 0), - new IntVector(0, -1, 0), - new IntVector(0, 0, 1), - new IntVector(0, 0, -1) - }; - } - - // Generate quadrants for each direction - for(IntVector direction : directions) { - Map map = new HashMap<>(); - for(int z = (direction.z == 0 ? -1 : 0); z <= 1; z+=2) { - for(int y = (direction.y == 0 ? -1 : 0); y <= 1; y+=2) { - for(int x = (direction.x == 0 ? -1 : 0); x <= 1; x+=2) { - map.put(new IntVector(x, y, z), new BitSet(region.volume())); - } - } - } - blockVisibility.put(direction, map); - } - } - - public void initialize() { - visibility.clear(); - occluding.clear(); - for(Map direction : blockVisibility.values()) { - for(BitSet set : direction.values()) - set.clear(); - } - - long start = System.currentTimeMillis(); - region.forEach((x, y, z) -> { - IntVector block = new IntVector(x, y, z); - if(Config.world.getBlockAt(x, y, z).getType().isOccluding()) //TODO more accurate check - occluding.set(block.toId(region)); - }); - forEachBorder((root, direction) -> { - for(Map.Entry quadrant : blockVisibility.get(direction).entrySet()) { - checkBlock(root, direction, quadrant.getKey(), quadrant.getValue()); - } - }); - FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.stream().count()); - - region.forEach(this::printDebug); - } - - public void updateBlockVisibility(Block b, Material changedType) { - IntVector root = new IntVector(b.getX(), b.getY(), b.getZ()); - if(root.notInRegion(region)) - return; - - int id = root.toId(region); - if(!occluding.get(id) || changedType.isOccluding()) //TODO more accurate check - return; - - occluding.clear(id); - for(Map.Entry> direction : blockVisibility.entrySet()) { - for(Map.Entry quadrant : direction.getValue().entrySet()) { - if(quadrant.getValue().get(id)) { - quadrant.getValue().clear(id); - checkBlock(root, direction.getKey(), quadrant.getKey(), quadrant.getValue()); - } - } - } - - printDebug(root.x, root.y, root.z); - } - - private final int air = BlockIds.impl.materialToId(Material.AIR); - private final int stone = BlockIds.impl.materialToId(Material.STONE); - private final int red = BlockIds.impl.materialToId(Material.RED_CONCRETE); - private void printDebug(int x, int y, int z) { - int id = new IntVector(x, y, z).toId(region); - - BlockIdWrapper.impl.setBlock(Config.world, x, y + Config.BlueExtendRegion.getSizeY(), z, visibility.get(id) ? (occluding.get(id) ? red : air) : stone); - } - - private void forEachBorder(BiConsumer f) { - for(int x = region.getMinX(); x < region.getMaxX(); x++) { - for(int z = region.getMinZ(); z < region.getMaxZ(); z++) { - if(groundVisible) - f.accept(new IntVector(x, region.getMinY(), z), new IntVector(0, 1, 0)); - f.accept(new IntVector(x, region.getMaxY()-1, z), new IntVector(0, -1, 0)); - } - } - - for(int x = region.getMinX(); x < region.getMaxX(); x++) { - for(int y = region.getMinY(); y < region.getMaxY(); y++) { - f.accept(new IntVector(x, y, region.getMinZ()), new IntVector(0, 0, 1)); - f.accept(new IntVector(x, y, region.getMaxZ()-1), new IntVector(0, 0, -1)); - } - } - - for(int z = region.getMinZ(); z < region.getMaxZ(); z++) { - for(int y = region.getMinY(); y < region.getMaxY(); y++) { - f.accept(new IntVector(region.getMinX(), y, z), new IntVector(1, 0, 0)); - f.accept(new IntVector(region.getMaxX()-1, y, z), new IntVector(-1, 0, 0)); - } - } - } - - private void checkBlock(IntVector block, IntVector direction, IntVector quadrant, BitSet quadVisibility) { - if(block.notInRegion(region)) - return; - - int id = block.toId(region); - if(quadVisibility.get(id)) - return; - - quadVisibility.set(id); - visibility.set(id); - if(occluding.get(id)) - return; - - IntVector neighbour = block.add(direction); - checkBlock(neighbour, direction, quadrant, quadVisibility); - boolean neigbourTransparent = boundedNonOccluding(neighbour); - boolean diagonalReachable = false; - if(direction.x == 0 && (neigbourTransparent || boundedNonOccluding(block.add(quadrant.x, 0, 0)))) { - checkBlock(neighbour.add(quadrant.x, 0, 0), direction, quadrant, quadVisibility); - diagonalReachable = boundedNonOccluding(neighbour.add(quadrant.x, 0, 0)); - } - - if(direction.y == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, quadrant.y, 0)))) { - checkBlock(neighbour.add(0, quadrant.y, 0), direction, quadrant, quadVisibility); - diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, quadrant.y, 0)); - } - - if(direction.z == 0 && (neigbourTransparent || boundedNonOccluding(block.add(0, 0, quadrant.z)))) { - checkBlock(neighbour.add(0, 0, quadrant.z), direction, quadrant, quadVisibility); - diagonalReachable = diagonalReachable || boundedNonOccluding(neighbour.add(0, 0, quadrant.z)); - } - - if(diagonalReachable) - checkBlock(neighbour.add(quadrant), direction, quadrant, quadVisibility); - } - - private boolean boundedNonOccluding(IntVector block) { - return !(block.notInRegion(region) || occluding.get(block.toId(region))); - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onSpawn(EntitySpawnEvent e) { + hulls.values().forEach(hull -> hull.checkEntity(e.getEntity())); } - private static class IntVector { - private final int x; - private final int y; - private final int z; + private void onTick() { + Recording.iterateOverEntities(Objects::nonNull, entity -> { + for (Hull hull : hulls.values()) + hull.checkEntity(entity); + }); + } - public IntVector(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; - } - - public boolean notInRegion(Region region) { - return !region.inRegion(x, y, z); - } - - public int toId(Region region) { - return ((y - region.getMinY()) * region.getSizeZ() + (z - region.getMinZ())) * region.getSizeX() + (x - region.getMinX()); - } - - public IntVector add(int x, int y, int z) { - return new IntVector(this.x + x, this.y + y, this.z + z); - } - - public IntVector add(IntVector v) { - return add(v.x, v.y, v.z); - } - - @Override - public int hashCode() { - return y << 24 ^ x << 12 ^ z; - } - - @Override - public boolean equals(Object o) { - if(o == null || this.getClass() != o.getClass()) - return false; - - IntVector v = (IntVector) o; - return x == v.x && y == v.y && z == v.z; - } - - @Override - public String toString() { - return x + "," + y + "," + z; - } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDeath(EntityDeathEvent e) { + hulls.values().forEach(hull -> hull.removeEntity(e.getEntity())); } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index 5b443da..9638292 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -36,7 +36,6 @@ import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; public class TechHiderWrapper extends StateDependent { @@ -45,7 +44,7 @@ public class TechHiderWrapper extends StateDependent { public TechHiderWrapper() { super(ENABLED, FightState.Schem); - techHider = new TechHider(this::bypass, Material.getMaterial(Config.ObfuscateWith), Config.HiddenBlocks.stream().map(String::toUpperCase).map(Material::getMaterial).collect(Collectors.toSet()), Config.HiddenBlockEntities); + techHider = new TechHider(this::bypass, Material.getMaterial(Config.ObfuscateWith), Config.HiddenBlocks, Config.HiddenBlockEntities); register(); }