diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index 63752202..f4fb2121 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -1244,6 +1244,8 @@ SELECT_ITEM_TESTBLOCK=§eDummy CHESTFILLER_FILLED = §eChest filled CHESTFILLER_COUNT = §7{0}§8: §e§l{1} +PISTON_INFO = §7Moved Blocks {0}{1}§8/§712 + # Warp WARP_DISALLOWED = §cYou are not allowed to use the warp here WARP_LOC_X = §7X§8: §e{0} diff --git a/BauSystem_Main/src/BauSystem_de.properties b/BauSystem_Main/src/BauSystem_de.properties index 524bbe77..1d10d0c6 100644 --- a/BauSystem_Main/src/BauSystem_de.properties +++ b/BauSystem_Main/src/BauSystem_de.properties @@ -1223,6 +1223,8 @@ SELECT_ITEM_TESTBLOCK=§eTestblock CHESTFILLER_FILLED = §eKiste gefüllt +PISTON_INFO = §7Bewegte Blöcke {0}{1}§8/§712 + # Warp WARP_DISALLOWED = §cDu darfst hier nicht das Warp System nutzen WARP_LOC_X = §7X§8: §e{0} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java new file mode 100644 index 00000000..130af74e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java @@ -0,0 +1,131 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 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.bausystem.features.util; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import net.md_5.bungee.api.ChatMessageType; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.PistonMoveReaction; +import org.bukkit.block.TileState; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Piston; +import org.bukkit.block.data.type.PistonHead; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; + +@Linked(LinkageType.LISTENER) +public class PistonCalculator implements Listener { + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.SLIME_BALL) return; + if (event.getClickedBlock() == null) return; + Block clickedBlock = event.getClickedBlock(); + Material blockType = clickedBlock.getType(); + if (!(blockType == Material.PISTON || blockType == Material.STICKY_PISTON)) return; + Piston piston = (Piston) clickedBlock.getBlockData(); + + boolean pulling = blockType == Material.STICKY_PISTON && (clickedBlock.getRelative(piston.getFacing()).getType() == Material.AIR || piston.isExtended()); + + CalculationResult result = calc(clickedBlock, piston.getFacing(), (pulling ? piston.getFacing().getOppositeFace() : piston.getFacing())); + BauSystem.MESSAGE.sendPrefixless("PISTON_INFO", event.getPlayer(), ChatMessageType.ACTION_BAR, result.unmovable ? "§c" : (result.tooMany ? "§e" : "§a"), result.amount); + } + + private final BlockFace[] FACES = new BlockFace[]{BlockFace.UP, BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}; + + private CalculationResult calc(Block origin, BlockFace facing, BlockFace direction) { + Set blockSet = new HashSet<>(); + AtomicBoolean unmovable = new AtomicBoolean(); + + Block calcOrigin = origin; + if (facing != direction) calcOrigin = origin.getRelative(facing, 3); + + List toCalc = new LinkedList<>(); + calcDirection(origin, calcOrigin, facing != direction ? origin.getRelative(facing) : null, facing, direction, blockSet, toCalc, unmovable); + + while (!toCalc.isEmpty()) { + Block current = toCalc.remove(0); + blockSet.add(current); + + Material type = current.getType(); + if (type != Material.SLIME_BLOCK && type != Material.HONEY_BLOCK) continue; + Material oppositeType = type == Material.SLIME_BLOCK ? Material.HONEY_BLOCK : Material.SLIME_BLOCK; + + for (BlockFace face : FACES) { + Block block = current.getRelative(face); + if (block.getType().isAir()) continue; + if (!isPiston(block) && (block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getPistonMoveReaction() == PistonMoveReaction.PUSH_ONLY || block.getState() instanceof TileState)) continue; + if (block.getType() != oppositeType) { + if (!blockSet.contains(block)) toCalc.add(block); + calcDirection(null, block, null, facing, direction, blockSet, toCalc, unmovable); + } + } + } + + blockSet.remove(origin); + if (facing != direction) blockSet.remove(origin.getRelative(facing, 1)); + return new CalculationResult(blockSet.size(), blockSet.size() > 12, unmovable.get()); + } + + private void calcDirection(Block origin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, Set blockSet, List toCalc, AtomicBoolean unmovable) { + for (int i = 1; i < 13; i++) { + Block block = calcOrigin.getRelative(direction, i); + if (block.equals(ignore)) return; + if (block.getPistonMoveReaction() == PistonMoveReaction.BREAK) return; + if (!isPiston(block) && (block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getState() instanceof TileState)) { + unmovable.set(true); + return; + } + if (block.getType().isAir()) return; + if (facing != direction && (block.equals(origin) || block.getRelative(facing.getOppositeFace()).equals(origin))) return; + if (!blockSet.contains(block)) toCalc.add(block); + } + } + + private boolean isPiston(Block block) { + BlockData blockData = block.getBlockData(); + if (blockData instanceof Piston) { + return !((Piston) blockData).isExtended(); + } + return false; + } + + @AllArgsConstructor + @Getter + @ToString + private static class CalculationResult { + private int amount; + private boolean tooMany; + private boolean unmovable; + } +}