diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index c539480b..ad8d78a5 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -1116,6 +1116,15 @@ PANZERN_NO_WORLDEDIT = §cDu hast keine WorldEdit Selection PANZERN_PROGRESS = §e{0} §7Blöcke übrig, §e{1} §7Blöcke pro Sekunde, §e{2} §7Block Delta PANZERN_DONE = §aZuende gepanzert +# Laufbau +LAUFBAU_HELP = §8/§elaufbau §8[§7Block§8] §8[§7Slab§8] §8- §7Baue einen Lauf in deiner WorldEdit Auswahl mit den Traces +LAUFBAU_PREPARE1 = §71. Trace die Kanonen so oft wie nötig, in allen Modi. +LAUFBAU_PREPARE2 = §72. Versuche alle Fails aus dem Trace zu löschen. +LAUFBAU_NO_PERM = §cDu darfst hier nicht das Laufbau System verwenden +LAUFBAU_NO_WORLDEDIT = §cDu hast keine WorldEdit Selection +LAUFBAU_PROGRESS = §e{0} §7Blöcke übrig, §e{1} §7Blöcke pro Sekunde, §e{2} §7Block Delta +LAUFBAU_DONE = §aZuende gepanzert + # UTILS SELECT_HELP = §8/§eselect §8[§7RegionsTyp§8] §8- §7Wähle einen RegionsTyp aus SELECT_EXTENSION_HELP = §8/§eselect §8[§7RegionsTyp§8] §8[§7Extension§8] §8- §7Wähle einen RegionsTyp aus mit oder ohne Extension diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java new file mode 100644 index 00000000..7873a924 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java @@ -0,0 +1,221 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.slaves.laufbau; + +import de.steamwar.bausystem.features.tracer.TNTPosition; +import de.steamwar.bausystem.features.tracer.show.StoredRecords; +import de.steamwar.bausystem.utils.FlatteningWrapper; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Slab; +import org.bukkit.util.Vector; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +public class Laufbau { + + private Set tntPositions = new HashSet<>(); + private Map laufMap = new HashMap<>(); + + private World world; + private Location pos1; + private Location pos2; + private Material blockMaterial; + private Material slabMaterial; + + public Laufbau(Location pos1, Location pos2, Material blockMaterial, Material slabMaterial) { + this.world = pos1.getWorld(); + this.pos1 = new Location(world, Math.min(pos1.getBlockX(), pos2.getBlockX()), Math.min(pos1.getBlockY(), pos2.getBlockY()), Math.min(pos1.getBlockZ(), pos2.getBlockZ())); + this.pos2 = new Location(world, Math.max(pos1.getBlockX(), pos2.getBlockX()), Math.max(pos1.getBlockY(), pos2.getBlockY()), Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + this.blockMaterial = blockMaterial; + this.slabMaterial = slabMaterial; + + StoredRecords.getRecords().forEach(record -> { + record.getTnt().forEach(tntRecord -> { + tntRecord.getPositions().forEach(tntPosition -> { + if (FlatteningWrapper.impl.inWater(world, tntPosition.getLocation())) { + return; + } + if (inRegionExpanded(tntPosition.getLocation().toLocation(world))) { + tntPositions.add(tntPosition); + } + if (tntPosition.getPreviousLocation() != null && inRegionExpanded(tntPosition.getPreviousLocation().toLocation(world))) { + tntPositions.add(tntPosition); + } + }); + }); + }); + + for (TNTPosition tntPosition : tntPositions) { + Vector current = tntPosition.getLocation(); + + boolean xPositive = current.getX() - (int) current.getX() > 0; + boolean yPositive = current.getY() - (int) current.getY() >= 0.5; + boolean zPositive = current.getZ() - (int) current.getZ() > 0; + + UnaryTriConsumer coordinateConsumer = (x, y, z) -> { + Point point = new Point(x, y + (yPositive ? 1 : 0), z); + if (inRegion(point)) laufMap.put(point, Type.FULL); + point = new Point(x, y + (yPositive ? 0 : 1), z); + if (inRegion(point)) laufMap.putIfAbsent(point, (yPositive ? Type.HALF_TOP : Type.HALF_BOTTOM)); + }; + update(current, xPositive, zPositive, coordinateConsumer); + + if (tntPosition.getPreviousLocation() != null) { + boolean previousXPositive = tntPosition.getPreviousLocation().getX() - (int) tntPosition.getPreviousLocation().getX() > 0; + boolean previousZPositive = tntPosition.getPreviousLocation().getZ() - (int) tntPosition.getPreviousLocation().getZ() > 0; + System.out.println("- empty"); + System.out.println(tntPosition.getPreviousLocation()); + interpolate(tntPosition.getPreviousLocation().getY(), tntPosition.getLocation().getY(), y -> { + Vector vector = new Vector(tntPosition.getPreviousLocation().getX(), y, tntPosition.getPreviousLocation().getZ()); + System.out.println(vector); + update(vector, previousXPositive, previousZPositive, coordinateConsumer); + }); + System.out.println(tntPosition.getLocation()); + // Vector movement = tntPosition.getLocation().clone().subtract(tntPosition.getPreviousLocation()); + } + } + + BlockData fullBlock = Material.STONE.createBlockData(); + Slab topBlock = (Slab) Material.STONE_SLAB.createBlockData(); + Slab bottomBlock = (Slab) Material.STONE_SLAB.createBlockData(); + topBlock.setType(Slab.Type.TOP); + bottomBlock.setType(Slab.Type.BOTTOM); + Bukkit.getOnlinePlayers().forEach(player -> { + laufMap.forEach((point, type) -> { + if (type == Type.HALF_TOP) { + player.sendBlockChange(point.toVector().toLocation(world), topBlock); + } else if (type == Type.HALF_BOTTOM) { + player.sendBlockChange(point.toVector().toLocation(world), bottomBlock); + } else if (type == Type.FULL) { + player.sendBlockChange(point.toVector().toLocation(world), fullBlock); + } + }); + }); + System.out.println(laufMap); + } + + private void update(Vector current, boolean xPositive, boolean zPositive, UnaryTriConsumer coordinateConsumer) { + coordinateConsumer.accept((int) current.getX(), (int) current.getY(), (int) current.getZ()); + coordinateConsumer.accept((int) current.getX() + (xPositive ? 1 : -1), (int) current.getY(), (int) current.getZ()); + coordinateConsumer.accept((int) current.getX(), (int) current.getY(), (int) current.getZ() + (zPositive ? 1 : -1)); + coordinateConsumer.accept((int) current.getX() + (xPositive ? 1 : -1), (int) current.getY(), (int) current.getZ() + (zPositive ? 1 : -1)); + } + + private void interpolate(double from, double to, Consumer integerConsumer) { + if (from > to) { + for (double i = to; i <= from + 0.1; i += 0.1) { + integerConsumer.accept(i); + } + } else { + for (double i = from; i <= to + 0.1; i += 0.1) { + integerConsumer.accept(i); + } + } + } + + private boolean inRegion(Location location) { + return inRegion(location.toVector()); + } + + private boolean inRegion(Point point) { + return inRegion(point.toVector()); + } + + private boolean inRegion(Vector location) { + if (location.getBlockX() >= pos1.getBlockX()) { + if (location.getBlockY() >= pos1.getBlockY()) { + if (location.getBlockZ() >= pos1.getBlockZ()) { + if (location.getBlockX() <= pos2.getBlockX()) { + if (location.getBlockY() <= pos2.getBlockY()) { + if (location.getBlockZ() <= pos2.getBlockZ()) { + return true; + } + } + } + } + } + } + return false; + } + + private boolean inRegionExpanded(Location location) { + return inRegionExpanded(location.toVector()); + } + + private boolean inRegionExpanded(Vector location) { + if (location.getBlockX() > pos1.getBlockX() - 1) { + if (location.getBlockY() > pos1.getBlockY() - 1) { + if (location.getBlockZ() > pos1.getBlockZ() - 1) { + if (location.getBlockX() < pos2.getBlockX() + 1) { + if (location.getBlockY() < pos2.getBlockY() + 1) { + if (location.getBlockZ() < pos2.getBlockZ() + 1) { + return true; + } + } + } + } + } + } + return false; + } + + private enum Type { + FULL, + HALF_BOTTOM, + HALF_TOP, + EMPTY + } + + @Getter + @RequiredArgsConstructor + @EqualsAndHashCode + @ToString + private class Point { + private final int x; + private final int y; + private final int z; + + public Point(Vector vector) { + this.x = vector.getBlockX(); + this.y = vector.getBlockY(); + this.z = vector.getBlockZ(); + } + + public Vector toVector() { + return new Vector(x, y, z); + } + } + + private interface UnaryTriConsumer { + void accept(T first, T second, T third); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java new file mode 100644 index 00000000..9f8f952e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java @@ -0,0 +1,128 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.slaves.laufbau; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.features.slaves.WorldEditUtils; +import de.steamwar.bausystem.features.slaves.panzern.Panzern; +import de.steamwar.bausystem.linkage.LinkageType; +import de.steamwar.bausystem.linkage.Linked; +import de.steamwar.bausystem.shared.Pair; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@Linked(LinkageType.COMMAND) +public class LaufbauCommand extends SWCommand { + + public LaufbauCommand() { + super("laufbau", "laufsklave"); + } + + private boolean permissionCheck(Player player, Permission permission) { + if (Permission.hasPermission(player, permission)) { + return true; + } + BauSystem.MESSAGE.send("LAUFBAU_NO_PERM", player); + return false; + } + + @Register(help = true) + public void genericHelp(Player player, String... args) { + BauSystem.MESSAGE.send("COMMAND_HELP_HEAD", player, "laufbau"); + BauSystem.MESSAGE.send("LAUFBAU_HELP", player); + BauSystem.MESSAGE.send("LAUFBAU_PREPARE1", player); + BauSystem.MESSAGE.send("LAUFBAU_PREPARE2", player); + } + + @Register + public void laufbauSelection(Player player, @Mapper("block") Material blockMaterial, @Mapper("slab") Material slabMaterial) { + if (!permissionCheck(player, Permission.WORLDEDIT)) { + return; + } + Pair selection = WorldEditUtils.getSelection(player); + if (selection == null) { + BauSystem.MESSAGE.send("LAUFBAU_NO_WORLDEDIT", player); + return; + } + Laufbau laufbau = new Laufbau(selection.getKey(), selection.getValue(), blockMaterial, slabMaterial); + } + + @Mapper(value = "block", local = true) + private TypeMapper blockMapper() { + Set strings = new HashSet<>(); + for (Material material : Material.values()) { + if (!material.isBlock()) { + continue; + } + strings.add(material.name().toLowerCase()); + } + return new TypeMapper() { + @Override + public List tabCompletes(CommandSender commandSender, String[] ignored, String s) { + return new ArrayList<>(strings); + } + + @Override + public Material map(CommandSender commandSender, String[] previousArguments, String s) { + if (strings.contains(s.toLowerCase())) { + return Material.valueOf(s.toUpperCase()); + } + return null; + } + }; + } + + @Mapper(value = "slab", local = true) + private TypeMapper slabMapper() { + Set strings = new HashSet<>(); + for (Material material : Material.values()) { + if (!material.isBlock()) { + continue; + } + if (material.name().contains("STAIRS") || material.name().contains("SLAB")) { + strings.add(material.name().toLowerCase()); + } + } + return new TypeMapper() { + @Override + public List tabCompletes(CommandSender commandSender, String[] ignored, String s) { + return new ArrayList<>(strings); + } + + @Override + public Material map(CommandSender commandSender, String[] previousArguments, String s) { + if (strings.contains(s.toLowerCase())) { + return Material.valueOf(s.toUpperCase()); + } + return null; + } + }; + } +}