diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/.gitkeep b/BauSystem_15/src/de/steamwar/bausystem/features/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/detonator/DetonatorEntity_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/detonator/DetonatorEntity_15.java
new file mode 100644
index 00000000..795c14f9
--- /dev/null
+++ b/BauSystem_15/src/de/steamwar/bausystem/features/detonator/DetonatorEntity_15.java
@@ -0,0 +1,81 @@
+/*
+ * 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.detonator;
+
+import net.minecraft.server.v1_15_R1.*;
+import org.bukkit.World;
+import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+class DetonatorEntity_15 extends EntityFallingBlock implements AbstractDetonatorEntity {
+
+ private static final Vec3D ZERO = new Vec3D(0, 0, 0);
+ private final Vector position;
+ private int references = 0;
+
+ public DetonatorEntity_15(World world, Vector position) {
+ super(((CraftWorld) world).getHandle(), position.getX(), position.getY(), position.getZ(), Blocks.RED_STAINED_GLASS.getBlockData());
+ this.position = position;
+
+ this.h(true);
+ this.setNoGravity(true);
+ this.ticksLived = -12000;
+ }
+
+ @Override
+ public void display(Player player) {
+ if (references++ > 0)
+ return;
+
+ PacketPlayOutSpawnEntity packetPlayOutSpawnEntity = new PacketPlayOutSpawnEntity(getId(), getUniqueID(), position.getX(), position.getY(), position.getZ(), 0, 0, EntityTypes.FALLING_BLOCK, Block.getCombinedId(Blocks.RED_STAINED_GLASS.getBlockData()), ZERO);
+ PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
+ playerConnection.sendPacket(packetPlayOutSpawnEntity);
+
+ PacketPlayOutEntityMetadata packetPlayOutEntityMetadata = new PacketPlayOutEntityMetadata(getId(), datawatcher, true);
+ playerConnection.sendPacket(packetPlayOutEntityMetadata);
+ }
+
+ @Override
+ public boolean hide(Player player, boolean force) {
+ if (!force && --references > 0)
+ return false;
+
+ sendDestroy(player);
+ die();
+ return true;
+ }
+
+ private void sendDestroy(Player player) {
+ PacketPlayOutEntityDestroy packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(getId());
+ ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packetPlayOutEntityDestroy);
+ }
+
+ @Override
+ public void sendEntity(Player player) {
+ display(player);
+ }
+
+ @Override
+ public void sendEntityDestroy(Player player) {
+ hide(player, false);
+ }
+}
diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/detonator/Detonator_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/detonator/Detonator_15.java
new file mode 100644
index 00000000..05b8abd4
--- /dev/null
+++ b/BauSystem_15/src/de/steamwar/bausystem/features/detonator/Detonator_15.java
@@ -0,0 +1,30 @@
+/*
+ * 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.detonator;
+
+import org.bukkit.World;
+import org.bukkit.util.Vector;
+
+public class Detonator_15 {
+
+ static AbstractDetonatorEntity constructEntity(World world, Vector position) {
+ return new DetonatorEntity_15(world, position);
+ }
+}
diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/simulator/SimulatorEntity_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/SimulatorEntity_15.java
index 6e10e2b1..903f3871 100644
--- a/BauSystem_15/src/de/steamwar/bausystem/features/simulator/SimulatorEntity_15.java
+++ b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/SimulatorEntity_15.java
@@ -30,8 +30,8 @@ class SimulatorEntity_15 extends BaseEntity_15 implements AbstractSimulatorEntit
private ReferenceCounter referenceCounter = new ReferenceCounter();
- public SimulatorEntity_15(World world, Vector position, boolean tnt) {
- super(world, position, tnt ? Material.TNT : Material.WHITE_STAINED_GLASS);
+ public SimulatorEntity_15(World world, Vector position, boolean highlight) {
+ super(world, position, highlight ? Material.TNT : Material.WHITE_STAINED_GLASS);
this.setNoGravity(true);
this.ticksLived = -12000;
@@ -52,7 +52,7 @@ class SimulatorEntity_15 extends BaseEntity_15 implements AbstractSimulatorEntit
return false;
}
- sendDestroy(player);
+ sendEntityDestroy(player);
die();
return true;
}
diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator_15.java
index c593dbcd..22504db2 100644
--- a/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator_15.java
+++ b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator_15.java
@@ -24,8 +24,8 @@ import org.bukkit.util.Vector;
public class Simulator_15 {
- public static AbstractSimulatorEntity create(World world, Vector tntPosition, boolean tnt) {
- return new SimulatorEntity_15(world, tntPosition, tnt);
+ public static AbstractSimulatorEntity create(World world, Vector tntPosition, boolean highlight) {
+ return new SimulatorEntity_15(world, tntPosition, highlight);
}
}
diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/tracer/TraceEntity_15.java b/BauSystem_15/src/de/steamwar/bausystem/features/tracer/TraceEntity_15.java
index e427ec59..e4447ee5 100644
--- a/BauSystem_15/src/de/steamwar/bausystem/features/tracer/TraceEntity_15.java
+++ b/BauSystem_15/src/de/steamwar/bausystem/features/tracer/TraceEntity_15.java
@@ -46,7 +46,7 @@ class TraceEntity_15 extends BaseEntity_15 implements AbstractTraceEntity {
this.setCustomName(new ChatComponentText("Bumm"));
this.exploded = true;
if (referenceCounter.increment() > 0) {
- sendDestroy(player);
+ sendEntityDestroy(player);
}
} else if (referenceCounter.increment() > 0) {
return;
@@ -61,7 +61,7 @@ class TraceEntity_15 extends BaseEntity_15 implements AbstractTraceEntity {
return false;
}
- sendDestroy(player);
+ sendEntityDestroy(player);
die();
return true;
}
diff --git a/BauSystem_15/src/de/steamwar/bausystem/shared/BaseEntity_15.java b/BauSystem_15/src/de/steamwar/bausystem/shared/BaseEntity_15.java
index e1e0f02b..84befad9 100644
--- a/BauSystem_15/src/de/steamwar/bausystem/shared/BaseEntity_15.java
+++ b/BauSystem_15/src/de/steamwar/bausystem/shared/BaseEntity_15.java
@@ -28,7 +28,7 @@ import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-public class BaseEntity_15 extends EntityFallingBlock {
+public class BaseEntity_15 extends EntityFallingBlock implements AbstractEntity {
private static final Vec3D ZERO = new Vec3D(0, 0, 0);
@@ -44,7 +44,7 @@ public class BaseEntity_15 extends EntityFallingBlock {
this.ticksLived = -12000;
}
- protected void sendEntity(Player player) {
+ public void sendEntity(Player player) {
PacketPlayOutSpawnEntity packetPlayOutSpawnEntity = new PacketPlayOutSpawnEntity(getId(), getUniqueID(), position.getX(), position.getY(), position.getZ(), 0, 0, EntityTypes.FALLING_BLOCK, Block.getCombinedId(iBlockData), ZERO);
PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection;
playerConnection.sendPacket(packetPlayOutSpawnEntity);
@@ -53,7 +53,7 @@ public class BaseEntity_15 extends EntityFallingBlock {
playerConnection.sendPacket(packetPlayOutEntityMetadata);
}
- protected void sendDestroy(Player player) {
+ public void sendEntityDestroy(Player player) {
PacketPlayOutEntityDestroy packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(getId());
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packetPlayOutEntityDestroy);
}
diff --git a/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java b/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java
index 54c3eae0..043950e1 100644
--- a/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java
+++ b/BauSystem_API/src/de/steamwar/bausystem/SWUtils.java
@@ -19,16 +19,24 @@
package de.steamwar.bausystem;
+import lombok.Getter;
+import lombok.Setter;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.Plugin;
@UtilityClass
public class SWUtils {
+ @Getter
+ @Setter
+ private static Plugin bausystem;
+
public static void giveItemToPlayer(Player player, ItemStack itemStack) {
if (itemStack == null || itemStack.getType() == Material.AIR) {
return;
@@ -51,4 +59,8 @@ public class SWUtils {
public static void sendToActionbar(Player p, String message) {
p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
}
+
+ public static NamespacedKey getNamespaceKey(String name) {
+ return new NamespacedKey(getBausystem(), name);
+ }
}
diff --git a/BauSystem_API/src/de/steamwar/bausystem/features/detonator/AbstractDetonatorEntity.java b/BauSystem_API/src/de/steamwar/bausystem/features/detonator/AbstractDetonatorEntity.java
new file mode 100644
index 00000000..1f1a5b8b
--- /dev/null
+++ b/BauSystem_API/src/de/steamwar/bausystem/features/detonator/AbstractDetonatorEntity.java
@@ -0,0 +1,35 @@
+/*
+ * 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.detonator;
+
+import de.steamwar.bausystem.shared.AbstractEntity;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public interface AbstractDetonatorEntity extends AbstractEntity {
+
+ void display(Player player);
+
+ boolean hide(Player player, boolean always);
+
+ int getId();
+
+ Entity getBukkitEntity();
+}
diff --git a/BauSystem_API/src/de/steamwar/bausystem/features/detonator/Detoblock.java b/BauSystem_API/src/de/steamwar/bausystem/features/detonator/Detoblock.java
new file mode 100644
index 00000000..ce97930d
--- /dev/null
+++ b/BauSystem_API/src/de/steamwar/bausystem/features/detonator/Detoblock.java
@@ -0,0 +1,50 @@
+/*
+ * 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.detonator;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+public enum Detoblock {
+ SWITCH(0, true, "Hebel"),
+ WOOD_BUTTON(30, "Knopf"),
+ STONE_BUTTON(20, "Knopf"),
+ PRESSURE_PLATE(30, "Druckplatte"),
+ WEIGHTED_PRESSURE_PLATE(20, "Druckplatte"),
+ TRIPWIRE(30, "Tripwire"),
+ NOTEBLOCK(1, "Noteblock"),
+ REDSTONETORCH(0, true, "Redstonefackel"),
+ POWERABLE(0, true, "Aktivierbarer Block"),
+ INVALID(-1, "Invalider");
+
+ @Getter
+ private final int time;
+ @Getter
+ private final boolean toggle;
+ @Getter
+ private final String name;
+
+ Detoblock(int time, String name) {
+ this.time = time;
+ this.name = name;
+ toggle = false;
+ }
+}
diff --git a/BauSystem_API/src/de/steamwar/bausystem/shared/AbstractEntity.java b/BauSystem_API/src/de/steamwar/bausystem/shared/AbstractEntity.java
index 6627cae9..a187531b 100644
--- a/BauSystem_API/src/de/steamwar/bausystem/shared/AbstractEntity.java
+++ b/BauSystem_API/src/de/steamwar/bausystem/shared/AbstractEntity.java
@@ -19,5 +19,9 @@
package de.steamwar.bausystem.shared;
+import org.bukkit.entity.Player;
+
public interface AbstractEntity {
+ void sendEntity(Player player);
+ void sendEntityDestroy(Player player);
}
diff --git a/BauSystem_API/src/de/steamwar/bausystem/shared/SizedStack.java b/BauSystem_API/src/de/steamwar/bausystem/shared/SizedStack.java
new file mode 100644
index 00000000..7d503b2e
--- /dev/null
+++ b/BauSystem_API/src/de/steamwar/bausystem/shared/SizedStack.java
@@ -0,0 +1,143 @@
+/*
+ * 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.shared;
+
+@SuppressWarnings({"unused", "UnusedReturnValue"})
+public class SizedStack {
+
+ private int maxSize;
+ private T[] data;
+ private int size;
+ private int head;
+
+ public SizedStack(int size) {
+ this.maxSize = size;
+ //noinspection unchecked
+ this.data = (T[]) new Object[this.maxSize];
+ this.head = 0;
+ this.size = 0;
+ }
+
+ public T push(final T element) {
+ this.data[this.head] = element;
+ this.increaseHead();
+ this.increaseSize();
+ return element;
+ }
+
+ public T pop() {
+ this.decreaseHead();
+ this.decreaseSize();
+ final T result = this.data[this.head];
+ this.data[this.head] = null;
+ return result;
+ }
+
+ public T peek() {
+ return this.data[this.head];
+ }
+
+ public boolean empty() {
+ return this.size == 0;
+ }
+
+ protected boolean canEqual(final Object other) {
+ return other instanceof SizedStack;
+ }
+
+ private void increaseHead() {
+ this.head++;
+ while (this.head > this.maxSize - 1) {
+ this.head -= this.maxSize;
+ }
+ }
+
+ private void decreaseHead() {
+ this.head--;
+ while (this.head < 0) {
+ this.head += this.maxSize;
+ }
+ }
+
+ private void increaseSize() {
+ if (this.size < this.maxSize) {
+ this.size++;
+ }
+ }
+
+ private void decreaseSize() {
+ if (this.size > 0) {
+ this.size--;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.maxSize;
+ result = result * PRIME + this.toString().hashCode();
+ result = result * PRIME + this.size;
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof SizedStack)) {
+ return false;
+ }
+ final SizedStack> other = (SizedStack>) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (this.maxSize != other.maxSize) {
+ return false;
+ }
+ if (this.size != other.size) {
+ return false;
+ }
+ if (!this.data.getClass().equals(other.data.getClass())) {
+ return false;
+ }
+ return this.toString().equals(other.toString());
+ }
+
+ public int getMaxSize() {
+ return maxSize;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder result = new StringBuilder("[");
+ for (int i = 0; i < this.size - 1; i++) {
+ result.append(this.data[(this.head - i - 1 < 0) ? (this.head - i - 1 + this.maxSize) : (this.head - i - 1)]).append(",");
+ }
+ result.append(this.data[(this.head - this.size < 0) ? (this.head - this.size + this.maxSize) : (this.head - this.size)]);
+ result.append("]");
+ return result.toString();
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
index 3562cf5a..ae41d271 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java
@@ -35,6 +35,8 @@ public class BauSystem extends JavaPlugin implements Listener {
@Override
public void onEnable() {
instance = this;
+ SWUtils.setBausystem(instance);
+
LinkageUtils.link();
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/BauCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/BauCommand.java
index 40f9fa4f..83af51c6 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/BauCommand.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/BauCommand.java
@@ -24,6 +24,7 @@ import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.linkage.LinkageType;
import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.bausystem.linkage.LinkedInstance;
import de.steamwar.command.SWCommand;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.TypeMapper;
@@ -36,6 +37,9 @@ import java.util.stream.Collectors;
@Linked(LinkageType.COMMAND)
public class BauCommand extends SWCommand {
+ @LinkedInstance(BauServer.class)
+ private BauServer bauServer;
+
public BauCommand() {
super("bau", "b", "gs");
}
@@ -43,7 +47,7 @@ public class BauCommand extends SWCommand {
@Register(help = true)
public void genericHelp(Player p, String... args) {
p.sendMessage("§8/§ebau togglewe §8[§7Player§8] §8- §7Editiere die WorldEdit Rechte eines Spielers");
- p.sendMessage("§8/§ebau toggleworld §8[§7Player§8] §8- §7Editiere die Werlt Rechte eines Spielers");
+ p.sendMessage("§8/§ebau toggleworld §8[§7Player§8] §8- §7Editiere die Welt Rechte eines Spielers");
}
@Register("info")
@@ -68,12 +72,22 @@ public class BauCommand extends SWCommand {
onToggleWorld(p, user);
}
+ @Register("delmember")
+ public void delMemberCommand(Player p, SteamwarUser user) {
+
+ }
+
+ @Register("addmemebr")
+ public void addMemberCommand(Player p, String s) {
+
+ }
+
private void onToggleWE(Player p, SteamwarUser id) {
if (negativeToggleCheck(p, id)) {
return;
}
- BauweltMember target = BauweltMember.getBauMember(BauServer.getInstance().getOwnerID(), id.getId());
+ BauweltMember target = BauweltMember.getBauMember(bauServer.getOwnerID(), id.getId());
Permission.WORLDEDIT.toggle(p, target);
}
@@ -82,7 +96,7 @@ public class BauCommand extends SWCommand {
return;
}
- BauweltMember target = BauweltMember.getBauMember(BauServer.getInstance().getOwnerID(), id.getId());
+ BauweltMember target = BauweltMember.getBauMember(bauServer.getOwnerID(), id.getId());
Permission.WORLD.toggle(p, target);
}
@@ -92,7 +106,7 @@ public class BauCommand extends SWCommand {
return true;
}
- BauweltMember target = BauweltMember.getBauMember(BauServer.getInstance().getOwnerID(), id.getId());
+ BauweltMember target = BauweltMember.getBauMember(bauServer.getOwnerID(), id.getId());
if (target == null) {
p.sendMessage(BauSystem.PREFIX + "§cDer Spieler ist kein Mitglied deiner Welt!");
return true;
@@ -102,7 +116,7 @@ public class BauCommand extends SWCommand {
private boolean permissionCheck(Player p) {
- if (!BauServer.getInstance().getOwner().equals(p.getUniqueId())) {
+ if (!bauServer.getOwner().equals(p.getUniqueId())) {
p.sendMessage(BauSystem.PREFIX + "§cDies ist nicht deine Welt!");
return false;
} else {
@@ -113,7 +127,7 @@ public class BauCommand extends SWCommand {
@ClassMapper(value = SteamwarUser.class, local = true)
private TypeMapper steamwarUserTypeMapper() {
- return SWCommandUtils.createMapper(s -> BauweltMember.getMembers(BauServer.getInstance().getOwnerID())
+ return SWCommandUtils.createMapper(s -> BauweltMember.getMembers(bauServer.getOwnerID())
.stream()
.map(m -> SteamwarUser.get(m.getMemberID()))
.filter(u -> u.getUserName().equals(s))
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java
new file mode 100644
index 00000000..aa6e9546
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/Detonator.java
@@ -0,0 +1,207 @@
+/*
+ * 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.detonator;
+
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.SWUtils;
+import de.steamwar.bausystem.config.ColorConfig;
+import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
+import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
+import de.steamwar.core.VersionedRunnable;
+import lombok.experimental.UtilityClass;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.block.data.Lightable;
+import org.bukkit.block.data.Openable;
+import org.bukkit.block.data.Powerable;
+import org.bukkit.block.data.type.Switch;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@UtilityClass
+public class Detonator {
+
+ private static final Map> ENTITIES_MAP = new HashMap<>();
+ private static final Vector HALF = new Vector(0.5, 0, 0.5);
+
+ public static boolean isDetonator(ItemStack itemStack) {
+ return ItemStorage.isDetonator(itemStack);
+ }
+
+ public static void showDetonator(Player p, List locs) {
+ List vecs = locs.stream().map(Location::toVector).collect(Collectors.toList());
+ List entities = new LinkedList<>();
+ VersionedRunnable.call(new VersionedRunnable(() -> {
+ vecs.forEach(vector -> entities.add(Detonator_15.constructEntity(p.getWorld(), vector.add(HALF))));
+ }, 15));
+ entities.forEach(abstractDetonatorEntity -> abstractDetonatorEntity.display(p));
+ ENTITIES_MAP.putIfAbsent(p, entities);
+ }
+
+ public static void hideDetonator(Player p) {
+ ENTITIES_MAP.remove(p).forEach(abstractDetonatorEntity -> abstractDetonatorEntity.hide(p, true));
+ }
+
+ public static List getDetoEntities(Player p) {
+ return ENTITIES_MAP.getOrDefault(p, new ArrayList<>());
+ }
+
+ public static boolean hasActiveDetonatorShow(Player p) {
+ return ENTITIES_MAP.containsKey(p);
+ }
+
+ public static void activateDetonator(DetonatorStorage detonator) {
+ Player p = detonator.getPlayer();
+ Map> deactivate = new HashMap<>();
+ Set invalid = new HashSet<>();
+
+ for (Location location : detonator.getLocations()) {
+ Block block = location.getBlock();
+ Detoblock detoblock = getBlock(block);
+
+ if (detoblock == Detoblock.INVALID) {
+ invalid.add(location);
+ continue;
+ }
+
+ if (detoblock.isToggle()) {
+ setBlockPower(block, !getBlockPower(block));
+ updateButton(block, detoblock);
+ } else {
+ setBlockPower(block, true);
+ updateButton(block, detoblock);
+ deactivate.computeIfAbsent(detoblock.getTime(), integer -> new HashSet<>()).add(block);
+ }
+ }
+
+ int s = detonator.getLocations().size() - invalid.size();
+ SWUtils.sendToActionbar(p, ColorConfig.HIGHLIGHT.toString() + s + " Punkt" + (s > 1 ? "e" : "") + " ausgelöst");
+
+ invalid.forEach(detonator::removeLocation);
+ if (!invalid.isEmpty()) {
+ int invalidPoints = invalid.size();
+ p.sendMessage(BauSystem.PREFIX + ColorConfig.DISABLE + invalid.size() + " Punkt" + (invalidPoints > 1 ? "e" : "") + "konnte" + (invalidPoints > 1 ? "n" : "") + " nicht ausgeführt werden und wurde" + (invalidPoints > 1 ? "e" : "") + " entfernt");
+ detonator.write();
+ }
+
+ deactivate.forEach((integer, blocks1) ->
+ Bukkit.getScheduler().scheduleSyncDelayedTask(BauSystem.getInstance(), () -> blocks1.forEach(block -> {
+ setBlockPower(block, false);
+ updateButton(block, getBlock(block));
+ }), integer));
+ }
+
+ public static void updateButton(Block block, Detoblock detoblock) {
+ if (block.getBlockData() instanceof Switch) {
+ Switch sw = (Switch) block.getBlockData();
+ update(block.getRelative(sw.getFacing().getOppositeFace()));
+ } else if (detoblock == Detoblock.TRIPWIRE) {
+ update(block);
+ } else if (detoblock == Detoblock.PRESSURE_PLATE || detoblock == Detoblock.WEIGHTED_PRESSURE_PLATE) {
+ update(block.getRelative(BlockFace.DOWN));
+ } else if (detoblock == Detoblock.REDSTONETORCH) {
+ update(block.getRelative(BlockFace.UP));
+ }
+ }
+
+ private static void update(Block block) {
+ BlockData data = block.getBlockData();
+ block.setType(Material.BARRIER, true);
+ block.setBlockData(data, true);
+ }
+
+ private static void setBlockPower(Block block, boolean state) {
+ BlockData data = block.getBlockData();
+ if (data instanceof Powerable) {
+ Powerable pow = (Powerable) data;
+ pow.setPowered(state);
+ }
+ if (data instanceof Openable) {
+ Openable openable = (Openable) data;
+ openable.setOpen(state);
+ }
+ if (data instanceof Lightable) {
+ Lightable lightable = (Lightable) data;
+ lightable.setLit(state);
+ }
+ block.setBlockData(data);
+ }
+
+ private static boolean getBlockPower(Block block) {
+ BlockData data = block.getBlockData();
+ if (data instanceof Powerable) {
+ Powerable pow = (Powerable) data;
+ return pow.isPowered();
+ }
+ if (data instanceof Lightable) {
+ Lightable lightable = (Lightable) data;
+ return lightable.isLit();
+ }
+ return false;
+ }
+
+ static Detoblock getBlock(Block block) {
+ switch (block.getType()) {
+ case LEVER:
+ return Detoblock.SWITCH;
+ case ACACIA_BUTTON:
+ case BIRCH_BUTTON:
+ case DARK_OAK_BUTTON:
+ case JUNGLE_BUTTON:
+ case OAK_BUTTON:
+ case SPRUCE_BUTTON:
+ return Detoblock.WOOD_BUTTON;
+ case STONE_BUTTON:
+ return Detoblock.STONE_BUTTON;
+ case ACACIA_PRESSURE_PLATE:
+ case BIRCH_PRESSURE_PLATE:
+ case DARK_OAK_PRESSURE_PLATE:
+ case JUNGLE_PRESSURE_PLATE:
+ case OAK_PRESSURE_PLATE:
+ case SPRUCE_PRESSURE_PLATE:
+ case STONE_PRESSURE_PLATE:
+ return Detoblock.PRESSURE_PLATE;
+ case HEAVY_WEIGHTED_PRESSURE_PLATE:
+ case LIGHT_WEIGHTED_PRESSURE_PLATE:
+ return Detoblock.WEIGHTED_PRESSURE_PLATE;
+ case TRIPWIRE:
+ return Detoblock.TRIPWIRE;
+ case NOTE_BLOCK:
+ return Detoblock.NOTEBLOCK;
+ case REDSTONE_TORCH:
+ case REDSTONE_WALL_TORCH:
+ return Detoblock.REDSTONETORCH;
+ default:
+ if (block.getBlockData() instanceof Powerable) {
+ return Detoblock.POWERABLE;
+ } else {
+ return Detoblock.INVALID;
+ }
+ }
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorCommand.java
new file mode 100644
index 00000000..246d80fa
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorCommand.java
@@ -0,0 +1,84 @@
+/*
+ * 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.detonator;
+
+import de.steamwar.bausystem.SWUtils;
+import de.steamwar.bausystem.config.ColorConfig;
+import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
+import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
+import de.steamwar.bausystem.linkage.LinkageType;
+import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.command.SWCommand;
+import lombok.Getter;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.Arrays;
+
+@Linked(LinkageType.COMMAND)
+public class DetonatorCommand extends SWCommand {
+
+ @Getter
+ private static final ItemStack WAND;
+
+ static {
+ WAND = new ItemStack(Material.BLAZE_ROD);
+ ItemStorage.setDetonator(WAND);
+ ItemMeta meta = WAND.getItemMeta();
+
+ meta.setDisplayName(ColorConfig.HIGHLIGHT + "Fernzünder");
+ meta.setLore(Arrays.asList(ColorConfig.HIGHLIGHT + "Links Klick " + ColorConfig.OTHER + "- " + ColorConfig.BASE + "Setzte einen Punkt zum Aktivieren",
+ ColorConfig.HIGHLIGHT + "Links Klick + Shift " + ColorConfig.OTHER + "- " + ColorConfig.BASE + "Füge einen Punkt hinzu",
+ ColorConfig.HIGHLIGHT + "Rechts Klick " + ColorConfig.OTHER + "- " + ColorConfig.BASE + "Löse alle Punkte aus"));
+
+ WAND.setItemMeta(meta);
+ }
+
+ protected DetonatorCommand() {
+ super("detonator", "dt");
+ }
+
+ @Register(help = true)
+ public void genericHelp(Player p, String... args) {
+ p.sendMessage(ColorConfig.BASE + "---===(" + ColorConfig.HIGHLIGHT + "Fernzünder" + ColorConfig.BASE + ")===---");
+ p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "detonator wand " + ColorConfig.OTHER + "-" + ColorConfig.BASE + " Gibt den Fernzünder");
+ p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "detonator click " + ColorConfig.OTHER + "-" + ColorConfig.BASE + " Aktiviere einen Fernzünder (Haupthand -> Hotbar -> Inventar)");
+ p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "detonator clear " + ColorConfig.OTHER + "-" + ColorConfig.BASE + " Cleare einen Fernzünder");
+ }
+
+ @Register("wand")
+ public void giveWand(Player p) {
+ SWUtils.giveItemToPlayer(p, getWAND());
+ }
+
+ @Register("click")
+ public void clickDetonator(Player p) {
+ Detonator.activateDetonator(new ItemStorage(p));
+ }
+
+ @Register("clear")
+ public void clearDetonator(Player p) {
+ DetonatorStorage storage = new ItemStorage(p);
+ storage.clear();
+ storage.write();
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java
new file mode 100644
index 00000000..593708d4
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/DetonatorListener.java
@@ -0,0 +1,158 @@
+/*
+ * 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.detonator;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.PacketAdapter;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.events.PacketEvent;
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.SWUtils;
+import de.steamwar.bausystem.config.ColorConfig;
+import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
+import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
+import de.steamwar.bausystem.linkage.LinkageType;
+import de.steamwar.bausystem.linkage.Linked;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerItemHeldEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerSwapHandItemsEvent;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Linked(LinkageType.LISTENER)
+public class DetonatorListener implements Listener {
+
+ private static final Set HAS_UPDATED = new HashSet<>();
+
+ public DetonatorListener() {
+ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(BauSystem.getInstance(), PacketType.Play.Client.USE_ENTITY) {
+ @Override
+ public void onPacketReceiving(PacketEvent event) {
+ List entities = new ArrayList<>(Detonator.getDetoEntities(event.getPlayer()));
+ if (entities.isEmpty()) {
+ return;
+ }
+
+ PacketContainer container = event.getPacket();
+ int entityId = container.getIntegers().read(0);
+ entities.removeIf(abstractDetonatorEntity -> abstractDetonatorEntity.getId() != entityId);
+
+ if (entities.isEmpty()) {
+ return;
+ }
+ AbstractDetonatorEntity entity = entities.get(0);
+ Location location = entity.getBukkitEntity().getLocation().getBlock().getLocation();
+ addLocationToDetonator(location, event.getPlayer());
+ HAS_UPDATED.add(event.getPlayer());
+ event.setCancelled(true);
+ }
+ });
+ }
+
+ private static void addLocationToDetonator(Location location, Player p) {
+ Detoblock detoblock = Detonator.getBlock(location.getBlock());
+ if (detoblock == Detoblock.INVALID) {
+ SWUtils.sendToActionbar(p, ColorConfig.HIGHLIGHT + "Der Block konnte nicht hinzugefügt werden");
+ return;
+ }
+ DetonatorStorage detonator = new ItemStorage(p);
+ if (!p.isSneaking()) {
+ detonator.clear();
+ }
+ if (detonator.getLocations().contains(location)) {
+ detonator.removeLocation(location);
+ SWUtils.sendToActionbar(p, ColorConfig.HIGHLIGHT + detoblock.getName() + " entfernt");
+ } else {
+ detonator.addLocation(location);
+ SWUtils.sendToActionbar(p, ColorConfig.HIGHLIGHT + detoblock.getName() + " hinzugefügt");
+ }
+ detonator.write();
+ }
+
+ @EventHandler
+ public void onBlockBreak(BlockBreakEvent event) {
+ Player p = event.getPlayer();
+ if (Detonator.isDetonator(p.getInventory().getItemInMainHand())) {
+ event.setCancelled(true);
+ addLocationToDetonator(event.getBlock().getLocation(), p);
+ HAS_UPDATED.add(event.getPlayer());
+ }
+ }
+
+ @EventHandler
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (!Detonator.isDetonator(event.getItem())) {
+ return;
+ }
+
+ if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) {
+ event.setCancelled(true);
+ DetonatorStorage detonator = new ItemStorage(event.getPlayer());
+ Detonator.activateDetonator(detonator);
+ HAS_UPDATED.add(event.getPlayer());
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onPlayerMove(PlayerMoveEvent event) {
+ if (!Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
+ if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
+ Detonator.hideDetonator(event.getPlayer());
+ }
+ } else {
+ if (!Detonator.hasActiveDetonatorShow(event.getPlayer())) {
+ Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
+ }
+ }
+
+ if (HAS_UPDATED.contains(event.getPlayer())) {
+ HAS_UPDATED.remove(event.getPlayer());
+ if (Detonator.hasActiveDetonatorShow(event.getPlayer())) {
+ Detonator.hideDetonator(event.getPlayer());
+ Detonator.showDetonator(event.getPlayer(), new ItemStorage(event.getPlayer()).getLocations());
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlayerItemHeld(PlayerItemHeldEvent event) {
+ if (Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
+ HAS_UPDATED.add(event.getPlayer());
+ }
+ }
+
+ @EventHandler
+ public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
+ if (Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem())) {
+ HAS_UPDATED.add(event.getPlayer());
+ }
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/DetonatorStorage.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/DetonatorStorage.java
new file mode 100644
index 00000000..104abf29
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/DetonatorStorage.java
@@ -0,0 +1,40 @@
+/*
+ * 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.detonator.storage;
+
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+
+public interface DetonatorStorage {
+
+ void addLocation(Location location);
+
+ List getLocations();
+
+ void removeLocation(Location location);
+
+ void clear();
+
+ void write();
+
+ Player getPlayer();
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/ItemStorage.java b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/ItemStorage.java
new file mode 100644
index 00000000..dd9a14bf
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/detonator/storage/ItemStorage.java
@@ -0,0 +1,184 @@
+/*
+ * 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.detonator.storage;
+
+import de.steamwar.bausystem.SWUtils;
+import lombok.Getter;
+import org.bukkit.Location;
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.IntFunction;
+
+public class ItemStorage implements DetonatorStorage {
+
+ private static final NamespacedKey DETO_KEY = SWUtils.getNamespaceKey("deto");
+ private static final NamespacedKey SLOT_KEY = SWUtils.getNamespaceKey("slots");
+ private static final IntFunction DETOLOCATION_BUILDER = integer -> SWUtils.getNamespaceKey("deto_loc_" + integer);
+ @Getter
+ private final Player p;
+ private final List locs;
+ private int slot;
+ private ItemStack itemStack;
+
+ public ItemStorage(Player p) {
+ this.p = p;
+ if (isDetonator(p.getInventory().getItemInMainHand())) {
+ slot = p.getInventory().getHeldItemSlot();
+ itemStack = p.getInventory().getItemInMainHand();
+ } else {
+ ItemStack[] inv = p.getInventory().getContents();
+ for (int i = 0; i < inv.length; i++) {
+ if (isDetonator(inv[i])) {
+ slot = i;
+ itemStack = inv[i];
+ break;
+ }
+ }
+ }
+ locs = read();
+ }
+
+ public static ItemStack setDetonator(ItemStack item) {
+ ItemMeta meta = item.getItemMeta();
+ if (meta == null) {
+ return item;
+ }
+ PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
+ dataContainer.set(DETO_KEY, PersistentDataType.BYTE, (byte) 1);
+ dataContainer.set(SLOT_KEY, PersistentDataType.INTEGER, 0);
+ item.setItemMeta(meta);
+ return item;
+ }
+
+ public static boolean isDetonator(ItemStack item) {
+ if (item == null) {
+ return false;
+ }
+ ItemMeta meta = item.getItemMeta();
+ if (meta == null) {
+ return false;
+ }
+ PersistentDataContainer container = meta.getPersistentDataContainer();
+ return container.has(DETO_KEY, PersistentDataType.BYTE) && container.has(SLOT_KEY, PersistentDataType.INTEGER);
+ }
+
+ @Override
+ public void addLocation(Location location) {
+ locs.add(location);
+ }
+
+ @Override
+ public List getLocations() {
+ return locs;
+ }
+
+ @Override
+ public void removeLocation(Location location) {
+ locs.remove(location);
+ }
+
+ @Override
+ public void clear() {
+ internalClear();
+ locs.clear();
+ apply();
+ }
+
+ @Override
+ public void write() {
+ write(locs);
+ }
+
+ @Override
+ public Player getPlayer() {
+ return p;
+ }
+
+ private List read() {
+ List tempLocs = new LinkedList<>();
+
+ ItemMeta meta = itemStack.getItemMeta();
+ PersistentDataContainer container = meta.getPersistentDataContainer();
+
+ int length = length();
+ for (int i = 0; i < length; i++) {
+ NamespacedKey key = DETOLOCATION_BUILDER.apply(i);
+ int[] loc = container.get(key, PersistentDataType.INTEGER_ARRAY);
+ tempLocs.add(new Location(p.getWorld(), loc[0], loc[1], loc[2]));
+ }
+
+ return tempLocs;
+ }
+
+ private int length() {
+ ItemMeta meta = itemStack.getItemMeta();
+ PersistentDataContainer container = meta.getPersistentDataContainer();
+ return container.get(SLOT_KEY, PersistentDataType.INTEGER);
+ }
+
+ private void internalClear() {
+ ItemMeta meta = itemStack.getItemMeta();
+ PersistentDataContainer container = meta.getPersistentDataContainer();
+
+ int length = length();
+ for (int i = 0; i < length; i++) {
+ NamespacedKey key = DETOLOCATION_BUILDER.apply(i);
+ container.remove(key);
+ }
+
+ container.set(SLOT_KEY, PersistentDataType.INTEGER, 0);
+
+ itemStack.setItemMeta(meta);
+ }
+
+ private void write(List locs) {
+ internalClear();
+ ItemMeta meta = itemStack.getItemMeta();
+ PersistentDataContainer container = meta.getPersistentDataContainer();
+
+ int i = 0;
+ for (Location loc : locs) {
+ NamespacedKey key = DETOLOCATION_BUILDER.apply(i);
+ int[] slotLoc = new int[]{
+ loc.getBlockX(),
+ loc.getBlockY(),
+ loc.getBlockZ()
+ };
+ container.set(key, PersistentDataType.INTEGER_ARRAY, slotLoc);
+ i++;
+ }
+
+ container.set(SLOT_KEY, PersistentDataType.INTEGER, i);
+
+ itemStack.setItemMeta(meta);
+ apply();
+ }
+
+ private void apply() {
+ p.getInventory().setItem(slot, itemStack);
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/ClearCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/ClearCommand.java
new file mode 100644
index 00000000..b2a29f0f
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/ClearCommand.java
@@ -0,0 +1,73 @@
+/*
+ * 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.other;
+
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.Permission;
+import de.steamwar.bausystem.linkage.LinkageType;
+import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.command.SWCommand;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+@Linked(LinkageType.COMMAND)
+public class ClearCommand extends SWCommand {
+
+ public ClearCommand() {
+ super("clear");
+ }
+
+ @Register(help = true)
+ public void genericHelp(Player p, String... args) {
+ p.sendMessage("§8/§eclear §8- §7Leere dein Inventar");
+ p.sendMessage("§8/§ebau clear §8[§7Player§8] §8- §7Leere ein Spieler Inventar");
+ }
+
+ @Register
+ public void genericClearCommand(Player p) {
+ clear(p);
+ p.sendMessage(BauSystem.PREFIX + "Dein Inventar wurde geleert.");
+ }
+
+ @Register
+ public void clearPlayerCommand(Player p, Player target) {
+ if (!permissionCheck(p)) return;
+ clear(target);
+ target.sendMessage(BauSystem.PREFIX + "Dein Inventar wurde von" + p.getDisplayName() + " §7geleert.");
+ p.sendMessage(BauSystem.PREFIX + "Das Inventar von " + target.getDisplayName() + " §7wurde geleert.");
+ }
+
+ private boolean permissionCheck(Player player) {
+ if (!Permission.hasPermission(player, Permission.WORLD)) {
+ player.sendMessage(BauSystem.PREFIX + "$cDu darfst hier keine fremden Inventare leeren.");
+ return false;
+ }
+ return true;
+ }
+
+ private void clear(Player player) {
+ player.getInventory().clear();
+ player.getInventory().setHelmet(new ItemStack(Material.AIR));
+ player.getInventory().setChestplate(new ItemStack(Material.AIR));
+ player.getInventory().setLeggings(new ItemStack(Material.AIR));
+ player.getInventory().setBoots(new ItemStack(Material.AIR));
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/DeclutterCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/DeclutterCommand.java
new file mode 100644
index 00000000..6eb10fee
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/DeclutterCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.other;
+
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.config.ColorConfig;
+import de.steamwar.bausystem.linkage.LinkageType;
+import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.command.SWCommand;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Linked(LinkageType.COMMAND)
+public class DeclutterCommand extends SWCommand {
+
+ public DeclutterCommand() {
+ super("declutter", "cleanup");
+ }
+
+ @Register(help = true)
+ public void genericHelp(Player p, String... args) {
+ p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "declutter " + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Räume dein Inventar auf");
+ }
+
+ @Register
+ public void genericCommand(Player p) {
+ Inventory inventory = p.getInventory();
+ Set containedItems = new HashSet<>();
+ inventory.forEach(itemStack -> {
+ if (itemStack == null) {
+ return;
+ }
+
+ if (containedItems.stream().anyMatch(itemStack::isSimilar)) {
+ itemStack.setAmount(0);
+ return;
+ }
+
+ if (itemStack.getAmount() > 1) {
+ itemStack.setAmount(1);
+ }
+
+ containedItems.add(itemStack);
+ });
+
+ p.sendMessage(BauSystem.PREFIX + ColorConfig.ENABLE + "Dein Inventar wurde aufgeräumt.");
+ }
+
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java
index 1b939b91..c718d6c8 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java
@@ -29,7 +29,7 @@ import de.steamwar.bausystem.linkage.Linked;
import de.steamwar.command.SWCommand;
import org.bukkit.entity.Player;
-@Linked(LinkageType.LISTENER)
+@Linked(LinkageType.COMMAND)
public class SimulatorCommand extends SWCommand {
public SimulatorCommand() {
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java
index ee8ab535..e504b182 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulator.java
@@ -22,6 +22,8 @@
package de.steamwar.bausystem.features.simulator;
import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.SWUtils;
+import de.steamwar.bausystem.config.ColorConfig;
import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode;
import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.inventory.SWInventory;
@@ -94,7 +96,7 @@ public class TNTSimulator {
cursor = SimulatorEntityShowMode.createEntity(player, entity.position, false);
cursor.display(player);
- player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText("§ePosition bearbeiten"));
+ SWUtils.sendToActionbar(player, ColorConfig.HIGHLIGHT + "Position bearbeiten");
return;
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/show/SimulatorEntityShowMode.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/show/SimulatorEntityShowMode.java
index 8a2ae390..be6034a3 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/show/SimulatorEntityShowMode.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/show/SimulatorEntityShowMode.java
@@ -48,8 +48,8 @@ public class SimulatorEntityShowMode implements ShowMode {
entity.display(player);
}
- public static AbstractSimulatorEntity createEntity(Player player, Vector position, boolean tnt) {
- return VersionedCallable.call(new VersionedCallable<>(() -> Simulator_15.create(player.getWorld(), position, tnt), 15));
+ public static AbstractSimulatorEntity createEntity(Player player, Vector position, boolean highlight) {
+ return VersionedCallable.call(new VersionedCallable<>(() -> Simulator_15.create(player.getWorld(), position, highlight), 15));
}
@Override
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java
index 61429e55..fcf9ed74 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java
@@ -28,8 +28,6 @@ import de.steamwar.bausystem.linkage.Linked;
import de.steamwar.command.SWCommand;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.TypeMapper;
-import lombok.AccessLevel;
-import lombok.Getter;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
@@ -43,14 +41,10 @@ import java.util.List;
@Linked(LinkageType.ENABLE_LINK)
public class TPSLimitCommand extends SWCommand implements Enable {
- @Getter(AccessLevel.PACKAGE)
- private static TPSLimitCommand instance = null;
-
private final List tabCompletions = new ArrayList<>(Arrays.asList("0,5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"));
public TPSLimitCommand() {
super("tpslimit");
- instance = this;
if (TPSWarpUtils.isWarpAllowed()) {
for (int i = 20; i <= 60; i += 5) {
tabCompletions.add(i + "");
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java
index fda628cf..44d0fcd3 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceCommand.java
@@ -31,8 +31,15 @@ import de.steamwar.bausystem.features.tracer.show.mode.TraceEntityShowMode;
import de.steamwar.bausystem.linkage.LinkageType;
import de.steamwar.bausystem.linkage.Linked;
import de.steamwar.command.SWCommand;
+import de.steamwar.command.SWCommandUtils;
+import de.steamwar.command.TypeMapper;
import org.bukkit.entity.Player;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
@Linked(LinkageType.COMMAND)
public class TraceCommand extends SWCommand {
@@ -40,6 +47,40 @@ public class TraceCommand extends SWCommand {
super("trace", "trail");
}
+ @ClassMapper(value = ShowModeParameterType.class, local = true)
+ public TypeMapper showModeParameterTypesTypeMapper() {
+ Map showModeParameterTypesMap = new HashMap<>();
+ showModeParameterTypesMap.put("-water", ShowModeParameterType.WATER);
+
+ showModeParameterTypesMap.put("-interpolatey", ShowModeParameterType.INTERPOLATE_Y);
+ showModeParameterTypesMap.put("-interpolate-y", ShowModeParameterType.INTERPOLATE_Y);
+ showModeParameterTypesMap.put("-interpolate_y", ShowModeParameterType.INTERPOLATE_Y);
+ showModeParameterTypesMap.put("-y", ShowModeParameterType.INTERPOLATE_Y);
+
+ showModeParameterTypesMap.put("-interpolatex", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate-x", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate_x", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-x", ShowModeParameterType.INTERPOLATE_XZ);
+
+ showModeParameterTypesMap.put("-interpolatez", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate-z", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate_z", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-z", ShowModeParameterType.INTERPOLATE_XZ);
+
+ showModeParameterTypesMap.put("-interpolatexz", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate-xz", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-interpolate_xz", ShowModeParameterType.INTERPOLATE_XZ);
+ showModeParameterTypesMap.put("-xz", ShowModeParameterType.INTERPOLATE_XZ);
+
+ showModeParameterTypesMap.put("-advanced", ShowModeParameterType.ADVANCED);
+ showModeParameterTypesMap.put("-a", ShowModeParameterType.ADVANCED);
+ showModeParameterTypesMap.put("advanced", ShowModeParameterType.ADVANCED);
+ showModeParameterTypesMap.put("a", ShowModeParameterType.ADVANCED);
+
+ List tabCompletes = new ArrayList<>(showModeParameterTypesMap.keySet());
+ return SWCommandUtils.createMapper(s -> showModeParameterTypesMap.getOrDefault(s, null), s -> tabCompletes);
+ }
+
@Register(help = true)
public void genericHelp(Player p, String... args) {
p.sendMessage(ColorConfig.OTHER + "/" + ColorConfig.HIGHLIGHT + "trace start" + ColorConfig.OTHER + " - " + ColorConfig.BASE + "Startet die Aufnahme aller TNT-Positionen");
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java
index dd806a31..922850a1 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkageUtils.java
@@ -27,6 +27,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.logging.Level;
@@ -35,10 +36,12 @@ import java.util.logging.Level;
public class LinkageUtils {
private Map, Object> objectMap = new HashMap<>();
+ private Set fieldsToLink = new HashSet<>();
public void link() {
internalLinkOrUnlink(false, Linked.class);
internalLinkOrUnlink(false, Linked.Linkages.class);
+ internalLinkFields();
}
public void unlink() {
@@ -64,6 +67,23 @@ public class LinkageUtils {
}
}
+ private void internalLinkFields() {
+ for (Field field : fieldsToLink) {
+ LinkedInstance linkedInstance = field.getDeclaredAnnotation(LinkedInstance.class);
+ if (linkedInstance == null) {
+ continue;
+ }
+ Object object = objectMap.getOrDefault(linkedInstance.value(), null);
+ Object source = objectMap.getOrDefault(field.getDeclaringClass(), null);
+ try {
+ field.setAccessible(true);
+ field.set(source, object);
+ } catch (IllegalAccessException e) {
+ // Ignored
+ }
+ }
+ }
+
private void linkOrUnlink(Class> clazz, boolean unlink) {
Linked[] linkages = clazz.getDeclaredAnnotationsByType(Linked.class);
if (linkages.length == 0) {
@@ -87,8 +107,27 @@ public class LinkageUtils {
}
linkageTypeList.sort(Comparator.comparingInt(LinkageType::getOrder));
- Object object = objectMap.computeIfAbsent(clazz, LinkageUtils::constructInstance);
- linkageTypeList.forEach(linkageType -> linkageType.getLinkageConsumer().accept(object));
+ if (unlink) {
+ Object object = objectMap.remove(clazz);
+ if (object == null) {
+ return;
+ }
+ linkageTypeList.forEach(linkageType -> linkageType.getLinkageConsumer().accept(object));
+ } else {
+ Object object = objectMap.computeIfAbsent(clazz, LinkageUtils::constructInstance);
+ linkageTypeList.forEach(linkageType -> linkageType.getLinkageConsumer().accept(object));
+
+ for (Field field : clazz.getDeclaredFields()) {
+ LinkedInstance linkedInstance = field.getDeclaredAnnotation(LinkedInstance.class);
+ if (linkedInstance == null) {
+ continue;
+ }
+ if (!field.getType().isAssignableFrom(linkedInstance.value())) {
+ continue;
+ }
+ fieldsToLink.add(field);
+ }
+ }
}
private Object constructInstance(Class> clazz) {
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkedInstance.java b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkedInstance.java
new file mode 100644
index 00000000..7cfa2857
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/linkage/LinkedInstance.java
@@ -0,0 +1,31 @@
+/*
+ * 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.linkage;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface LinkedInstance {
+ Class> value();
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/FlagStorage.java b/BauSystem_Main/src/de/steamwar/bausystem/region/FlagStorage.java
index 8efdb4eb..dbd30203 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/region/FlagStorage.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/region/FlagStorage.java
@@ -38,7 +38,11 @@ public class FlagStorage {
}
public boolean set(final Flag flagType, final Flag.Value> value) {
- return flags.put(flagType, value) != value;
+ if (flags.put(flagType, value) != value) {
+ writeChangedKey(flagType, value);
+ return true;
+ }
+ return false;
}
@SuppressWarnings("unchecked")
@@ -52,4 +56,8 @@ public class FlagStorage {
flags.put(flag, flagValue == null ? flag.getDefaultValue() : flag.getFlagValueOf(flagValue.getAsString().toUpperCase()));
}
}
+
+ private void writeChangedKey(Flag flag, Flag.Value> value) {
+ jsonObject.add(flag.name().toLowerCase(), new JsonPrimitive(value.getValue().getName()));
+ }
}
\ No newline at end of file
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/GlobalRegion.java b/BauSystem_Main/src/de/steamwar/bausystem/region/GlobalRegion.java
new file mode 100644
index 00000000..06f0e25b
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/region/GlobalRegion.java
@@ -0,0 +1,23 @@
+/*
+ * 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.region;
+
+public class GlobalRegion {
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java
new file mode 100644
index 00000000..3f04a9f8
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Prototype.java
@@ -0,0 +1,23 @@
+/*
+ * 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.region;
+
+public class Prototype {
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java
new file mode 100644
index 00000000..c34946cb
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Region.java
@@ -0,0 +1,23 @@
+/*
+ * 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.region;
+
+public class Region {
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/ChatMessageBuilder.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/ChatMessageBuilder.java
new file mode 100644
index 00000000..f8c819f4
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/ChatMessageBuilder.java
@@ -0,0 +1,88 @@
+/*
+ * 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.utils;
+
+import de.steamwar.bausystem.config.ColorConfig;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ChatMessageBuilder {
+
+ private List messages = new ArrayList<>();
+ private String[] strings = new String[0];
+
+ public ChatMessageBuilder() {
+ messages.add(new StringBuilder());
+ }
+
+ public ChatMessageBuilder highlight(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.HIGHLIGHT).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder base(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.BASE).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder other(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.OTHER).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder enable(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.ENABLE).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder disable(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.DISABLE).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder error(String s) {
+ messages.get(messages.size() - 1).append(ColorConfig.ERROR).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder append(String s) {
+ messages.get(messages.size() - 1).append(s);
+ return this;
+ }
+
+ public ChatMessageBuilder newLine() {
+ messages.add(new StringBuilder());
+ return this;
+ }
+
+ public ChatMessageBuilder finish() {
+ strings = messages.stream().map(StringBuilder::toString).toArray(String[]::new);
+ return this;
+ }
+
+ public void send(Player player) {
+ for (String message : strings) {
+ player.sendMessage(message);
+ }
+ }
+
+}