diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracer.java b/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracer.java index bf4871bf..e4e39b4c 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracer.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracer.java @@ -19,71 +19,158 @@ package de.steamwar.bausystem.features.observer; -import lombok.experimental.UtilityClass; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Particle; -import org.bukkit.block.*; -import org.bukkit.block.Dispenser; -import org.bukkit.block.Hopper; -import org.bukkit.block.data.Powerable; -import org.bukkit.block.data.type.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.data.Bisected; +import org.bukkit.block.data.BlockData; import org.bukkit.block.data.type.Observer; +import org.bukkit.block.data.type.*; +import org.bukkit.craftbukkit.v1_15_R1.block.impl.CraftPoweredRail; import org.bukkit.entity.Player; import java.util.*; -import java.util.function.BiPredicate; -@UtilityClass public class ObserverTracer { - private final Set ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN); + private static final Set ALLOWED = EnumSet.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN); - private Set> predicates = new HashSet<>(); + private Player player; + private Set seen = new HashSet<>(); + private List blockList = new ArrayList<>(); - static { - predicates.add((block, blockFace) -> { - if (block.getType() != Material.OBSERVER) { - return false; - } - Observer observer = (Observer) block.getBlockData(); - return observer.getFacing() == blockFace.getOppositeFace(); - }); + public ObserverTracer(Player player) { + this.player = player; } - public void trace(Player player, Block block) { + public void trace(Block block) { if (block.getType() != Material.OBSERVER) { return; } - Set seen = new HashSet<>(); - List blockList = new ArrayList<>(); blockList.add(block); while (!blockList.isEmpty()) { - Block b = blockList.remove(0); - for (BlockFace blockFace : ALLOWED) { - Location location = b.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); - Block toCheck = location.getBlock(); - if (!seen.add(location)) { - continue; - } + blockList.removeIf(b -> seen.contains(b.getLocation())); + if (blockList.isEmpty()) { + break; + } - for (BiPredicate predicate : predicates) { - if (predicate.test(toCheck, blockFace)) { - blockList.add(toCheck); - player.spawnParticle(Particle.FLAME, location.clone().add(0, 0, 0), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(1, 0, 0), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(1, 0, 1), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(0, 0, 1), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(0, 1, 0), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(1, 1, 0), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(1, 1, 1), 1, 0, 0, 0, 0); - player.spawnParticle(Particle.FLAME, location.clone().add(0, 1, 1), 1, 0, 0, 0, 0); + Block b = blockList.remove(0); + seen.add(b.getLocation()); + spawnParticle(player, b.getLocation()); + + switch (b.getType()) { + case OBSERVER: + calculateObserver(b); + break; + default: + BlockData blockData = b.getBlockData(); + if (blockData instanceof Door) { + if (((Door) blockData).getHalf() == Bisected.Half.BOTTOM) { + blockList.add(b.getLocation().add(0, 1, 0).getBlock()); + } else { + blockList.add(b.getLocation().add(0, -1, 0).getBlock()); + } + } + if (checkAllowed(b, blockData)) { + calculateSpecial(b); break; } - } + if (b.getType().isBlock() && b.getType().isSolid()) { + calculateSolidBlock(b); + } + break; } } } + private void spawnParticle(Player player, Location location) { + player.spawnParticle(Particle.FLAME, location.clone().add(0, 0, 0), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(1, 0, 0), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(1, 0, 1), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(0, 0, 1), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(0, 1, 0), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(1, 1, 0), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(1, 1, 1), 1, 0, 0, 0, 0); + player.spawnParticle(Particle.FLAME, location.clone().add(0, 1, 1), 1, 0, 0, 0, 0); + } + + private void calculateObserver(Block block) { + Observer observer = (Observer) block.getBlockData(); + for (BlockFace blockFace : ALLOWED) { + Location location = block.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + Block b = location.getBlock(); + if (blockFace == observer.getFacing().getOppositeFace() && !b.getType().isAir()) { + blockList.add(b); + Material material = b.getType(); + if (material == Material.REDSTONE_LAMP || material == Material.DROPPER || material == Material.DISPENSER) { + calculateRedstoneLamp(b); + } + continue; + } + if (b.getType() != Material.OBSERVER) { + continue; + } + if (((Observer) b.getBlockData()).getFacing() == blockFace.getOppositeFace()) { + blockList.add(b); + } + } + } + + private void calculateRedstoneLamp(Block block) { + for (BlockFace blockFace : ALLOWED) { + Location location = block.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + Block b = location.getBlock(); + if (checkAllowed(b, b.getBlockData())) { + blockList.add(b); + } + } + } + + private void calculateSolidBlock(Block block) { + for (BlockFace blockFace : ALLOWED) { + Location location = block.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + Block b = location.getBlock(); + BlockData blockData = b.getBlockData(); + if (checkAllowed(b, blockData)) { + blockList.add(b); + } + } + } + + private boolean checkAllowed(Block block, BlockData blockData) { + if (block.getType() == Material.DROPPER) { + return true; + } + if (block.getType() == Material.HOPPER) { + return true; + } + if (block.getType() == Material.DISPENSER) { + return true; + } + if (block.getType() == Material.REDSTONE_LAMP) { + return true; + } + + return blockData instanceof Door + || blockData instanceof Gate + || blockData instanceof NoteBlock + || blockData instanceof CraftPoweredRail + || blockData instanceof TrapDoor; + } + + private void calculateSpecial(Block block) { + for (BlockFace blockFace : ALLOWED) { + Location location = block.getLocation().add(blockFace.getModX(), blockFace.getModY(), blockFace.getModZ()); + Block b = location.getBlock(); + if (b.getType() == Material.OBSERVER) { + Observer blockData = (Observer) b.getBlockData(); + if (blockData.getFacing() == blockFace.getOppositeFace()) { + blockList.add(b); + } + } + } + } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracerListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracerListener.java index 42428323..34b7de77 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracerListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/observer/ObserverTracerListener.java @@ -36,7 +36,7 @@ public class ObserverTracerListener implements Listener { return; } if (event.getClickedBlock().getType() == Material.OBSERVER) { - ObserverTracer.trace(event.getPlayer(), event.getClickedBlock()); + new ObserverTracer(event.getPlayer()).trace(event.getClickedBlock()); } } }