diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
index 9a7276b..0d92386 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
@@ -96,6 +96,7 @@ public class BauSystem extends JavaPlugin implements Listener {
getCommand("detonator").setExecutor(new CommandDetonator());
getCommand("detonator").setTabCompleter(new CommandDetonatorTabCompleter());
getCommand("script").setExecutor(new CommandScript());
+ getCommand("simulator").setExecutor(new CommandSimulator());
Bukkit.getPluginManager().registerEvents(this, this);
Bukkit.getPluginManager().registerEvents(new RegionListener(), this);
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSimulator.java b/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSimulator.java
new file mode 100644
index 0000000..5a51c5b
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSimulator.java
@@ -0,0 +1,251 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.canonsimulator;
+
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.inventory.SWAnvilInv;
+import de.steamwar.inventory.SWInventory;
+import de.steamwar.inventory.SWItem;
+import de.steamwar.inventory.SWListInv;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Consumer;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+
+public class TNTSimulator {
+
+ private static final Vector X_VECTOR = new Vector(0.0625, 0, 0);
+ private static final Vector NX_VECTOR = new Vector(-0.0625, 0, 0);
+ private static final Vector Y_VECTOR = new Vector(0, 0.0625, 0);
+ private static final Vector NY_VECTOR = new Vector(0, -0.0625, 0);
+ private static final Vector Z_VECTOR = new Vector(0, 0, 0.0625);
+ private static final Vector NZ_VECTOR = new Vector(0, 0, -0.0625);
+
+ private static Map tntSimulatorMap = new HashMap<>();
+
+ public static void openSimulator(Player player) {
+ if (!tntSimulatorMap.containsKey(player)) {
+ tntSimulatorMap.put(player, new TNTSimulator());
+ }
+ TNTSimulator tntSimulator = tntSimulatorMap.get(player);
+
+ List> swListEntryList = new ArrayList<>();
+ tntSimulator.tntSpawns.forEach(tntSpawn -> {
+ List lore = new ArrayList<>();
+ lore.add("§eTNT-Anzahl§8: §7" + tntSpawn.getCount());
+ lore.add("§eTick§8: §7" + tntSpawn.getTickOffset());
+ lore.add("");
+ lore.add("§eX§8: §7" + tntSpawn.getPosition().getX());
+ lore.add("§eY§8: §7" + tntSpawn.getPosition().getY());
+ lore.add("§eZ§8: §7" + tntSpawn.getPosition().getZ());
+ swListEntryList.add(new SWListInv.SWListEntry<>(new SWItem(Material.TNT, "§eTNT", lore, false, null), tntSpawn));
+ });
+ SWListInv swListInv = new SWListInv<>(player, "Kanonen Simulator", false, swListEntryList, (clickType, tntSpawn) -> {
+ editTNT(player, tntSpawn);
+ });
+ swListInv.setItem(48, new SWItem(Material.BARRIER, "§cLösche alle TNT", clickType -> {
+ tntSimulator.tntSpawns.clear();
+ openSimulator(player);
+ }));
+ swListInv.setItem(49, new SWItem(Material.TNT, "§aNeues TNT", clickType -> {
+ Vector vector = player.getLocation().toVector().multiply(16);
+ vector.setX((int) vector.getX());
+ vector.setY((int) vector.getY());
+ vector.setZ((int) vector.getZ());
+ vector.multiply(0.0625);
+
+ TNTSpawn tntSpawn = new TNTSpawn(vector);
+ if (tntSimulator.tntSpawns.contains(tntSpawn)) {
+ return;
+ }
+ tntSimulator.tntSpawns.add(tntSpawn);
+ editTNT(player, tntSpawn);
+ }));
+ swListInv.setItem(50, new SWItem(Material.FLINT_AND_STEEL, "§eSimulation Starten", clickType -> {
+ tntSimulator.start();
+ player.closeInventory();
+ }));
+ swListInv.open();
+ }
+
+ private static void editTNT(Player player, TNTSpawn tntSpawn) {
+ SWInventory swInventory = new SWInventory(player, 45, "TNT");
+ swInventory.setItem(44, new SWItem(Material.REDSTONE_BLOCK, "§cZurück", clickType -> {
+ openSimulator(player);
+ }));
+
+ // Change Count of spawned TNT
+ swInventory.setItem(10, new SWItem(SWItem.getDye(10), "§a+1", clickType -> {
+ tntSpawn.setCount(tntSpawn.getCount() + 1);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(19, new SWItem(Material.TNT, "§eAnzahl §8- §7" + tntSpawn.getCount(), clickType -> {
+ changeCount(player, count -> {
+ if (count < 1) count = 1;
+ tntSpawn.setCount(count);
+ editTNT(player, tntSpawn);
+ }, () -> editTNT(player, tntSpawn));
+ }));
+ swInventory.setItem(28, new SWItem(SWItem.getDye(1), "§c-1", clickType -> {
+ tntSpawn.setCount(tntSpawn.getCount() - 1);
+ if (tntSpawn.getCount() < 1) {
+ tntSpawn.setCount(1);
+ }
+ editTNT(player, tntSpawn);
+ }));
+
+ // Change TickOffset
+ swInventory.setItem(11, new SWItem(SWItem.getDye(10), "§a+1", clickType -> {
+ tntSpawn.setTickOffset(tntSpawn.getTickOffset() + 1);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(20, new SWItem(Material.CLOCK, "§eTick §8- §7" + tntSpawn.getTickOffset(), clickType -> {
+ changeCount(player, tick -> {
+ if (tick < 0) tick = 0;
+ tntSpawn.setTickOffset(tick);
+ editTNT(player, tntSpawn);
+ }, () -> editTNT(player, tntSpawn));
+ }));
+ swInventory.setItem(29, new SWItem(SWItem.getDye(1), "§c-1", clickType -> {
+ tntSpawn.setTickOffset(tntSpawn.getTickOffset() - 1);
+ if (tntSpawn.getTickOffset() < 0) {
+ tntSpawn.setTickOffset(0);
+ }
+ editTNT(player, tntSpawn);
+ }));
+
+ // Delete icon
+ swInventory.setItem(21, new SWItem(Material.BARRIER, "§cDelete", clickType -> {
+ tntSimulatorMap.get(player).tntSpawns.remove(tntSpawn);
+ openSimulator(player);
+ }));
+
+ // Velocity Settings
+ swInventory.setItem(13, new SWItem(tntSpawn.isxVelocity() ? Material.LIME_WOOL : Material.RED_WOOL, "§eVelocity-X §8- §7" + active(tntSpawn.isxVelocity()), clickType -> {
+ tntSpawn.setxVelocity(!tntSpawn.isxVelocity());
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(22, new SWItem(tntSpawn.isyVelocity() ? Material.LIME_WOOL : Material.RED_WOOL, "§eVelocity-Y §8- §7" + active(tntSpawn.isyVelocity()), clickType -> {
+ tntSpawn.setyVelocity(!tntSpawn.isyVelocity());
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(31, new SWItem(tntSpawn.iszVelocity() ? Material.LIME_WOOL : Material.RED_WOOL, "§eVelocity-Z §8- §7" + active(tntSpawn.iszVelocity()), clickType -> {
+ tntSpawn.setzVelocity(!tntSpawn.iszVelocity());
+ editTNT(player, tntSpawn);
+ }));
+
+ // X Position
+ swInventory.setItem(14, new SWItem(SWItem.getDye(10), "§a+0,0625", clickType -> {
+ tntSpawn.getPosition().add(X_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(23, new SWItem(Material.PAPER, "§ePosition-X §8- §7" + tntSpawn.getPosition().getX(), clickType -> {
+ changePosition(player, x -> {
+ tntSpawn.getPosition().setX(clamp(x));
+ editTNT(player, tntSpawn);
+ }, () -> editTNT(player, tntSpawn));
+ }));
+ swInventory.setItem(32, new SWItem(SWItem.getDye(1), "§c-0,0625", clickType -> {
+ tntSpawn.getPosition().add(NX_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+
+ // Y Position
+ swInventory.setItem(15, new SWItem(SWItem.getDye(10), "§a+0,0625", clickType -> {
+ tntSpawn.getPosition().add(Y_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(24, new SWItem(Material.PAPER, "§ePosition-Y §8- §7" + tntSpawn.getPosition().getY(), clickType -> {
+ changePosition(player, y -> {
+ tntSpawn.getPosition().setY(clamp(y));
+ editTNT(player, tntSpawn);
+ }, () -> editTNT(player, tntSpawn));
+ }));
+ swInventory.setItem(33, new SWItem(SWItem.getDye(1), "§c-0,0625", clickType -> {
+ tntSpawn.getPosition().add(NY_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+
+ // Z Position
+ swInventory.setItem(16, new SWItem(SWItem.getDye(10), "§a+0,0625", clickType -> {
+ tntSpawn.getPosition().add(Z_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.setItem(25, new SWItem(Material.PAPER, "§ePosition-Z §8- §7" + tntSpawn.getPosition().getZ(), clickType -> {
+ changePosition(player, z -> {
+ tntSpawn.getPosition().setZ(clamp(z));
+ editTNT(player, tntSpawn);
+ }, () -> editTNT(player, tntSpawn));
+ }));
+ swInventory.setItem(34, new SWItem(SWItem.getDye(1), "§c-0,0625", clickType -> {
+ tntSpawn.getPosition().add(NZ_VECTOR);
+ editTNT(player, tntSpawn);
+ }));
+ swInventory.open();
+ }
+
+ private static String active(boolean b) {
+ return b ? "§aan" : "§caus";
+ }
+
+ private static void changeCount(Player player, Consumer result, Runnable failure) {
+ SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Zahl");
+ swAnvilInv.setItem(Material.PAPER);
+ swAnvilInv.setCallback(s -> {
+ try {
+ result.accept(Integer.parseInt(s));
+ } catch (NumberFormatException e) {
+ failure.run();
+ }
+ });
+ swAnvilInv.open();
+ }
+
+ private static void changePosition(Player player, Consumer result, Runnable failure) {
+ SWAnvilInv swAnvilInv = new SWAnvilInv(player, "Position");
+ swAnvilInv.setItem(Material.PAPER);
+ swAnvilInv.setCallback(s -> {
+ try {
+ result.accept(Double.parseDouble(s.replace(',', '.')));
+ } catch (NumberFormatException e) {
+ failure.run();
+ }
+ });
+ swAnvilInv.open();
+ }
+
+ private static double clamp(double d) {
+ return (int)(d * 100) * 0.01;
+ }
+
+ private Set tntSpawns = new TreeSet<>();
+
+ public void start() {
+ tntSpawns.forEach(tntSpawn -> {
+ Bukkit.getScheduler().runTaskLater(BauSystem.getPlugin(), tntSpawn::spawn, tntSpawn.getTickOffset() + 1L);
+ });
+ }
+
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSpawn.java b/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSpawn.java
new file mode 100644
index 0000000..cb93471
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/canonsimulator/TNTSpawn.java
@@ -0,0 +1,127 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.canonsimulator;
+
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.util.Vector;
+
+import java.util.Objects;
+
+public class TNTSpawn implements Comparable {
+
+ private static final World WORLD = Bukkit.getWorlds().get(0);
+
+ private Vector position;
+ private int count = 1;
+ private int tickOffset = 0;
+ private boolean xVelocity = true;
+ private boolean yVelocity = true;
+ private boolean zVelocity = true;
+
+ public TNTSpawn(Vector position) {
+ this.position = position;
+ }
+
+ public void spawn() {
+ for (int i = 0; i < count; i++) {
+ WORLD.spawn(position.toLocation(WORLD), TNTPrimed.class, tntPrimed -> {
+ if (!xVelocity) tntPrimed.setVelocity(tntPrimed.getVelocity().setX(0));
+ if (!yVelocity) tntPrimed.setVelocity(tntPrimed.getVelocity().setY(0));
+ if (!zVelocity) tntPrimed.setVelocity(tntPrimed.getVelocity().setZ(0));
+ });
+ }
+ }
+
+ public Vector getPosition() {
+ return position;
+ }
+
+ public void setPosition(Vector position) {
+ this.position = position;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public void setCount(int count) {
+ this.count = count;
+ }
+
+ public int getTickOffset() {
+ return tickOffset;
+ }
+
+ public void setTickOffset(int tickOffset) {
+ this.tickOffset = tickOffset;
+ }
+
+ public boolean isxVelocity() {
+ return xVelocity;
+ }
+
+ public void setxVelocity(boolean xVelocity) {
+ this.xVelocity = xVelocity;
+ }
+
+ public boolean isyVelocity() {
+ return yVelocity;
+ }
+
+ public void setyVelocity(boolean yVelocity) {
+ this.yVelocity = yVelocity;
+ }
+
+ public boolean iszVelocity() {
+ return zVelocity;
+ }
+
+ public void setzVelocity(boolean zVelocity) {
+ this.zVelocity = zVelocity;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof TNTSpawn)) return false;
+ TNTSpawn tntSpawn = (TNTSpawn) o;
+ return count == tntSpawn.count &&
+ tickOffset == tntSpawn.tickOffset &&
+ xVelocity == tntSpawn.xVelocity &&
+ yVelocity == tntSpawn.yVelocity &&
+ zVelocity == tntSpawn.zVelocity &&
+ position.equals(tntSpawn.position);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(position, count, tickOffset, xVelocity, yVelocity, zVelocity);
+ }
+
+ @Override
+ public int compareTo(TNTSpawn tntSpawn) {
+ return -Integer.compare(tickOffset, tntSpawn.tickOffset);
+ }
+
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandSimulator.java b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandSimulator.java
new file mode 100644
index 0000000..5c48636
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/commands/CommandSimulator.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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.commands;
+
+import de.steamwar.bausystem.canonsimulator.TNTSimulator;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class CommandSimulator implements CommandExecutor {
+
+ @Override
+ public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
+ if(!(commandSender instanceof Player))
+ return false;
+ Player p = (Player) commandSender;
+ TNTSimulator.openSimulator(p);
+ return false;
+ }
+
+}
diff --git a/BauSystem_Main/src/plugin.yml b/BauSystem_Main/src/plugin.yml
index bc85fb9..200cb28 100644
--- a/BauSystem_Main/src/plugin.yml
+++ b/BauSystem_Main/src/plugin.yml
@@ -33,4 +33,6 @@ commands:
lockschem:
detonator:
aliases: dt
- script:
\ No newline at end of file
+ script:
+ simulator:
+ aliases: sim
\ No newline at end of file