Add BauSystem module

Fix ci java version
Fix LinkageProcessor
This commit is contained in:
2024-08-05 13:28:50 +02:00
parent 41d31e6c9c
commit 3366a30b0c
526 changed files with 43550 additions and 149479 deletions
+58
View File
@@ -0,0 +1,58 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
compileOnly(project(":BauSystem:BauSystem_Main"))
compileOnly(project(":SpigotCore"))
compileOnly("de.steamwar:spigot:1.15")
compileOnly("de.steamwar:worldedit:1.15")
}
@@ -0,0 +1,243 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Mask2D;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockTypes;
import de.steamwar.bausystem.region.Point;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import javax.annotation.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiPredicate;
import java.util.logging.Level;
public class FlatteningWrapper15 implements FlatteningWrapper {
@Override
public boolean isNoBook(ItemStack item) {
return item.getType() != Material.WRITABLE_BOOK && item.getType() != Material.WRITTEN_BOOK;
}
private static final Set<Material> unpushable = new HashSet<>(Arrays.asList(Material.BARRIER, Material.BEACON, Material.COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.ENCHANTING_TABLE, Material.END_GATEWAY, Material.END_PORTAL, Material.ENDER_CHEST, Material.GRINDSTONE, Material.JIGSAW, Material.JUKEBOX, Material.NETHER_PORTAL, Material.OBSIDIAN, Material.STRUCTURE_VOID, Material.BARREL, Material.BEEHIVE, Material.BEE_NEST, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CHEST, Material.DAYLIGHT_DETECTOR, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.LECTERN, Material.SMOKER, Material.TRAPPED_CHEST));
// TODO: FLOWER
private static final Set<Material> breaking = new HashSet<>(Arrays.asList(Material.BAMBOO, Material.CACTUS, Material.CAKE, Material.CARVED_PUMPKIN, Material.CHORUS_FLOWER, Material.CHORUS_PLANT, Material.COBWEB, Material.COCOA, Material.DRAGON_EGG, Material.FIRE, Material.FLOWER_POT, Material.JACK_O_LANTERN, Material.LADDER, Material.LAVA, Material.LAVA, Material.LEVER, Material.LILY_PAD, Material.MELON, Material.NETHER_WART, Material.PUMPKIN, Material.COMPARATOR, Material.REDSTONE_WIRE, Material.REPEATER, Material.TORCH, Material.STRUCTURE_VOID, Material.SCAFFOLDING, Material.SEA_PICKLE, Material.SNOW, Material.SUGAR_CANE, Material.TORCH, Material.TRIPWIRE, Material.TRIPWIRE_HOOK, Material.TURTLE_EGG, Material.VINE, Material.WATER, Material.WHEAT));
@Override
public boolean isUnpusheable(Material material) {
if (unpushable.contains(material)) {
return true;
}
String name = material.name();
return name.contains("BANNER") || name.contains("SIGN");
}
@Override
public boolean isBreakingOnPush(Material material) {
if (breaking.contains(material)) {
return true;
}
String name = material.name();
return name.contains("BED") || name.contains("BUTTON") || name.contains("CARPET") || (name.contains("DOOR") && !name.contains("TRAPDOOR")) || name.contains("HEAD") || name.contains("LEAVES") || name.contains("MUSHROOM") || name.contains("PRESSURE_PLATE") || name.contains("SHULKER_BOX");
}
@Override
public boolean isWorldEditCommand(String command) {
if (command.startsWith("/")) {
command = command.replaceFirst("/", "");
}
command = command.toLowerCase();
return WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getCommandManager().containsCommand(command);
}
private static final WorldEditPlugin WORLDEDIT_PLUGIN = Objects.requireNonNull((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"));
private static final World BUKKITWORLD = new BukkitWorld(Bukkit.getWorlds().get(0));
@Override
public void setSelection(Player p, Point minPoint, Point maxPoint) {
WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, toBlockVector3(minPoint), toBlockVector3(maxPoint)));
}
@Override
public Clipboard loadSchematic(File file) {
Clipboard clipboard;
try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) {
clipboard = reader.read();
} catch (NullPointerException | IOException e) {
throw new SecurityException("Bausystem schematic not found", e);
}
return clipboard;
}
@Override
public EditSession paste(PasteBuilder pasteBuilder) {
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) {
Clipboard clipboard = pasteBuilder.getClipboard();
if (!pasteBuilder.getMappers().isEmpty()) {
BlockVector3 minimum = clipboard.getRegion().getMinimumPoint();
for (int x = 0; x < clipboard.getDimensions().getX(); x++) {
for (int y = 0; y < clipboard.getDimensions().getY(); y++) {
for (int z = 0; z < clipboard.getDimensions().getZ(); z++) {
BlockVector3 pos = minimum.add(x, y, z);
pasteBuilder.getMappers().forEach(mapper -> mapper.accept(clipboard, pos));
}
}
}
}
AtomicReference<BlockVector3> pastePoint = new AtomicReference<>();
if (!pasteBuilder.getPredicates().isEmpty()) {
e.setMask(new Mask() {
@Override
public boolean test(BlockVector3 blockVector3) {
BaseBlock block = clipboard.getFullBlock(blockVector3.subtract(pastePoint.get()).add(clipboard.getRegion().getMinimumPoint()));
String blockName = block.getBlockType().toString().toLowerCase();
for (BiPredicate<BaseBlock, String> predicate : pasteBuilder.getPredicates()) {
if (!predicate.test(block, blockName)) return false;
}
return true;
}
public Mask copy() {
return this;
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
});
}
ClipboardHolder ch = new ClipboardHolder(clipboard);
BlockVector3 dimensions = clipboard.getDimensions();
BlockVector3 v = BlockVector3.at(pasteBuilder.getPastPoint().getX(), pasteBuilder.getPastPoint().getY(), pasteBuilder.getPastPoint().getZ());
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
if (pasteBuilder.isRotate()) {
ch.setTransform(new AffineTransform().rotateY(180));
v = v.add(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset.multiply(-1, 1, -1)).subtract(0, 0, 1);
} else {
v = v.subtract(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset);
}
pastePoint.set(v);
if (pasteBuilder.isReset()) {
e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint())), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock());
if (pasteBuilder.getWaterLevel() != 0) {
e.setBlocks(new CuboidRegion(toBlockVector3(pasteBuilder.getMinPoint()), toBlockVector3(pasteBuilder.getMaxPoint()).withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock());
}
}
Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build());
return e;
} catch (WorldEditException e) {
throw new SecurityException(e.getMessage(), e);
}
}
@Override
public Clipboard copy(Point minPoint, Point maxPoint, Point copyPoint) {
BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0));
CuboidRegion region = new CuboidRegion(bukkitWorld, toBlockVector3(minPoint), toBlockVector3(maxPoint));
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(bukkitWorld, -1)) {
ForwardExtentCopy copy = new ForwardExtentCopy(
e, region, clipboard, region.getMinimumPoint()
);
copy.setCopyingEntities(false);
copy.setCopyingBiomes(false);
Operations.complete(copy);
clipboard.setOrigin(toBlockVector3(copyPoint));
return clipboard;
} catch (WorldEditException e) {
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
return null;
}
}
@Override
public boolean backup(Point minPoint, Point maxPoint, File file) {
Clipboard clipboard = copy(minPoint, maxPoint, minPoint);
try (ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) {
writer.write(clipboard);
return true;
} catch (IOException e) {
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
return false;
}
}
private BlockVector3 toBlockVector3(Point point) {
return BlockVector3.at(point.getX(), point.getY(), point.getZ());
}
@Override
public boolean inWater(org.bukkit.World world, Vector tntPosition) {
Block block = world.getBlockAt(tntPosition.getBlockX(), tntPosition.getBlockY(), tntPosition.getBlockZ());
if (block.getType() == Material.WATER)
return true;
BlockData data = block.getBlockData();
if (!(data instanceof Waterlogged))
return false;
return ((Waterlogged) data).isWaterlogged();
}
}
@@ -0,0 +1,135 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.bausystem.features.util.NoClipCommand;
import net.minecraft.server.v1_15_R1.*;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongSupplier;
public class NMSWrapper15 implements NMSWrapper {
private static final Reflection.FieldAccessor<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
@Override
@SuppressWarnings("deprecation")
public void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().playerInteractManager, EnumGamemode.getById(gameMode.getValue()));
}
@Override
public void setSlotToItemStack(Player player, Object o) {
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
int index = packetPlayInSetCreativeSlot.b();
if (index >= 36 && index <= 44) {
index -= 36;
} else if (index > 44) {
index -= 5;
} else if (index <= 8) {
index = index - 8 + 36;
}
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.getItemStack()));
if (index < 9) player.getInventory().setHeldItemSlot(index);
player.updateInventory();
}
private static final Reflection.FieldAccessor<Integer> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, int.class, 0);
@Override
public void setGameStateChangeReason(Object packet) {
gameStateChangeReason.set(packet, 3);
}
@Override
public void setPlayerBuildAbilities(Player player) {
((CraftPlayer) player).getHandle().abilities.mayBuild = true;
((CraftPlayer) player).getHandle().abilities.canInstantlyBuild = true;
}
@Override
public Material pathMaterial() {
return Material.GRASS_PATH;
}
private static final int threshold = 2048;
@Override
public boolean checkItemStack(ItemStack item) {
net.minecraft.server.v1_15_R1.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
NBTTagCompound tag = nmsItem.getTag();
if (tag != null && tag.hasKey("BlockEntityTag")) {
NBTTagCompound blockTag = tag.getCompound("BlockEntityTag");
if (blockTag.hasKey("Items")) {
return drillDown(blockTag.getList("Items", 10), 0, 0) > threshold;
}
}
return false;
}
private int drillDown(NBTTagList items, int layer, int start) {
if (layer > 2) return start + threshold;
int invalid = start;
for (NBTBase nbtBase : items) {
if (!(nbtBase instanceof NBTTagCompound))
continue;
NBTTagCompound slot = (NBTTagCompound) nbtBase;
if (slot.hasKey("tag")) {
invalid += slot.getByte("Count");
NBTTagCompound iTag = slot.getCompound("tag");
if (iTag.hasKey("BlockEntityTag")) {
NBTTagCompound blockTag = iTag.getCompound("BlockEntityTag");
if (blockTag.hasKey("Items")) {
invalid = drillDown(blockTag.getList("Items", 10), layer + 1, invalid);
}
}
}
if (invalid > threshold)
break;
}
return invalid;
}
private final Class<?> explosionPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
private final Reflection.FieldAccessor<Double> a = Reflection.getField(explosionPacket, double.class, 0);
private final Reflection.FieldAccessor<Double> b = Reflection.getField(explosionPacket, double.class, 1);
private final Reflection.FieldAccessor<Double> c = Reflection.getField(explosionPacket, double.class, 2);
private final Reflection.FieldAccessor<Float> d = Reflection.getField(explosionPacket, float.class, 0);
private final Reflection.FieldAccessor<List> e = Reflection.getField(explosionPacket, List.class, 0);
@Override
public Object resetExplosionKnockback(Object packet) {
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), Vec3D.a);
}
}
@@ -0,0 +1,43 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import org.bukkit.Material;
public class PlaceItemWrapper15 implements PlaceItemWrapper {
public PlaceItemWrapper15() {
for (Material material : Material.values()) {
if (!material.isBlock()) continue;
if (material.isLegacy()) continue;
String nonWall = material.name().replace("_WALL_", "").replace("WALL_", "").replace("_WALL", "");
try {
Material nonWallMaterial = Material.valueOf(nonWall);
if (nonWallMaterial != material && nonWallMaterial.isItem() && !nonWallMaterial.isBlock()) {
BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(nonWallMaterial, material);
}
} catch (Exception e) {
// Ignore
}
}
ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(Material.REDSTONE, Material.REDSTONE_WIRE);
}
}
@@ -0,0 +1,59 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.bausystem.utils.PlayerMovementWrapper;
import net.minecraft.server.v1_15_R1.EntityPlayer;
import net.minecraft.server.v1_15_R1.PacketPlayInFlying;
import net.minecraft.server.v1_15_R1.PacketPlayOutEntity;
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityTeleport;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class PlayerMovementWrapper15 implements PlayerMovementWrapper {
@Override
public void setPosition(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (Float.isNaN(packetPlayInFlying.a(Float.NaN))) {
entityPlayer.e(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0));
} else {
entityPlayer.setLocation(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0), packetPlayInFlying.a(0F), packetPlayInFlying.b(0F));
}
}
@Override
public Object convertToOut(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
Object packet = Reflection.newInstance(teleportPacket);
teleportEntity.set(packet, player.getEntityId());
teleportPosition.set(packet, packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0));
if (Float.isNaN(packetPlayInFlying.a(Float.NaN))) {
teleportYaw.set(packet, rotToByte(player.getLocation().getYaw()));
teleportPitch.set(packet, rotToByte(player.getLocation().getPitch()));
} else {
teleportYaw.set(packet, rotToByte(packetPlayInFlying.a(0.0F)));
teleportPitch.set(packet, rotToByte(packetPlayInFlying.b(0.0F)));
}
return packet;
}
}
@@ -0,0 +1,23 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
public class TickListener15 implements TickListener {
}
+65
View File
@@ -0,0 +1,65 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
compileOnly(project(":BauSystem:BauSystem_Main"))
compileOnly(project(":SpigotCore"))
compileOnly("de.steamwar:spigot:1.18")
compileOnly("de.steamwar:worldedit:1.15")
compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT")
compileOnly("it.unimi.dsi:fastutil:8.5.6")
compileOnly("com.mojang:datafixerupper:4.0.26")
compileOnly("io.netty:netty-all:4.1.68.Final")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("com.mojang:brigadier:1.0.18")
}
@@ -0,0 +1,145 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.bausystem.features.util.NoClipCommand;
import net.minecraft.SystemUtils;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.server.level.PlayerInteractManager;
import net.minecraft.world.level.EnumGamemode;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongSupplier;
public class NMSWrapper18 implements NMSWrapper {
private static final Reflection.FieldAccessor<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
@Override
@SuppressWarnings("deprecation")
public void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
}
@Override
public void setSlotToItemStack(Player player, Object o) {
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
int index = packetPlayInSetCreativeSlot.b();
if (index >= 36 && index <= 44) {
index -= 36;
} else if (index > 44) {
index -= 5;
} else if (index <= 8) {
index = index - 8 + 36;
}
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
if (index < 9) player.getInventory().setHeldItemSlot(index);
player.updateInventory();
}
private static final Reflection.FieldAccessor<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
@Override
public void setGameStateChangeReason(Object packet) {
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
}
@Override
public void setPlayerBuildAbilities(Player player) {
((CraftPlayer) player).getHandle().fs().d = true;
((CraftPlayer) player).getHandle().fs().e = true;
}
@Override
public Material pathMaterial() {
return Material.DIRT_PATH;
}
private static final int threshold = 2048;
@Override
public boolean checkItemStack(ItemStack item) {
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
NBTTagCompound tag = nmsItem.t();
if (tag != null && tag.e("BlockEntityTag")) {
NBTTagCompound blockTag = tag.p("BlockEntityTag");
if (blockTag.e("Items")) {
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
}
}
return false;
}
private int drillDown(NBTTagList items, int layer, int start) {
if (layer > 2) return start + threshold;
int invalid = start;
for (NBTBase nbtBase : items) {
if (!(nbtBase instanceof NBTTagCompound))
continue;
NBTTagCompound slot = (NBTTagCompound) nbtBase;
if (slot.e("tag")) {
invalid += slot.f("Count");
NBTTagCompound iTag = slot.p("tag");
if (iTag.e("BlockEntityTag")) {
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
if (blockTag.e("Items")) {
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
}
}
}
if (invalid > threshold)
break;
}
return invalid;
}
private final Class<?> explosionPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
private final Reflection.FieldAccessor<Double> a = Reflection.getField(explosionPacket, double.class, 0);
private final Reflection.FieldAccessor<Double> b = Reflection.getField(explosionPacket, double.class, 1);
private final Reflection.FieldAccessor<Double> c = Reflection.getField(explosionPacket, double.class, 2);
private final Reflection.FieldAccessor<Float> d = Reflection.getField(explosionPacket, float.class, 0);
private final Reflection.FieldAccessor<List> e = Reflection.getField(explosionPacket, List.class, 0);
@Override
public Object resetExplosionKnockback(Object packet) {
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
}
}
@@ -0,0 +1,57 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.bausystem.utils.PlayerMovementWrapper;
import net.minecraft.network.protocol.game.PacketPlayInFlying;
import net.minecraft.server.level.EntityPlayer;
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class PlayerMovementWrapper18 implements PlayerMovementWrapper {
@Override
public void setPosition(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (packetPlayInFlying.h) {
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
} else {
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
}
}
@Override
public Object convertToOut(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
Object packet = Reflection.newInstance(teleportPacket);
teleportEntity.set(packet, player.getEntityId());
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
if (packetPlayInFlying.h) {
teleportYaw.set(packet, rotToByte(player.getLocation().getYaw()));
teleportPitch.set(packet, rotToByte(player.getLocation().getPitch()));
} else {
teleportYaw.set(packet, rotToByte(packetPlayInFlying.d));
teleportPitch.set(packet, rotToByte(packetPlayInFlying.e));
}
return packet;
}
}
+66
View File
@@ -0,0 +1,66 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
compileOnly(project(":BauSystem:BauSystem_Main"))
compileOnly(project(":SpigotCore"))
compileOnly("de.steamwar:spigot:1.19")
compileOnly("de.steamwar:worldedit:1.15")
compileOnly("org.spigotmc:spigot-api:1.19-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")
compileOnly("it.unimi.dsi:fastutil:8.5.6")
compileOnly("com.mojang:datafixerupper:4.0.26")
compileOnly("io.netty:netty-all:4.1.68.Final")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("com.mojang:brigadier:1.0.18")
}
@@ -0,0 +1,145 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.bausystem.features.util.NoClipCommand;
import net.minecraft.SystemUtils;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.server.level.PlayerInteractManager;
import net.minecraft.world.level.EnumGamemode;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.function.LongSupplier;
public class NMSWrapper19 implements NMSWrapper {
private static final Reflection.FieldAccessor<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
@Override
@SuppressWarnings("deprecation")
public void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
}
@Override
public void setSlotToItemStack(Player player, Object o) {
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
int index = packetPlayInSetCreativeSlot.b();
if (index >= 36 && index <= 44) {
index -= 36;
} else if (index > 44) {
index -= 5;
} else if (index <= 8) {
index = index - 8 + 36;
}
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
if (index < 9) player.getInventory().setHeldItemSlot(index);
player.updateInventory();
}
private static final Reflection.FieldAccessor<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
@Override
public void setGameStateChangeReason(Object packet) {
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
}
@Override
public void setPlayerBuildAbilities(Player player) {
((CraftPlayer) player).getHandle().fF().d = true;
((CraftPlayer) player).getHandle().fF().e = true;
}
@Override
public Material pathMaterial() {
return Material.DIRT_PATH;
}
private static final int threshold = 2048;
@Override
public boolean checkItemStack(ItemStack item) {
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
NBTTagCompound tag = nmsItem.v();
if (tag != null && tag.e("BlockEntityTag")) {
NBTTagCompound blockTag = tag.p("BlockEntityTag");
if (blockTag.e("Items")) {
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
}
}
return false;
}
private int drillDown(NBTTagList items, int layer, int start) {
if (layer > 2) return start + threshold;
int invalid = start;
for (NBTBase nbtBase : items) {
if (!(nbtBase instanceof NBTTagCompound))
continue;
NBTTagCompound slot = (NBTTagCompound) nbtBase;
if (slot.e("tag")) {
invalid += slot.f("Count");
NBTTagCompound iTag = slot.p("tag");
if (iTag.e("BlockEntityTag")) {
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
if (blockTag.e("Items")) {
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
}
}
}
if (invalid > threshold)
break;
}
return invalid;
}
private final Class<?> explosionPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
private final Reflection.FieldAccessor<Double> a = Reflection.getField(explosionPacket, double.class, 0);
private final Reflection.FieldAccessor<Double> b = Reflection.getField(explosionPacket, double.class, 1);
private final Reflection.FieldAccessor<Double> c = Reflection.getField(explosionPacket, double.class, 2);
private final Reflection.FieldAccessor<Float> d = Reflection.getField(explosionPacket, float.class, 0);
private final Reflection.FieldAccessor<List> e = Reflection.getField(explosionPacket, List.class, 0);
@Override
public Object resetExplosionKnockback(Object packet) {
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
}
}
@@ -0,0 +1,61 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import net.minecraft.network.protocol.game.PacketPlayInFlying;
import net.minecraft.server.level.EntityPlayer;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerMovementWrapper19 implements PlayerMovementWrapper {
@Override
public void setPosition(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (packetPlayInFlying.h) {
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
} else {
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
}
}
@Override
public Object convertToOut(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
Object packet = Reflection.newInstance(teleportPacket);
teleportEntity.set(packet, player.getEntityId());
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
if (packetPlayInFlying.h) {
teleportYaw.set(packet, rotToByte(player.getLocation().getYaw()));
teleportPitch.set(packet, rotToByte(player.getLocation().getPitch()));
} else {
teleportYaw.set(packet, rotToByte(packetPlayInFlying.d));
teleportPitch.set(packet, rotToByte(packetPlayInFlying.e));
}
return packet;
}
}
@@ -0,0 +1,51 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
import com.destroystokyo.paper.event.server.ServerTickStartEvent;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.tpslimit.TPSFreezeUtils;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class TickListener19 implements TickListener, Listener {
private boolean tickStartRan = false;
public TickListener19() {
Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance());
}
@EventHandler
public void onServerTickStart(ServerTickStartEvent event) {
if (TPSFreezeUtils.isFrozen()) return;
Bukkit.getPluginManager().callEvent(new TickStartEvent());
tickStartRan = true;
}
@EventHandler
public void onServerTickEnd(ServerTickEndEvent event) {
if (!tickStartRan) return;
Bukkit.getPluginManager().callEvent(new TickEndEvent());
tickStartRan = false;
}
}
+64
View File
@@ -0,0 +1,64 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
compileOnly(project(":BauSystem:BauSystem_Main"))
compileOnly(project(":SpigotCore"))
compileOnly("de.steamwar:spigot:1.20")
compileOnly("org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
compileOnly("it.unimi.dsi:fastutil:8.5.6")
compileOnly("com.mojang:datafixerupper:4.0.26")
compileOnly("io.netty:netty-all:4.1.68.Final")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("com.mojang:brigadier:1.0.18")
}
@@ -0,0 +1,136 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.bausystem.features.util.NoClipCommand;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot;
import net.minecraft.network.protocol.game.PacketPlayOutExplosion;
import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange;
import net.minecraft.server.level.PlayerInteractManager;
import net.minecraft.world.level.EnumGamemode;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
public class NMSWrapper20 implements NMSWrapper {
private static final Reflection.FieldAccessor<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
@Override
@SuppressWarnings("deprecation")
public void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().e, EnumGamemode.a(gameMode.getValue()));
}
@Override
public void setSlotToItemStack(Player player, Object o) {
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
int index = packetPlayInSetCreativeSlot.a();
if (index >= 36 && index <= 44) {
index -= 36;
} else if (index > 44) {
index -= 5;
} else if (index <= 8) {
index = index - 8 + 36;
}
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
if (index < 9) player.getInventory().setHeldItemSlot(index);
player.updateInventory();
}
private static final Reflection.FieldAccessor<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
@Override
public void setGameStateChangeReason(Object packet) {
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
}
@Override
public void setPlayerBuildAbilities(Player player) {
((CraftPlayer) player).getHandle().fO().d = true;
((CraftPlayer) player).getHandle().fO().e = true;
}
@Override
public Material pathMaterial() {
return Material.DIRT_PATH;
}
private static final int threshold = 2048;
@Override
public boolean checkItemStack(ItemStack item) {
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
NBTTagCompound tag = nmsItem.v();
if (tag != null && tag.e("BlockEntityTag")) {
NBTTagCompound blockTag = tag.p("BlockEntityTag");
if (blockTag.e("Items")) {
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
}
}
return false;
}
private int drillDown(NBTTagList items, int layer, int start) {
if (layer > 2) return start + threshold;
int invalid = start;
for (NBTBase nbtBase : items) {
if (!(nbtBase instanceof NBTTagCompound))
continue;
NBTTagCompound slot = (NBTTagCompound) nbtBase;
if (slot.e("tag")) {
invalid += slot.f("Count");
NBTTagCompound iTag = slot.p("tag");
if (iTag.e("BlockEntityTag")) {
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
if (blockTag.e("Items")) {
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
}
}
}
if (invalid > threshold)
break;
}
return invalid;
}
private final Class<?> explosionPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
private final Reflection.FieldAccessor<Double> a = Reflection.getField(explosionPacket, double.class, 0);
private final Reflection.FieldAccessor<Double> b = Reflection.getField(explosionPacket, double.class, 1);
private final Reflection.FieldAccessor<Double> c = Reflection.getField(explosionPacket, double.class, 2);
private final Reflection.FieldAccessor<Float> d = Reflection.getField(explosionPacket, float.class, 0);
private final Reflection.FieldAccessor<List> e = Reflection.getField(explosionPacket, List.class, 0);
@Override
public Object resetExplosionKnockback(Object packet) {
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
}
}
@@ -0,0 +1,43 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
public class PlaceItemWrapper20 implements PlaceItemWrapper {
public PlaceItemWrapper20() {
for (Material material : Material.values()) {
if (!material.isBlock()) continue;
if (material.isLegacy()) continue;
BlockData blockData = material.createBlockData();
Material placementMaterial = blockData.getPlacementMaterial();
if (material == placementMaterial) continue;
if (placementMaterial == Material.AIR) continue;
if (placementMaterial.isItem() && !placementMaterial.isBlock()) {
ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(placementMaterial, material);
}
if (material.name().contains("WALL")) {
BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(placementMaterial, material);
}
}
}
}
@@ -0,0 +1,62 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import net.minecraft.network.protocol.game.PacketPlayInFlying;
import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport;
import net.minecraft.server.level.EntityPlayer;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class PlayerMovementWrapper20 implements PlayerMovementWrapper {
@Override
public void setPosition(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
if (packetPlayInFlying.h) {
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
} else {
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
}
}
@Override
public Object convertToOut(Player player, Object object) {
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
Object packet = Reflection.newInstance(teleportPacket);
teleportEntity.set(packet, player.getEntityId());
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
if (packetPlayInFlying.h) {
teleportYaw.set(packet, rotToByte(player.getLocation().getYaw()));
teleportPitch.set(packet, rotToByte(player.getLocation().getPitch()));
} else {
teleportYaw.set(packet, rotToByte(packetPlayInFlying.d));
teleportPitch.set(packet, rotToByte(packetPlayInFlying.e));
}
return packet;
}
}
@@ -0,0 +1,54 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
compileOnly(project(":SpigotCore"))
}
@@ -0,0 +1,40 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class BauGuiItem_GENERIC implements LinkageType {
@Override
public String method() {
return "linkGUIItems";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
buildPlan.addImport("de.steamwar.bausystem.features.gui.BauGUI");
methodBuilder.addLine("BauGUI.addItem(" + s + ");");
}
}
@@ -0,0 +1,39 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class BoundingBoxLoader_GENERIC implements LinkageType {
@Override
public String method() {
return "linkBoundingBox";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement) {
method.addLine(instance + ".load();");
}
}
@@ -0,0 +1,40 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class ConfigConverter_GENERIC implements LinkageType {
@Override
public String method() {
return "link";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
buildPlan.addImport("de.steamwar.bausystem.configplayer.Config");
methodBuilder.addLine("Config.addConfigConverter(" + s + ");");
}
}
@@ -0,0 +1,41 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class FAWEMaskParser_GENERIC implements LinkageType {
@Override
public String method() {
return "link";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
methodBuilder.addLine("if (org.bukkit.Bukkit.getPluginManager().getPlugin(\"FastAsyncWorldEdit\") != null) {");
methodBuilder.addLine(" " + s + ";");
methodBuilder.addLine("}");
}
}
@@ -0,0 +1,41 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class FAWEPatternParser_GENERIC implements LinkageType {
@Override
public String method() {
return "link";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
methodBuilder.addLine("if (org.bukkit.Bukkit.getPluginManager().getPlugin(\"FastAsyncWorldEdit\") != null) {");
methodBuilder.addLine(" " + s + ";");
methodBuilder.addLine("}");
}
}
@@ -0,0 +1,40 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class LuaLib_GENERIC implements LinkageType {
@Override
public String method() {
return "link";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
buildPlan.addImport("de.steamwar.bausystem.features.script.lua.SteamWarLuaPlugin");
methodBuilder.addLine("SteamWarLuaPlugin.add(" + s + ");");
}
}
@@ -0,0 +1,40 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class PanzernAlgorithm_GENERIC implements LinkageType {
@Override
public String method() {
return "linkPanzern";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
buildPlan.addImport("de.steamwar.bausystem.features.slaves.panzern.Panzern");
methodBuilder.addLine("Panzern.add(" + s + ");");
}
}
@@ -0,0 +1,40 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class ScoreboardElement_GENERIC implements LinkageType {
@Override
public String method() {
return "link";
}
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder methodBuilder, String s, TypeElement typeElement) {
buildPlan.addImport("de.steamwar.bausystem.features.world.BauScoreboard");
methodBuilder.addLine("BauScoreboard.addElement(" + s + ");");
}
}
+67
View File
@@ -0,0 +1,67 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2024 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 <https://www.gnu.org/licenses/>.
*/
plugins {
id("java")
id("base")
}
group = "de.steamwar"
version = ""
tasks.compileJava {
options.encoding = "UTF-8"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
sourceSets {
main {
java {
srcDirs("src/", "build/generated/sources/annotationProcessor/java/main/")
}
resources {
srcDirs("src/")
exclude("**/*.java", "**/*.kt")
}
}
}
dependencies {
compileOnly("org.projectlombok:lombok:1.18.32")
annotationProcessor("org.projectlombok:lombok:1.18.32")
implementation(project(":BauSystem:BauSystem_Linkage"))
annotationProcessor(project(":BauSystem:BauSystem_Linkage"))
compileOnly(project(":SpigotCore"))
annotationProcessor(project(":SpigotCore"))
compileOnly("de.steamwar:spigot:1.20")
compileOnly("de.steamwar:fastasyncworldedit:1.18")
compileOnly("de.steamwar:axiompaper:RELEASE")
implementation("org.luaj:luaj-jse:3.0.1")
implementation(files("$projectDir/../libs/YAPION-SNAPSHOT.jar"))
compileOnly("org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("io.netty:netty-all:4.1.68.Final")
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,955 @@
#
# 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 <https://www.gnu.org/licenses/>.
#
PREFIX=§eBau§8System§8»
TIME=HH:mm:ss
DATE=........
COMMAND_HELP_HEAD=§7---=== (§e{0}§7) ===---
ONLY_SCHEMS=§cDu kannst hier keinen Ordner angeben
PAGE_LIST=§e Seite ({0}/{1}) »»
LIST_PREVIOUS_PAGE=§eVorherige Seite
LIST_NEXT_PAGE=§eNächste Seite
# Permission
NO_PERMISSION=Du darfst dies hier nicht nutzen
SPECTATOR=§fZuschauer
# Scoreboard
SCOREBOARD_TIME=Uhrzeit
SCOREBOARD_REGION=Region
SCOREBOARD_TRACE=Trace
SCOREBOARD_LOADER=Loader
SCOREBOARD_TPS=TPS
SCOREBOARD_TPS_FROZEN=§eEingefroren
SCOREBOARD_TRACE_TICKS=Ticks
SCOREBOARD_TECHHIDER=TechHider§8: §aAn
SCOREBOARD_XRAY=XRay§8: §aAn
SCOREBOARD_LOCK_TEAM=Bau Lock§8: §eTeam
SCOREBOARD_LOCK_TEAM_AND_SERVERTEAM=Bau Lock§8: §e(Server-) Team
SCOREBOARD_LOCK_SERVERTEAM=Bau Lock§8: §eServerteam
SCOREBOARD_LOCK_NOBODY=Bau Lock§8: §cNiemand
# Flags
FLAG_COLOR=Color
FLAG_TNT=TNT
FLAG_FIRE=Fire
FLAG_FREEZE=Freeze
FLAG_PROTECT=Protect
FLAG_ITEMS=Items
FLAG_FIRE_ALLOW=§can
FLAG_FIRE_DENY=§aaus
FLAG_FREEZE_ACTIVE=§aan
FLAG_FREEZE_INACTIVE=§caus
FLAG_PROTECT_ACTIVE=§aan
FLAG_PROTECT_INACTIVE=§caus
FLAG_TNT_ALLOW=§aan
FLAG_TNT_DENY=§caus
FLAG_TNT_ONLY_TB=§7Kein §eBaurahmen
FLAG_TNT_ONLY_BUILD=§7Kein §eTestblock
FLAG_ITEMS_ACTIVE=§aan
FLAG_ITEMS_INACTIVE=§caus
FLAG_COLOR_WHITE=§fWeiß
FLAG_COLOR_ORANGE=§6Orange
FLAG_COLOR_MAGENTA=§dMagenta
FLAG_COLOR_LIGHT_BLUE=§bHellblau
FLAG_COLOR_YELLOW=§eGelb
FLAG_COLOR_LIME=§aHellgrün
## This cannot be converted
FLAG_COLOR_PINK=§ePink
FLAG_COLOR_GRAY=§8Grau
FLAG_COLOR_LIGHT_GRAY=§7Hellgrau
FLAG_COLOR_CYAN=§3Cyan
FLAG_COLOR_PURPLE=§5Lila
FLAG_COLOR_BLUE=§1Blau
## This cannot be converted
FLAG_COLOR_BROWN=§eBraun
FLAG_COLOR_GREEN=§2Grün
FLAG_COLOR_RED=§cRot
FLAG_COLOR_BLACK=§0Schwarz
# Region
REGION_TYPE_NORMAL=Normal
REGION_TYPE_BUILD=Baubereich
REGION_TYPE_ONLY_TB=Testblock
# AttributesCopy
ATTRIBUTES_CANT_COPY=§cDu musst den Item Type in der Hand halten wo du auch drauf guckst.
ATTRIBUTES_NO_COPY=§cKeine Attribute kopiert.
ATTRIBUTES_COPIED=§eAttribute kopiert.
ATTRIBUTE_REMOVE_ALL=§eAlle Attribute entfernt.
ATTRIBUTE_REMOVE_SINGLE=§eAttribut §7{0}§e entfernt.
ATTRIBUTE_REMOVE_NOT_FOUND=§cAttribut nicht gefunden
# AutoStart
AUTOSTART_COMMAND_HELP=§8/§etimer §8- §7Legt den AutostartTimer ins Inventar
AUTOSTART_ITEM_NAME=§eAutostartTimer
AUTOSTART_ITEM_LORE=§eRechtsklick Block §8- §7Starte den Timer
AUTOSTART_MESSAGE_NO_REGION=§cDu befindest dich derzeit in keiner Region
AUTOSTART_MESSAGE_RESET=§eDer AutostartTimer wurde zurückgesetzt
AUTOSTART_MESSAGE_START=§eAutostartTimer gestartet
AUTOSTART_MESSAGE_RESULT1=§eZeit §7bis zur §eExplosion §7am Gegner§8:§e {0}§7 in game ticks
AUTOSTART_MESSAGE_RESULT2=§7Zeitdifferenz in §egame ticks §7bis {0} Sekunden§8:§e {1}
AUTOSTART_MESSAGE_RESULT3=§7Positiv, wenn zu wenig, negativ wenn zu viel
# Backup
BACKUP_HELP_CREATE=§8/§ebackup create §8- §7Erstelle ein Backup der Region
BACKUP_HELP_LOAD=§8/§ebackup load §8[§7BackupName§8] §8- §7 Lade ein Backup
BACKUP_HELP_LIST=§8/§ebackup list §8- §7Liste alle Backups der Region auf
BACKUP_HELP_GUI=§8/§ebackup gui §8- §7Öffne die Backups in einer GUI
BACKUP_REGION_NO_REGION=§cDu bist in keiner Region
BACKUP_CREATE_SUCCESS=§7Das Backup wurde erstellt
BACKUP_CREATE_FAILURE=§cDas Backup erstellen ist schiefgegangen
BACKUP_CREATE_NO_CHANGE=§7Die Region hat keine Veränderung
BACKUP_LIST_HEAD=§7---=== (§eBackup §7{0}§7) ===---
BACKUP_LIST_ENTRY=§7{0} §e[Laden]
BACKUP_LOAD_FAILURE=§cDas Backup laden ist schiefgegangen
BACKUP_LOAD=§7Backup geladen
BACKUP_INV_NAME=§eBackup
BACKUP_ITEM_NAME=§eBackup §7von §e{0}
BACKUP_LORE=§eKlicken zum Laden
# Bau
BAU_COMMAND_HELP_INFO=§8/§ebau info §8- §7Alias für §8/§ebauinfo
BAU_INFO_ITEM_NAME=§eBau-Management
## This is used in BauInfoBauGuiItem.java
BAU_INFO_ITEM_LORE_TNT=§7TNT§8: §e{0}
BAU_INFO_ITEM_LORE_FREEZE=§7Freeze§8: §e{0}
BAU_INFO_ITEM_LORE_DAMAGE=§7Damage§8: §e{0}
BAU_INFO_ITEM_LORE_FIRE=§7Feuer§8: §e{0}
BAU_INFO_ITEM_LORE_COLOR=§7Farbe§8: §e{0}
BAU_INFO_ITEM_LORE_PROTECT=§7Protect§8: §e{0}
BAU_INFO_COMMAND_HELP=§8/§ebauinfo §8- §7Gibt Informationen über den Bau
BAU_INFO_COMMAND_OWNER=§7Besitzer§8: §e{0}
BAU_INFO_COMMAND_MEMBER=§7{0} §8[§7{1}§8]§8: §e{2}
BAU_INFO_COMMAND_FLAG=§7{0}§8: §7{1}
BAU_INFO_COMMAND_TPS=§7TPS§8:§e
# Countingwand
COUNTINGWAND_COMMAND_HELP=§8/§ecountingwand §8- §7Gibt dir ein CountingWand
COUNTINGWAND_ITEM_NAME=§eZollstock
COUNTINGWAND_ITEM_LORE1=§eLinksklick §8- §7Setzt die 1. Position
COUNTINGWAND_ITEM_LORE2=§eRechtsklick §8- §7Setzt die 2. Position
COUNTINGWAND_MESSAGE_RCLICK=§7Erste Position bei: §8[§7{0}§8, §7{1}§8, §7{2}§8] ({3}§8) ({4}§8)
COUNTINGWAND_MESSAGE_LCLICK=§7Zweite Position bei: §8[§7{0}§8, §7{1}§8, §7{2}§8] ({3}§8) ({4}§8)
COUNTINGWAND_MESSAGE_VOLUME=§e{0}
COUNTINGWAND_MESSAGE_DIMENSION=§e{0}§8, §e{1}§8, §e{2}
# Design Endstone
DESIGN_ENDSTONE_COMMAND_HELP=§8/§edesign endstone §8- §7Zeige End Stone im Design
DESIGN_ENDSTONE_REGION_ERROR=§cDiese Region hat keinen Baubereich
DESIGN_ENDSTONE_ENABLE=§aEndstone im Design ist angezeigt
DESIGN_ENDSTONE_DISABLE=§cEndstone im Design ist versteckt
# Detonator
DETONATOR_LOC_REMOVE=§e{0} entfernt
DETONATOR_LOC_ADD=§e{0} hinzugefügt
DETONATOR_BUTTON_SWITCH=Hebel
DETONATOR_BUTTON_WOOD_BUTTON=Knopf
DETONATOR_BUTTON_STONE_BUTTON=Knopf
DETONATOR_BUTTON_PRESSURE_PLATE=Druckplatte
DETONATOR_BUTTON_WEIGHTED-PRESSURE_PLATE=Druckplatte
DETONATOR_BUTTON_TRIPWIRE=Tripwire
DETONATOR_BUTTON_NOTEBLOCK=Noteblock
DETONATOR_BUTTON_DAYLIGHTSENSOR=Tageslichtsensor
DETONATOR_BUTTON_POWERABLE=Aktivierbarer Block
DETONATOR_BUTTON_INVALID=Invalider
DETONATOR_WAND_NAME=§eFernzünder
DETONATOR_WAND_LORE_1=§eLinks Klick §8- §7Setzte einen Punkt zum Aktivieren
DETONATOR_WAND_LORE_2=§eLinks Klick + Shift §8- §eFüge einen Punkt hinzu
DETONATOR_WAND_LORE_3=§eRechts Klick §8- §eLöse alle Punkte aus
DETONATOR_HELP_WAND=§8/§edetonator wand §8-§7 Gibt den Fernzünder
DETONATOR_HELP_CLICK=§8/§edetonator click §8-§7 Aktiviere einen Fernzünder (Haupthand -> Hotbar -> Inventar)
DETONATOR_HELP_CLEAR=§8/§edetonator clear §8-§7 Cleare einen Fernzünder
DETONATOR_HELP_AUTOSTART=§8/§edetonator autostart §8-§7 Automatisch den Autostarttester Aktivieren
DETONATOR_AUTOSTART_ENABLE=§7Autostart beim detonate §aangeschaltet
DETONATOR_AUTOSTART_DISABLE=§7Autostart beim detonate §causgeschaltet
DETONATOR_POINT_ACT=§eEinen Punkt ausgelöst
DETONATOR_POINTS_ACT=§e{0} Punkte ausgelöst
DETONATOR_INVALID_POINT=§cEin Punkt konnte nicht ausgeführt werden
DETONATOR_INVALID_POINTS=§c{0} Punkte konnten nicht ausgeführt werden
DETONATOR_INVALID_BLOCK=§eDer Block konnte nicht hinzugefügt werden
# Hotbar
HOTBAR_HELP_GENERIC=§7Speichert eine Hotbar. Diese wird beim Joinen eines Bauserver, wo du ein Leeres Inventar hast geladen.
HOTBAR_HELP_SAVE=§8/§ehotbar save §8-§7 Speicher deine Aktuelle Hotbar
HOTBAR_HELP_LOAD=§8/§ehotbar load §8-§7 Lade deine Standard Hotbar
HOTBAR_HELP_SHOW=§8/§ehotbar show §8-§7 Zeigt dir deine Standard Hotbar
HOTBAR_SAVED=§7Deine Hotbar wurde als Standard gespeichert
HOTBAR_LOADED=§7Deine Standard Hotbar wurde geladen
HOTBAR_INVENTORY=Standard Hotbar
# GUI
GUI_EDITOR_ITEM_NAME=§eGui Editor
GUI_NAME=Bau GUI
GUI_ITEM_LORE1=§7Du kannst dieses Item zum Öffnen der BauGUI nutzen
GUI_ITEM_LORE2=§7oder Doppel F (Swap hands) drücken.
GUI_EDITOR_TITLE=Bau GUI Editor
GUI_EDITOR_ITEM_ROW_P=§e+1 Zeile
GUI_EDITOR_ITEM_ROW_M=§e-1 Zeile
GUI_EDITOR_ITEM_TRASH=§cTrashcan
GUI_EDITOR_ITEM_TRASH_LORE=§7Item hier rein Legen
GUI_EDITOR_ITEM_MORE=§eMehr Items
GUI_EDITOR_ITEM_CLOSE=§eSchließen
GUI_EDITOR_TITLE_MORE=Item auswählen
# Script
## CustomScript
SCRIPT_HOTKEY_ITEM_NAME=§7Hotkey§8: §e{0}
SCRIPT_EVENT_ITEM_NAME=§7Event§8: §e{0}
SCRIPT_COMMAND_ITEM_NAME=§7Befehl§8: §e/{0}
SCRIPT_ERROR_ONLY_IN_GLOBAL=§cDieses Skript kann nur als globales Skript ausgeführt werden
## Script Menu GUI
SCRIPT_MENU_GUI_ITEM_LORE_1=§7Klicke zum rausnehmen
SCRIPT_MENU_GUI_ITEM_LORE_2=§7Shiftklick zum kopieren
SCRIPT_MENU_GUI_ITEM_LORE_3=§7Rechtsklick zum editieren
SCRIPT_MENU_GUI_ITEM_LORE_4=§7Mittelklick zum anschauen
SCRIPT_MENU_GUI_NAME=§eSkript-Menü
SCRIPT_MENU_GUI_ITEM_ADD_NAME=§eHinzufügen
SCRIPT_MENU_GUI_ITEM_ADD_LORE=§7Klicke mit einem Buch zum hinzufügen
SCRIPT_DEPRECATED=§cDie Funktion §e{0}§c ist veraltet und wird demnächst entfernt. Bitte benutze §e{1}§c.
# Shield Printing
SHIELD_PRINTING_HELP_START=§8/§eshieldprinting start §8- §7Starte das Schild drucken
SHIELD_PRINTING_HELP_COPY=§8/§eshieldprinting copy §8- §7Kopiert die Schilder
SHIELD_PRINTING_HELP_APPLY=§8/§eshieldprinting apply §8- §7Wendet die Schilder an
SHIELD_PRINTING_HELP_STOP=§8/§eshieldprinting stop §8- §7Stoppt das Schild drucken
SHIELD_PRINTING_HELP_STEP_1=§81. §7Füge die Schematic in die Welt ein
SHIELD_PRINTING_HELP_STEP_2=§82. §7Starte das Schild drucken mit §8/§eshieldprinting start
SHIELD_PRINTING_HELP_STEP_3=§83. §7Warte bis alle Schilde ausgefahren sind
SHIELD_PRINTING_HELP_STEP_4=§84. §7Editiere die Schilde wenn nötig
SHIELD_PRINTING_HELP_STEP_5=§85. §7Kopiere das gedruckte mit §8/§eshieldprinting copy
SHIELD_PRINTING_HELP_STEP_6=§86. §7Füge die originale Schematic wieder ein
SHIELD_PRINTING_HELP_STEP_7=§87. §7Wende das gedruckte mit §8/§eshieldprinting apply§7 an
SHIELD_PRINTING_NO_REGION=§cDu bist in keiner Region.
SHIELD_PRINTING_NOT_RUNNING=§cShield printing ist nicht aktiv.
SHIELD_PRINTING_BOSSBAR=§fBewegungen: {0}
SHIELD_PRINTING_BOSSBAR_COPIED=§fBewegungen: {0} Kopiert: {1}
SHIELD_PRINTING_GUI_NAME=§7Schild Drucken
SHIELD_PRINTING_GUI_APPLY=§aAnwenden
SHIELD_PRINTING_GUI_STATE_PREVIOUS=§7R-Click§8: §7Vorherige
SHIELD_PRINTING_GUI_STATE_NEXT=§7L-Click§8: §7Nächste
SHIELD_PRINTING_GUI_STATE_ACTIVE=§e> §7{0}
SHIELD_PRINTING_GUI_STATE_INACTIVE=§8> §7{0}
SHIELD_PRINTING_GUI_STATE_FROM_ORIGINAL=Original
SHIELD_PRINTING_GUI_STATE_FROM_COPY=Kopie
SHIELD_PRINTING_GUI_STATE_ALWAYS_ON=An
SHIELD_PRINTING_GUI_STATE_ALWAYS_OFF=Aus
SHIELD_PRINTING_GUI_STATE_ALWAYS_OPEN=Offen
SHIELD_PRINTING_GUI_STATE_ALWAYS_CLOSED=Geschlossen
SHIELD_PRINTING_GUI_STATE_FENCE=§7{0} §fZaun Verbindungen
SHIELD_PRINTING_GUI_STATE_OPENABLE=§7{0} §fGeöffnet
SHIELD_PRINTING_GUI_STATE_PISTON=§7{0} §fAusgefahren
SHIELD_PRINTING_GUI_STATE_POWERABLE=§7{0} §fAktiviert
SHIELD_PRINTING_GUI_STATE_WALL=§7{0} §fWand Verbindungen
SHIELD_PRINTING_START=§aShield printing wurde gestartet.
SHIELD_PRINTING_COPY=§aSchilde wurden kopiert.
SHIELD_PRINTING_APPLY=§aSchilde wurden angewendet.
SHIELD_PRINTING_STOP=§aShield printing wurde gestoppt.
# Unsign Book
UNSIGN_HELP=§8/§eunsign §8- §7Mache ein Buch beschreibbar
# Simulator
SIMULATOR_HELP=§8/§esimulator §8-§7 Legt dir den Simulatorstab ins Inventar
SIMULATOR_CREATE_HELP=§8/§esimulator create §8[§7name§8] §8-§7 Erstelle einen neuen Simulator
SIMULATOR_CHANGE_HELP=§8/§esimulator change §8-§7 Wechsel zu einem anderen Simulator
SIMULATOR_DELETE_HELP=§8/§esimulator delete §8[§7name§8] §8-§7 Löscht den Simulator
SIMULATOR_START_HELP=§8/§esimulator start §8[§7name§8] §8-§7 Startet die Simulation
SIMULATOR_COPY_HELP=§8/§esimulator copy §8[§7to-copy§8] §8[§7name§8] §8-§7 Kopiert einen Simulator
SIMULATOR_GUI_ITEM_NAME=§eTNT Simulator
SIMULATOR_NO_SIM_IN_HAND=§cKein Simulator Item gewählt
SIMULATOR_GUI_SELECT_SIM=Simulator wählen
SIMULATOR_GUI_CREATE_SIM=§eSimulator erstellen
SIMULATOR_GUI_CREATE_SIM_GUI=Simulator erstellen
SIMULATOR_NAME_ALREADY_EXISTS=§cSimulator existiert bereits
SIMULATOR_NAME_INVALID=§cUngültiger Name
SIMULATOR_ERROR_COPY=§cFehler beim kopieren
SIMULATOR_NOT_EXISTS=§cSimulator existiert nicht
SIMULATOR_CREATE=§aSimulator erstellt
SIMULATOR_EDIT_LOCATION=§7Editiere Positionen
SIMULATOR_EDIT_PROPERTIES=§7Editiere Eigenschaften
SIMULATOR_EDIT_OTHER=§7Editiere Andere
SIMULATOR_EDIT_GROUP=§7Editiere Gruppe
SIMULATOR_EDIT_GROUP_MENU=§eEditiere Gruppe
SIMULATOR_WAND_NAME=§eKanonensimulator
SIMULATOR_WAND_NAME_SELECTED=§7Kanonensimulator §8- §e{0}
SIMULATOR_WAND_LORE_1=§eRechtsklick §8- §7Füge eine Position hinzu
SIMULATOR_WAND_LORE_2=§eSneaken §8- §7Freie Bewegung
SIMULATOR_WAND_LORE_3=§eLinksklick §8- §7Starte die Simulation
SIMULATOR_WAND_LORE_4=§eRechtsklick Luft §8- §7Öffne die GUI
SIMULATOR_WAND_LORE_5=§eDoppel Shift §8- §7Wechsel zwischen TNT und Redstone Block
SIMULATOR_REGION_FROZEN=§cSimulator kann nicht in eingefrorenen Regionen genutzt werden
## Other
SIMULATOR_PLUS_ONE=§7+1
SIMULATOR_PLUS_PIXEL_SHIFT=§eShift §7Click für §e+0,0625
SIMULATOR_PLUS_FIVE_SHIFT=§eShift §7Click für §e+5
SIMULATOR_MINUS_ONE=§7-1
SIMULATOR_MINUS_PIXEL_SHIFT=§eShift §7Click für §e-0,0625
SIMULATOR_MINUS_FIVE_SHIFT=§eShift §7Click für §e-5
SIMULATOR_POSITION_X=§7x-Position
SIMULATOR_POSITION_Y=§7y-Position
SIMULATOR_POSITION_Z=§7z-Position
SIMULATOR_BACK=§eZurück
SIMULATOR_GUI_TOTAL_TNT=§7Gesamt TNT§8: §e{0}
SIMULATOR_DELETED=§cSimulator gelöscht
## GUI
SIMULATOR_POSITION_EDIT=§ePosition bearbeiten
SIMULATOR_POSITION_ADD=§ePosition setzen
SIMULATOR_GUI_TNT_SPAWN_NAME=§eTNT
SIMULATOR_GUI_TNT_SPAWN_LORE_1=§7TNT-Anzahl§8: §e{0}
SIMULATOR_GUI_TNT_SPAWN_LORE_3=§7Lebensdauer§8: §e{0}
SIMULATOR_GUI_TNT_GROUP_NAME=§eTNT Gruppe
SIMULATOR_GUI_TNT_GROUP_LORE_1=§7Elementanzahl§8: §e{0}
SIMULATOR_GUI_TNT_DISABLED=§cDisabled
SIMULATOR_GUI_NAME=Kanonensimulator
SIMULATOR_GUI_DELETE=§cTNT löschen
SIMULATOR_GUI_AUTO_TRACE=§eAutoTrace§8: §7{0}
SIMULATOR_GUI_MOVE_ALL=§eAlle Verschieben
SIMULATOR_ALIGNMENT_CENTER=§7Verschiebung§8: §eMitte
SIMULATOR_ALIGNMENT_POSITIVE_X=§7Verschiebung§8: §ePositive X
SIMULATOR_ALIGNMENT_NEGATIVE_X=§7Verschiebung§8: §eNegative X
SIMULATOR_ALIGNMENT_POSITIVE_Z=§7Verschiebung§8: §ePositive Z
SIMULATOR_ALIGNMENT_NEGATIVE_Z=§7Verschiebung§8: §eNegative Z
SIMULATOR_MOVE_ALL_GUI_NAME=TNT Verschieben
SIMULATOR_TNT_SPAWN_GUI_NAME=TNT konfigurieren {0}
SIMULATOR_TNT_SPAWN_LORE=§eZum Ändern klicken
SIMULATOR_TNT_SPAWN_COUNT=§7TNT-Anzahl §8- §e{0}
SIMULATOR_TNT_SPAWN_COUNT_ANVIL_GUI_NAME=Anzahl TNT
SIMULATOR_TNT_SPAWN_TICK=§7Tick §8- §e{0}
SIMULATOR_TNT_SPAWN_TICK_ANVIL_GUI_NAME=Tick Offset
SIMULATOR_TNT_SPAWN_FUSE=§7Lebensdauer §8- §e{0}
SIMULATOR_TNT_SPAWN_FUSE_ANVIL_GUI_NAME=Fuse-Ticks
SIMULATOR_TNT_SPAWN_VELOCITY_NAME=§7TNT
SIMULATOR_TNT_SPAWN_VELOCITY_X=§7TNT §eSprung X §8- {0}
SIMULATOR_TNT_SPAWN_VELOCITY_Y=§7TNT §eSprung Y §8- {0}
SIMULATOR_TNT_SPAWN_VELOCITY_Z=§7TNT §eSprung Z §8- {0}
SIMULATOR_TNT_SPAWN_VELOCITY_ON=§aan
SIMULATOR_TNT_SPAWN_VELOCITY_OFF=§caus
SIMULATOR_TNT_SPAWN_POSITION_X=§7x-Position §8- §e{0}
SIMULATOR_TNT_SPAWN_POSITION_Y=§7y-Position §8- §e{0}
SIMULATOR_TNT_SPAWN_POSITION_Z=§7z-Position §8- §e{0}
SIMULATOR_TNT_SPAWN_ACTIVATED_WITH=§7Gezündet durch §8- §e{0}
SIMULATOR_TNT_SPAWN_ACTIVATED_WITH_COMPARATOR=Comparator
SIMULATOR_TNT_SPAWN_ACTIVATED_WITH_REPEATER=Repeater
SIMULATOR_TNT_SPAWN_ACTIVATED_WITH_OBSERVER=Observer
SIMULATOR_TNT_SPAWN_MATERIAL=§eMaterial
SIMULATOR_TNT_SPAWN_MATERIAL_LORE_1=§7Jetziges Material§8: §e{0}
SIMULATOR_TNT_SPAWN_MATERIAL_LORE_2=§eLink-Click §7Zum ändern
SIMULATOR_TNT_SPAWN_MATERIAL_LORE_3=§eRechts-Click §7Zum zurücksetzten
SIMULATOR_MATERIAL_GUI_NAME=Material ändern
SIMULATOR_MATERIAL_CLICK=§eKlicken zum wählen
SIMULATOR_TNT_SPAWN_ADD_IGNITION_PHASE=§eZündphase hinzufügen
SIMULATOR_TNT_SPAWN_ADD_TNT=§eTNT hinzufügen
SIMULATOR_TNT_SPAWN_REMOVE_TNT=§cEntfernen
SIMULATOR_TNT_SPAWN_POSITION_ANVIL_GUI_NAME=Position
# SmartPlace
SMART_PLACE_HELP=§8/§esmartplace §8-§7 Toggled SmartPlace
SMART_PLACE_INFO=§7Plaziert rotierbare Blöcke beim §esneaken§7 von dir §eweg§7.
SMART_PLACE_ENABLE=§aSmartPlace aktiviert
SMART_PLACE_DISABLE=§cSmartPlace deaktiviert
# InventoryFiller
INVENTORY_FILL_HELP=§8/§einventoryfill §8- §7Toggled InventoryFill
INVENTORY_FILL_INFO=§7Hilft dir, Behälter zu füllen, indem du sie beim sneaken ansiehst und den Gegenstand fallen lässt. Oder scrolle einfach auf einen Behälter, um die Menge des gehaltenen Gegenstandes darin zu ändern.
INVENTORY_FILL_ENABLE=§aInventoryFiller activated
INVENTORY_FILL_DISABLE=§cInventoryFiller deactivated
# Killchecker
KILLCHECKER_HELP_ENABLE=§8/§ekillchecker enable §8- §7Aktiviert Killchecker / Berechnet kills neu
KILLCHECKER_HELP_DISABLE=§8/§ekillchecker disable §8- §7Deaktiviert Killchecker
KILLCHECKER_INFO=§7Zeigt Überlappungen der Kanonen Kills im Baubereich an.
KILLCHECKER_INFO2=§7Nur farbige Blöcke wie Wolle, Terracotta, Stained Glass und Concrete wird gezählt.
KILLCHECKER_ENABLE=§aKillchecker aktiviert
KILLCHECKER_DISABLE=§cKillchecker deaktiviert
KILLCHECKER_BOSSBAR=§e§l{0} §7(§e{1}%§7) §e§l{2}§7 Kanonnen
# BlockCounter
BLOCK_COUNTER_HELP_TOGGLE=§8/§eblockcounter §8- §7Wechsel zwischen an und aus
BLOCK_COUNTER_HELP_ENABLE=§8/§eblockcounter enable §8- §7Schalte den BlockCounter an
BLOCK_COUNTER_HELP_DISABLE=§8/§eblockcounter disable §8- §7Schalte den BlockCounter aus
BLOCK_COUNTER_MESSAGE=§7Schaden §8> §e{0} §7Blöcke §e{1} §7TNT §e{2} §7Blöcke/TNT §e{3} §7Blöcke/tick
BLOCK_COUNTER_MESSAGE_SECOND=§7Schaden §8> §e{0} §7Blöcke §e{1} §7TNT §e{2} §7Blöcke/TNT §e{3} §7Blöcke/s
BLOCK_COUNTER_ENABLE=§7BlockCounter angemacht
BLOCK_COUNTER_DISABLE=§7BlockCounter ausgemacht
# DepthCounter
DEPTH_COUNTER_MESSAGE=§7Tiefe §8> §7
# TPSLimit
TPSLIMIT_FREEZE_HELP=§8/§etpslimit 0 §8-§7 Friere TPS ein
TPSLIMIT_LIMIT_HELP=§8/§etpslimit §8[§720>x>0.5§8] §8-§7 Verlangsame die TPS
TPSLIMIT_WARP_HELP=§8/§etpslimit §8[§7x>20§8] §8-§7 Beschleunige die TPS
TPSLIMIT_DEFAULT_HELP=§8/§etpslimit default §8-§7 Setze die TPS auf 20
TPSLIMIT_HELP=§8/§etpslimit §8-§7 Zeige die jetzige TPS
TICK_FREEZE_HELP=§8/§etick rate 0 §8-§7 Friere TPS ein
TICK_FREEZE_HELP_2=§8/§etick freeze §8-§7 Friere TPS ein
TICK_UNFREEZE_HELP=§8/§etick unfreeze §8-§7 Setze die TPS auf 20
TICK_LIMIT_HELP=§8/§etick rate §8[§720>x>0.5§8] §8-§7 Verlangsame die TPS
TICK_WARP_HELP=§8/§etick rate §8[§7x>20§8] §8-§7 Beschleunige die TPS
TICK_DEFAULT_HELP=§8/§etick rate default §8-§7 Setze die TPS auf 20
TICK_HELP=§8/§etick rate §8-§7 Zeige die jetzige TPS
TICK_STEPPING_HELP=§8/§etick step §8<§7Ticks§8> §8-§7 Spule n ticks oder 1 vor
TICK_WARPING_HELP=§8/§etick warp §8<§7Ticks§8> §8<§7TPS§8> §8-§7 Warpe n ticks oder 1 vor
TICK_BOSSBAR=§e{0}§8/§7{1} gesprungen
TPSLIMIT_GUI_ITEM_NAME=§eTPS Limiter
TPSLIMIT_GUI_ITEM_LORE=§7Aktuell: §e{0}
TPSLIMIT_ANVIL_GUI=Neues TPS Limit
TPSLIMIT_CURRENT=§7Jetziges TPS limit§8: §e{0}
TPSLIMIT_SET=§eTPS limit auf {0} gesetzt.
TPSLIMIT_FROZEN=§eTPS eingefroren.
# Trace
TRACE_RECORD=§aan
TRACE_HAS_TRACES=§ehat Traces
TRACE_MESSAGE_START=§aTNT-Tracer gestartet
TRACE_MESSAGE_AUTO_START=§eAuto TNT-Tracer gestartet
TRACE_MESSAGE_AUTO_STOP=§cAuto TNT-Tracer gestoppt
TRACE_MESSAGE_STOP=§cTNT-Tracer gestoppt
TRACE_MESSAGE_CLEAR=§cAlle TNT-Positionen gelöscht
TRACE_MESSAGE_CLICK_ISOLATE=§eKlicken zum §aisolieren§8/§causblenden
TRACE_MESSAGE_SHOW_AT=§aTNT-positions angezeigt bei {0}
TRACE_MESSAGE_SHOW_FROM=§aAll TNT-positions angezeigt von {0}
TRACE_MESSAGE_SHOW_FROM_TO=§aAll TNT-positions angezeigt von {0} bis {1}
TRACE_MESSAGE_BROADCAST=§e{0} teilte seinen Trace-Show-Status.
TRACE_MESSAGE_BROADCAST_HOVER=§eZum Ansehen klicken.
TRACE_MESSAGE_FOLLOW=§aSie folgen nun {0} Trace show state
TRACE_MESSAGE_FOLLOW_SELF=§cSie können sich selbst nicht folgen!
TRACE_MESSAGE_UNFOLLOW=§cSie folgen nicht mehr dem Status einer Trace-Show
TRACE_MESSAGE_SHOW_TO_SMALLER=§cBis muss größer als von sein
TRACE_MESSAGE_ISOLATE=§eTNT Positionen wurden isoliert
TRACE_COMMAND_HELP_BROADCAST=§8/§etrace broadcast §8- §7Teilt den aktuellen Trace-Show-Status mit anderen
TRACE_COMMAND_HELP_FOLLOW=§8/§etrace follow §8[§ePlayer§8] §8- §7Verfolgen eines Spielers Status anzeigen
TRACE_COMMAND_HELP_UNFOLLOW=§8/§etrace unfollow §8- §7Den Status der Trace-Anzeige aufheben
TRACE_COMMAND_HELP_START=§8/§etrace start §8- §7Startet die Aufnahme aller TNT-Positionen
TRACE_COMMAND_HELP_STOP=§8/§etrace stop §8- §7Stoppt den TNT-Tracer
TRACE_COMMAND_HELP_AUTO=§8/§etrace toggleauto §8- §7Automatischer Aufnahmenstart
TRACE_COMMAND_HELP_SHOW=§8/§etrace show §8<§eParameter§8> - §7Zeigt alle TNT-Positionen
TRACE_COMMAND_HELP_SHOW_AT=§8/§etrace show §8(§etime§8|§7fuse§8) §7at §8<§eTIME§8> - §7Zeigt alle TNT-Positionen bei §8<§eTIME§8> an
TRACE_COMMAND_HELP_SHOW_FROM=§8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> - §7Zeigt alle TNT-Positionen von §8<§eFROM§8>
TRACE_COMMAND_HELP_SHOW_FROM_TO=§8/§etrace show §8(§etime§8|§7fuse§8) §7from §8<§eFROM§8> §7to §8<§eTO§8> - §7Zeigt alle TNT-Positionen zwischen §8<§eFROM§8> und §8<§eTO§8>
TRACE_COMMAND_HELP_HIDE=§8/§etrace hide §8- §7Versteckt alle TNT-Positionen
TRACE_COMMAND_HELP_DELETE=§8/§etrace delete §8- §7Löscht alle TNT-Positionen
TRACE_COMMAND_HELP_ISOLATE=§8/§etrace isolate §8[§eTrace§8] §8[§eTNT§8] §8- §7Isoliert spezifische TNTs des Traces
TRACE_GUI_ITEM_NAME=§eTracer
TRACE_GUI_ITEM_LORE=§7Status§8: {0}
TRACE_GUI_NAME=Tracer Gui
TRACE_GUI_TRACE_INACTIVE=§eTracer Starten
TRACE_GUI_TRACE_ACTIVE=§eTracer Stoppen
TRACE_GUI_TRACE_ACTIVE_AUTO=§eAuto-Trace ist Aktiv
TRACE_GUI_AUTO_TRACE_INACTIVE=§eAuto-Tracer Aktivieren
TRACE_GUI_AUTO_TRACE_ACTIVE=§eAuto-Tracer Deaktivieren
TRACE_GUI_DELETE=§eTrace Löschen
# Loader
LOADER_SETUP=§eEinrichtung
LOADER_RUNNING=§aLaufend
LOADER_PAUSE=§7Pausiert
LOADER_END=§8Beendet
LOADER_SINGLE=§aEinmal
LOADER_MESSAGE_INTERACT=§e{0} hinzugefügt {1}
LOADER_BUTTON_TNT=TNT
LOADER_BUTTON_SWITCH=Hebel
LOADER_BUTTON_WOOD_BUTTON=Holzknopf
LOADER_BUTTON_STONE_BUTTON=Steinknopf
LOADER_BUTTON_PRESSURE_PLATE=Druckplatte
LOADER_BUTTON_WEIGHTED_PRESSURE_PLATE=Druckplatte
LOADER_BUTTON_TRIPWIRE=Tripwire
LOADER_BUTTON_NOTEBLOCK=Noteblock
LOADER_BUTTON_DAYLIGHT_DETECTOR=Tageslichtsensor
LOADER_BUTTON_COMPARATOR=Comparator
LOADER_BUTTON_REPEATER=Repeater
LOADER_BUTTON_LECTERN=Lectern
LOADER_BUTTON_TRAPDOOR=Trapdoor
LOADER_BUTTON_DOOR=Door
LOADER_BUTTON_FENCEGATE=Fencegate
LOADER_HELP_SETUP=§8/§eloader setup §8- §7Startet die Aufnahme der Aktionen
LOADER_SETUP_STOP_FIRST=§cBitte stoppe zuerst den Loader
LOADER_HELP_START=§8/§eloader start §8- §7Spielt die zuvor aufgenommenen Aktionen ab
LOADER_HELP_SINGLE=§8/§eloader single §8- §7Spielt die zuvor aufgenommenen Aktionen einmal ab
LOADER_HELP_PAUSE=§8/§7loader pause §8- §7Pausiert das Abspielen
LOADER_HELP_GUI=§8/§7loader settings §8- §7Zeigt die Einstellungen an
LOADER_HELP_STOP=§8/§eloader stop §8- §7Stoppt die Aufnahme bzw. das Abspielen
LOADER_HELP_WAIT=§8/§7loader wait §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Schüssen
LOADER_HELP_SPEED=§8/§7loader speed §8[§7Ticks§8] - §7Setzt die Wartezeit zwischen Aktionen
LOADER_NO_LOADER=§cDu hast noch keinen Loader. Erstelle dir einen mit /loader setup
LOADER_NEW=§7Belade und feuer einmal die Kanone ab, um den Loader zu initialisieren.
LOADER_HOW_TO_START=§7Führe dann /§eloader start§7 um den Loader zu starten
LOADER_ACTIVE=§7Der Loader ist nun aktiviert.
LOADER_STOP=§7Der Loader ist nun gestoppt.
LOADER_SINGLE_CMD=§7Der Loader spielt nun einmal ab.
LOADER_PAUSED=§7Der Loader ist nun pausiert.
LOADER_SMALL_TIME=§cDie Wartezeit ist zu klein
LOADER_NEW_TIME=§7Die Schusswartezeit ist nun: {0}
LOADER_NEW_LOAD_TIME=§7Die Setzwartezeit ist nun: {0}
LOADER_NOTHING_RECORDED=§cEs wurden keine Elemente aufgenommen!
LOADER_GUI_TITLE=Loader Einstellungen
LOADER_GUI_SHOW_ALL=Zeige alles
LOADER_GUI_SHOW_INTERACTIONS=Zeige Interaktionen
LOADER_GUI_SHOW_WAITS=Zeige Wartezeiten
LOADER_GUI_SHOW_WAITS_BETWEEN_TNT=Zeige Wartezeiten zwischen TNT
LOADER_GUI_SHOW_TNT=Zeige TNT
LOADER_GUI_SHOW_WAITS_SET_ALL=§7Wait Time alle
LOADER_GUI_SHOW_WAITS_TITLE=§7Wartezeit
LOADER_GUI_SETTINGS_TITLE=Einstellungen
LOADER_GUI_COPY_TITLE=Anzahl Kopien
LOADER_GUI_SETTINGS_BACK=§8Zurück
LOADER_GUI_SETTINGS_COPY=§7Kopieren
LOADER_GUI_SETTINGS_DELETE=§cLöschen
LOADER_GUI_WAIT_TITLE=Wartezeit
LOADER_GUI_WAIT_BACK=§8Zurück
LOADER_GUI_CLICK_TO_EDIT=§7Klicke zum editieren
LOADER_GUI_ITEM_NAME=§7{0}§8: §e{1}
LOADER_SETTING_NAME=§7{0}
LOADER_SETTING_MODES=§7Modi§8: §e{0}
LOADER_SETTING_POWER=§7Redstone Stärke§8: §e{0}
LOADER_SETTING_TICKS=§7Ticks§8: §e{0}
LOADER_SETTING_REPEATER=§7Repeater§8: §e{0}
LOADER_SETTING_WAIT=§7Wartezeit§8: §e{0} Tick(s)
LOADER_SETTING_WAIT_NAME=Wartezeit
LOADER_SETTING_TICKS_NAME=Ticks
LOADER_SETTING_TICKS_REMOVE_ONE=§c-1
LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT=§7Shift§8: §c-5
LOADER_SETTING_TICKS_ADD_ONE=§a+1
LOADER_SETTING_TICKS_ADD_ONE_SHIFT=§7Shift§8: §a+5
LOADER_SETTING_TNT_NAME=§cTNT
LOADER_SETTING_TNT_X=§7X§8: §e{0}
LOADER_SETTING_TNT_Y=§7Y§8: §e{0}
LOADER_SETTING_TNT_Z=§7Z§8: §e{0}
LOADER_INTERACTION_NOOP=NOOP
LOADER_INTERACTION_PLACE=Platzieren
LOADER_INTERACTION_INTERACT=Interagiere
LOADER_INTERACTION_POWERED=Aktiviert
LOADER_INTERACTION_UNPOWERED=Deaktiviert
LOADER_INTERACTION_PAGE_PREV=Vorherige Seite
LOADER_INTERACTION_PAGE_NEXT=Nächste Seite
LOADER_INTERACTION_PAGE=Seite {0}
LOADER_INTERACTION_ACTIVE=Aktiviert
LOADER_INTERACTION_INACTIVE=Deaktiviert
LOADER_INTERACTION_WAIT_FOR=Darauf warten
LOADER_INTERACTION_NO_WAIT_FOR=Nicht darauf warten
LOADER_INTERACTION_OPEN=Geöffnet
LOADER_INTERACTION_CLOSED=Geschlossen
LOADER_INTERACTION_COMPARE=Vergleichen
LOADER_INTERACTION_SUBTRACT=Subtrahieren
# Loadtimer
LOADTIMER_HELP_OVERVIEW=§7Messe dich und deine Freunde beim Beladen einer Kanone und bekomme informationen über die Kanone
LOADTIMER_HELP_START_1=§8/§eloadtimer start §8-§7 Startet den einfachen Loadtimer
LOADTIMER_HELP_START_2=§8/§7loadtimer start §8[§7full/half§8] - §7Starte den Timer in einem bestimmten Modus
LOADTIMER_HELP_START_3=§7Loadtimer Modis: Full -> Misst vom ersten TNT bis zur Treib-Explosion, kann somit besser die Schuss Frequent berechnen. Half -> Misst nur bis zur Aktivierung
LOADTIMER_HELP_STOP=§8/§eloadtimer stop §8-§7 Stoppe den Aktuellen Loadtimer
LOADTIMER_GUI_GLOBAL=§eLoadtimer gibt es nicht in der Global Region!
LOADTIMER_GUI_STOP=§eLoadtimer stoppen
LOADTIMER_GUI_START=§eLoadtimer starten
LOADTIMER_GUI_TITLE=Loadtimer Modus
LOADTIMER_GUI_FULL=§eFull
LOADTIMER_GUI_HALF=§eHalf
LOADTIMER_WAITING=§7Platziere ein TNT zum starten...
LOADTIMER_BOSSBAR=§7Tick: §e{0}§7(§e{1}§7) Zeit: §e{2}s §7Tnt: §e{3} §7Blöcke
LOADTIMER_ACTIVATED=§7Warte auf Zündung
LOADTIMER_IGNITION=§7Warte auf Explosion
LOADTIMER_SUMARY_HEAD=§7---=== (§eLoadtimer-Auswertung§7) ===---
LOADTIMER_SUMARY_PLAYERTABLE_HEAD=§7Spieler: §eTNT §7(§eTNT/s§7)
LOADTIMER_SUMARY_PLAYERTABLE_PLAYER=§7{0}: §e{1} §7(§e{2}/s§7)
LOADTIMER_SUMARY_PLAYERTABLE_ALL=Insgesamt
LOADTIMER_SUMARY_TIMES_HEAD=§7Zeiten: §eSekunden §7(§eTicks§7)
LOADTIMER_SUMARY_TIMES_START=§7 || §7Start!
LOADTIMER_SUMARY_TIMES_ACTIVATION=§7 || Aktivierung: §e{0}s §7(§e{1}t§7)
LOADTIMER_SUMARY_TIMES_IGNITION=§7 || Zündung: §e{0}s §7(§e{1}t§7)
LOADTIMER_SUMARY_TIMES_EXPLOSION=§7 || Explosion: §e{0}s §7(§e{1}t§7)
LOADTIMER_SUMARY_TIMES_LAST=§7\\/
LOADTIMER_SUMARY_STATS_HEAD=§7Kanonen-Stats§8:
LOADTIMER_SUMARY_STATS_TNT=§7TNT: §e{0}
LOADTIMER_SUMARY_STATS_FREQ=§7Belade Frequenz: §e{0}/m§8, §7Schuss Frequenz: §e{1}/m
# Observer
OBSERVER_HELP=§7Rechts-Klicke einen Observer um den Trace zu bekommen. Hierfür müssen Flammenpartikel an sein. Die Partikel werden im Block angezeigt.
OBSERVER_HELP_ENABLE=§8/§eobserver enable §8-§7 Aktiviere den Observer Tracer
OBSERVER_HELP_DISABLE=§8/§eobserver disable §8-§7 Deaktiviere den Observer Tracer
OBSERVER_HELP_DELETE=§8/§eobserver delete §8-§7 Lösche den Observer Tracer
OBSERVER_HELP_RETRACE=§8/§eobserver retrace §8-§7 Retrace den Observer Tracer
OBSERVER_ENABLE=§7Observer Trace gestartet
OBSERVER_DISABLE=§7Observer Trace gestoppt
OBSERVER_DELETE=§7Observer Trace gelöscht
OBSERVER_RETRACE_DONE=§7Observer Trace neu berechnet
OBSERVER_RETRACE_NO_TRACE=§7Kein Observer Trace zum neu berechnen
# Other
OTHER_ITEMS_TELEPORT_NAME=§eTeleporter
OTHER_ITEMS_TELEPORT_GUI_NAME=Teleportieren
OTHER_ITEMS_TELEPORT_PLAYER_OFFLINE=§cDer Spieler ist Offline
OTHER_ITEMS_CLEAR_NAME=§eClear
OTHER_ITEMS_DECLUTTER_NAME=§eDeclutter
OTHER_ITEMS_GAMEMODE_NAME=§eGamemode
OTHER_ITEMS_GAMEMODE_LORE_1=§eRechts-Click§8:§7 Umschalten zwischen Creative und Spectator
OTHER_ITEMS_GAMEMODE_LORE_2=§eLinks-Click§8:§7 Umschalten zwischen Survival und Adventure
OTHER_ITEMS_KILLALL_NAME=§eKillAll
OTHER_ITEMS_KILLALL_LORE_1=§eOhne Shift§8:§7 nur die Region
OTHER_ITEMS_KILLALL_LORE_2=§eMit Shift§8:§7 Global
OTHER_ITEMS_INVENTORY_FILL_LORE_ACTIVE=§aAktiviert
OTHER_ITEMS_INVENTORY_FILL_LORE_INACTIVE=§aDeaktiviert
OTHER_SLOT_INVALID_SLOT=§cInvalider Slot
OTHER_NOCLIP_SLOT_INFO=§7Mit /slot kannst du den ausgewählten Slot ändern und einen anderen Block in den Slot nehmen.
OTHER_NOCLIP_SLOT_HELP_PICK=§8/§eslot pick §8-§7 Lege den angeguckten Block ins Inventar
OTHER_NOCLIP_SLOT_HELP_DROP=§8/§eslot drop §8-§7 Cleared deinen Slot
OTHER_CLEAR_HELP_SELF=§8/§eclear §8- §7Leere dein Inventar
OTHER_CLEAR_HELP_PLAYER=§8/§eclear §8[§7Player§8] §8- §7Leere ein Spieler Inventar
OTHER_CLEAR_CLEARED=§7Dein Inventar wurde geleert.
OTHER_CLEAR_FROM=§7Dein Inventar wurde von {0} §7geleert.
OTHER_CLEAR_TO=§7Das Inventar von {0} §7wurde geleert.
OTHER_DECLUTTER_HELP=§8/§edeclutter §8- §7Räume dein Inventar auf
OTHER_DECLUTTER_DONE=§aDein Inventar wurde aufgeräumt.
OTHER_GAMEMODE_UNKNOWN=§cUnbekannter Spielmodus.
OTHER_GAMEMODE_POSSIBLE=§cMögliche Spielmodi: survival, adventure, creative, specator.
OTHER_KILLALL_HELP_SELF=§8/§ekillall §8- §7Entferne alle Entities aus deiner Region
OTHER_KILLALL_HELP_ALL=§8/§ekillall §8[§7Global§8/Local§7] §8- §7Entferne alle Entities aus deiner Region oder global
OTHER_KILLALL_REGION=§a{0} Entities aus der Region entfernt
OTHER_KILLALL_GLOBAL=§a{0} Entities aus der Welt entfernt
OTHER_TELEPORT_HELP=§8/§etp §8[§7Player§8] §8-§7 Teleportiere dich zu einem Spieler
OTHER_TELEPORT_SELF_0=§cSei eins mit dir selbst!
OTHER_TELEPORT_SELF_1=§cDu brauchst Leute zum spielen? Wir haben auch einen TeamSpeak!
OTHER_TELEPORT_SELF_2=§cNoch zu reisende Blöcke: 0; ETA: 0:00
OTHER_TELEPORT_SELF_3=§cEin wenig bewegung muss ein.
OTHER_TELEPORT_SELF_4=§cFür eine solche Distanz?
OTHER_TIME_HELP=§8/§etime §8<§7Zeit 0=Morgen§8, §76000=Mittag§8, §718000=Mitternacht§8> - §7Setzt die Zeit auf dem Bau
OTHER_TIME_INVALID=§cBitte gib eine Zahl zwischen 0 und 24000 an
OTHER_TIME_RESULT=§7§oWhooosh
OTHER_TPS_HEAD=§7TPS: 1s 10s 1m 5m 10m
OTHER_TPS_MESSAGE=§7 §e{0}§7 §e{1}§7 §e{2}§7 §e{3}§7 §e{4}
OTHER_TPS_SINGLE=§8TPS: §e{0}
OTHER_BIND_HELP=§8/§ebind §8[§7Command§8] §8-§e Binde ein Befehl auf Item Interaktion
OTHER_BIND_ERROR=§cFalscher oder unbekannter Befehl
OTHER_BIND_UNBINDABLE=§cBefehl konnte nicht gebunden werden
OTHER_BIND_MESSAGE_BIND=§7Befehl §e{0} §7ans Item gebunden
OTHER_BIND_MESSAGE_UNBIND=§7Befehl entbunden
# DebugStick
DEBUG_STICK_COMMAND_HELP=§8/§edebugstick §8-§7 Erhalte einen DebugStick
DEBUG_STICK_NAME=§eDebugstick
#Skull Gui
SKULL_GUI_ITEM_NAME=§eSpieler Köpfe
ANVIL_INV_NAME=Spieler name
# StructureVoid
STRUCTURE_VOID_COMMAND_HELP=§8/§estructureVoid §8-§7 Erhalte ein StructureVoid
# Dragon Egg
DRAGON_EGG_COMMAND_HELP=§8/§edragonegg §8-§7 Erhalte ein Drachenei
# NightVision
NIGHT_VISION_HELP=§8/§enightvision §8-§7 Schalte Nightvision an oder aus.
NIGHT_VISION_OFF=§eNightvision deaktiviert
NIGHT_VISION_ON=§eNightvision aktiviert
NIGHT_VISION_ITEM_ON=§7Nightvision: §eAktiviert
NIGHT_VISION_ITEM_OFF=§7Nightvision: §eDeaktiviert
#Navigation Wand
NAVIGATION_WAND=§eNavigation Wand
NAVIGATION_WAND_LEFT_CLICK=§eLeft click: jump to location
NAVIGATION_WAND_RIGHT_CLICK=§eRight click: pass through walls
# Material
MATERIAL_SEARCH_PROPERTY_TRUE=§aHat
MATERIAL_SEARCH_PROPERTY_FALSE=§cHat nicht
MATERIAL_SEARCH_PROPERTY_IGNORE=§eEgal
MATERIAL_INV_NAME=§eMaterial {0}/{1}
MATERIAL_SEARCH=§eSuchen
MATERIAL_BACK=§eZurück
MATERIAL_SEARCH_NAME=§eName
MATERIAL_SEARCH_TRANSPARENT=§eTransparent
MATERIAL_SEARCH_SOLID=§eSolide
MATERIAL_SEARCH_GRAVITY=§eFallend
MATERIAL_SEARCH_OCCLUDING=§eOccluding
MATERIAL_SEARCH_INTERACTEABLE=§eInterargierbar
MATERIAL_SEARCH_FLAMMABLE=§eFlammbar
MATERIAL_SEARCH_BURNABLE=§eBrennbar
MATERIAL_SEARCH_WATERLOGGABLE=§eWasserspeicherbar
MATERIAL_SEARCH_BLASTRESISTANCE=§eBlast Resistance
MATERIAL_SEARCH_VALUE=§8: §e{0}
MATERIAL_BLAST_RESISTANCE=§8- §eBlast Resistance§8: §7{0}
MATERIAL_HARDNESS=§8- §eHärte§8: §7{0}
MATERIAL_TNT_BREAKABLE=§8- §eZerstörbar durch TNT
MATERIAL_TNT_UNBREAKABLE=§8- §eNicht Zerstörbar durch TNT
MATERIAL_TRANSPARENT=§8- §eTransparenter Block
MATERIAL_SOLID=§8- §eSolider Block
MATERIAL_GRAVITY=§8- §eFallender Block
MATERIAL_OCCLUDING=§8- §eOccluding Block
MATERIAL_INTERACTABLE=§8- §eInterargierbarer Block
MATERIAL_FLAMMABLE=§8- §eFlammbarer Block
MATERIAL_BURNABLE=§8- §eBrennbarer Block
MATERIAL_WATERLOGGABLE=§8- §eWasserspeicherbarer Block
# Region Items
REGION_ITEM_COLOR=§7Color: §e{0}
REGION_ITEM_COLOR_CHOOSE=Farbe Wählen
REGION_ITEM_FIRE_ALLOW=§7Feuer: §eEingeschaltet
REGION_ITEM_FIRE_DISALLOW=§7Feuer: §eAusgeschaltet
REGION_ITEM_FREEZE_ALLOW=§7Freeze: §eEingeschaltet
REGION_ITEM_FREEZE_DISALLOW=§7Freeze: §eAusgeschaltet
REGION_ITEM_PROTECT_ALLOW=§7Protect: §eEingeschaltet
REGION_ITEM_PROTECT_DISALLOW=§7Protect: §eAusgeschaltet
REGION_ITEM_RESET=§eReset
REGION_ITEM_TESTBLOCK=§eTestblock
REGION_ITEM_TNT_OFF=§7TNT: §eAusgeschaltet
REGION_ITEM_TNT_ONLY_TB=§7TNT: §enur Testblock
REGION_ITEM_TNT_ONLY_BUILD=§7TNT: §enur Baubereich
REGION_ITEM_TNT_ON=§7TNT: §eEingeschaltet
REGION_ITEM_SELECTOR_TITLE=Tnt Modus
REGION_ITEM_SELECTOR_ON=§eEinschalten
REGION_ITEM_SELECTOR_ONLY_TB=§enur Testblock
REGION_ITEM_SELECTOR_ONLY_BUILD=§enur Baubereich
REGION_ITEM_SELECTOR_OFF=§eAusschalten
#Region
REGION_COLOR_HELP_COLOR=§8/§ecolor §8[§7Color§8] §8- §7Setze die Farbe der Region
REGION_COLOR_HELP_COLOR_TYPE=§8/§ecolor §8[§7Color§8] §8[§7Type§8] §8- §7Setze die Farbe der Region oder Global
REGION_COLOR_GLOBAL=§7Alle Regions farben auf §e{0}§7 gesetzt
REGION_COLOR_NO_REGION=§cDu befindest dich derzeit in keiner Region
REGION_FIRE_HELP=§8/§efire §8- §7Toggle Feuerschaden
REGION_FIRE_ENABLED=§cRegions Feuerschaden deaktiviert
REGION_FIRE_DISABLED=§aRegions Feuerschaden aktiviert
REGION_FREEZE_HELP=§8/§efreeze §8- §7Toggle Freeze
REGION_FREEZE_ENABLED=§cRegion eingefroren
REGION_FREEZE_DISABLED=§aRegion aufgetaut
REGION_ITEMS_HELP=§8/§eitems §8- §7Toggle Items
REGION_ITEMS_ENABLED=§aItems aktiviert in dieser Region
REGION_ITEMS_DISABLED=§cItems deaktiviert in dieser Region
REGION_PROTECT_HELP=§8/§eprotect §8- §7Schütze die Region
REGION_PROTECT_DISABLE=§cBoden Schutz aufgehoben
REGION_PROTECT_ENABLE=§aBoden geschützt
REGION_PROTECT_FALSE_REGION=§cDu befindest dich derzeit in keiner (M)WG-Region
REGION_NO_GRAVITY_HELP = §8/§enogravity §8- §7Toggle NoGravity
REGION_NO_GRAVITY_ENABLED = §aNoGravity aktiviert in dieser Region
REGION_NO_GRAVITY_DISABLED = §cNoGravity deaktiviert in dieser Region
REGION_REGION_HELP_UNDO=§8/§eregion undo §8- §7Mache die letzten 20 /testblock oder /reset rückgängig
REGION_REGION_HELP_REDO=§8/§eregion redo §8- §7Wiederhole die letzten 20 §8/§7rg undo
REGION_REGION_HELP_RESTORE=§8/§eregion restore §8- §7Setzte die Region zurück, ohne das Gebaute zu löschen
REGION_REGION_HELP_RESTORE_SCHEMATIC=§8/§eregion restore §8[§7Schematic§8] §8- §7Setzte die Region zurück, ohne das Gebaute zu löschen
REGION_REGION_HELP_COPYPOINT=§8/§eregion copypoint §8- §7Teleportiere dich zum Regions Kopierpunkt
REGION_REGION_HELP_TESTBLOCKPOINT=§8/§eregion testblockpoint §8- §7Teleportiere dich zum Regions Testblockpunkt
REGION_REGION_HELP_CHANGESKIN_INFO=§8/§eregion changeskin §8- §7Gebe den Regions Skin aus
REGION_REGION_HELP_CHANGESKIN=§8/§eregion changeskin §8[§7Skin§8] §8- §8Setzte den Regions Skin
REGION_REGION_HELP_COPY=§8/§eregion copy [-e] [-s] §8- §8Kopieren des Baubereichs optional mit Erweiterungen oder Auswahl am Kopierpunkt
REGION_REGION_HELP_PASTE=§8/§eregion paste [-a] [-s] §8[§7Skin§8] §8- §8Einfügen am Kopierpunkt optional ohne Luft und Auswahl des eingefügten Bereichs
REGION_REGION_NOTHING_UNDO=§cNichts zum rückgängig machen
REGION_REGION_UNDID=§7Letzte Aktion rückgangig gemacht
REGION_REGION_NOTHING_REDO=§cNichts zum wiederhohlen
REGION_REGION_REDID=§7Letzte Aktion wiederhohlt
REGION_REGION_RESTORED=§7Region zurückgesetzt
REGION_REGION_FAILED_RESTORE=§cFehler beim Zurücksetzen der Region
REGION_REGION_COLORED=§7Region umgefärbt
REGION_REGION_COLORED_FAILED=§7Nutze §e/rg restore§7 um manuell die Farbe zu ändern
REGION_REGION_FAILED_COLORED=§cFehler beim umfärben der Region
REGION_REGION_TP_COPY=§7Zum Kopierpunkt teleportiert
REGION_REGION_TP_TEST_BLOCK=§7Zum Testblock teleportiert
REGION_REGION_TP_UNKNOWN=§cNicht definierter Teleportierpunkt
REGION_REGION_NO_REGION=§cDu bist in keiner Region
REGION_REGION_NO_BUILD=§cDiese Region hat kein Baugebiet
REGION_REGION_COPY_DONE=§eBauregion oder Selektion kopiert
REGION_REGION_PASTE_DONE=§eBauregion oder Selektion eingefügt
REGION_REGION_CHANGESKIN_INFO=§7Regions Skin ist §e{0}
REGION_REGION_CHANGESKIN_INFO_CREATOR=§7Skin erstellt von §e{0}
REGION_REGION_CHANGESKIN_UNKNOWN=§cRegions Skin ist nicht valide
REGION_REGION_CHANGESKIN_INVALID=§cRegions Skin ist nicht erlaubt hier
REGION_REGION_CHANGESKIN_CHANGE=§7Regions Skin ist auf §e{0}§7 geändert
REGION_REGION_CHANGESKIN_CHANGE_UPDATE=§7Klicke §e§lHIER §7um den Skin anzuwenden
REGION_REGION_CHANGESKIN_CHANGE_UPDATE_HOVER=§8/§ereset
REGION_RESET_HELP_RESET=§8/§ereset §8- §7Setzte die Region zurück
REGION_RESET_HELP_SCHEMATIC=§8/§ereset §8[§7Schematic§8] §8- §7Setzte die Region mit einer Schematic zurück
REGION_RESET_RESETED=§7Region zurückgesetzt
REGION_RESET_ERROR=§cFehler beim Zurücksetzen der Region
REGION_RESET_NO_REGION=§cDu befindest dich derzeit in keiner Region
REGION_TB_HELP_RESET=§8/§etestblock §8- §7Setzte den Testblock zurück
REGION_TB_HELP_RESET_EXTENSION=§8/§etestblock §8[§7ExtensionType§8] §8- §7Setzte den Testblock zurück
REGION_TB_HELP_SCHEMATIC=§8/§etestblock §8[§7Schematic§8] §8- §7Setzte den Testblock mit einer Schematic zurück
REGION_TB_HELP_SCHEMATIC_EXTENSION=§8/§etestblock §8[§7Schematic§8] §8[§7ExtensionType§8] §8- §7Setzte den Testblock mit einer Schematic zurück
REGION_TB_DONE=§7Testblock zurückgesetzt
REGION_TB_ERROR=§cFehler beim Zurücksetzen des Testblocks
REGION_TB_NO_REGION=§cDu befindest dich derzeit in keiner Region
REGION_TB_NO_SCHEMSHARING=§cDu kannst aktuell keine Schematics teilen bis {0}.
REGION_TB_NO_SCHEMRECEIVING=§cDer Besitzer dieses Bauservers kann keine Schematics erhalten bis {0}.
REGION_TNT_HELP=§8/§etnt §8- §7Ändere das TNT verhalten
REGION_TNT_HELP_MODE=§8/§etnt §8[§7Mode§8] §8- §7Setzte das TNT verhalten auf einen Modus
REGION_TNT_ON=§aTNT-Schaden aktiviert
REGION_TNT_OFF=§cTNT-Schaden deaktiviert
REGION_TNT_TB=§aTNT-Schaden außerhalb Baurahmen aktiviert
REGION_TNT_BUILD_DESTROY=§cEine Explosion hätte Blöcke im Baubereich zerstört
REGION_TNT_TB_DESTROY=§cEine Explosion hätte Blöcke im Testblockbereich zerstört
AFK_KICK_MESSAGE=§cAuf diesem Server ist seit 15 Minuten nichts passiert.
AFK_WARNING_MESSAGE=§cDieser Server wird bei weiterer Inaktivität in einer Minute gestoppt
SKIN_HELP=§8/§eskin §8[§7Kuerzel§8] §8[§7Creator§8|§epublic§8] §8[§7Name...§8] §8- §7Erstellt die Skin Schematics. 'public' als Creator nutzen für keinen Creator, danach die nachricht an YoyoNow kopieren (mit Click kopieren)
SKIN_NO_REGION=§7Du steht in keiner Region, welche mit einem Skin versehen werden kann
SKIN_ALREADY_EXISTS=§cDieser Skin existiert in der Form bereits
SKIN_MESSAGE=§7Skin erstellt
SKIN_MESSAGE_HOVER=§eKlicken zum kopieren für YoyoNow und an diesen senden
# Panzern
PANZERN_HELP=§8/§epanzern §8[§7Block§8] §8[§7Slab§8] §8- §7Panzer deine WorldEdit Auswahl
PANZERN_PREPARE1=§71. Gucke nochmal nach, ob Läufe auch bis zur Panzergrenze führen.
PANZERN_PREPARE2=§72. Teppich in Gänge auf dem Boden vereinfacht das panzern.
PANZERN_PREPARE3=§73. Schildtechnik sollte explizit eingeschlossen sein.
PANZERN_PREPARE4=§74. Innerhalb der zu panzernden Region zu stehen, beim Befehlausführen kann das Panzern verbessern.
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[§7smallest§8|§7blastresistant§8] §8- §7Baue einen Lauf in deiner WorldEdit Auswahl mit den Traces
LAUFBAU_HELP_SETTINGS=§8/§elaufbau settings §8- §7Öffnet die Settings GUI
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_WORLDEDIT=§cDu hast keine WorldEdit Selection
LAUFBAU_STATE_FILTERING_TRACES=Traces filtern
LAUFBAU_STATE_PROCESSING_TRACES=Traces verbinden
LAUFBAU_STATE_CREATE_LAUF=Lauf erstellen
LAUFBAU_SIMPLE_PROGRESS=§e{0}§8: §e{1}§8/§e{2} §7Übrige Zeit §8: §e{3}
LAUFBAU_DONE=§aZuende gebaut
LAUFBAU_SETTINGS_GUI_NAME=§eLaufbau
LAUFBAU_SETTINGS_ACTIVE=§aAktiv
LAUFBAU_SETTINGS_INACTIVE=§cInaktiv
LAUFBAU_SETTINGS_MIXED=§e{0}§8/§e{1} §aAktiv
LAUFBAU_SETTINGS_GUI_BACK=§eBack
LAUFBAU_SETTINGS_TOGGLE=§eClick §8-§7 Toggle
LAUFBAU_SETTINGS_ADVANCED=§eMiddle-Click §8-§7 Erweiterte Einstellung
LAUFBAU_BLOCK_COBWEB=§eCobweb
LAUFBAU_BLOCK_GRASS_PATH=§eGrass Path
LAUFBAU_BLOCK_SOUL_SAND=§eSoul Sand
LAUFBAU_BLOCK_COCOA=§eCocoa
LAUFBAU_BLOCK_TURTLE_EGG=§eTurtle Eggs
LAUFBAU_BLOCK_CHEST=§eChest
LAUFBAU_BLOCK_SNOW=§eSnow Layer
LAUFBAU_BLOCK_PLAYER_WALL_HEAD=§ePlayer Wall Head
LAUFBAU_BLOCK_STONECUTTER=§eStonecutter
LAUFBAU_BLOCK_PLAYER_HEAD=§ePlayer Head
LAUFBAU_BLOCK_CAKE=§eCake
LAUFBAU_BLOCK_END_STONE_BRICK_SLAB=§eEndstone Brick Slabs
LAUFBAU_BLOCK_SEA_PICKLE=§eSea Pickles
LAUFBAU_BLOCK_CAMPFIRE=§eCampfire
LAUFBAU_BLOCK_FLOWER_POT=§eFlower Pot
LAUFBAU_BLOCK_IRON_TRAPDOOR=§eIron Trapdoor
LAUFBAU_BLOCK_LILY_PAD=§eLily Pad
LAUFBAU_BLOCK_WHITE_CARPET=§eCarpet
LAUFBAU_BLOCK_END_ROD=§eEnd Rod
LAUFBAU_BLOCK_LIGHTNING_ROD=§eLightning Rod
LAUFBAU_BLOCK_CONDUIT=§eConduit
LAUFBAU_BLOCK_BREWING_STAND=§eBrewing Stand
LAUFBAU_BLOCK_BELL=§eBell
LAUFBAU_BLOCK_GRINDSTONE=§eGrindstone
LAUFBAU_BLOCK_HOPPER=§eHopper
LAUFBAU_BLOCK_LANTERN=§eLantern
LAUFBAU_BLOCK_END_STONE_BRICK_STAIRS=§eEndstone Brick Stairs
LAUFBAU_BLOCK_CHORUS_PLANT=§eChorus Plant
LAUFBAU_BLOCK_NETHER_BRICK_FENCE=§eNether Brick Fence
LAUFBAU_BLOCK_IRON_BARS=§eIron Bars
LAUFBAU_BLOCK_END_STONE_BRICK_WALL=§eEndstone Brick Walls
LAUFBAU_BLOCK_CHAIN=§eChain
LAUFBAU_BLOCK_BIG_DRIP_LEAF=§eBig Drip Leaf
LAUFBAU_BLOCK_DRAGON_EGG=§eDragon Egg
LAUFBAU_BLOCK_AZALEA=§eAzalea
LAUFBAU_BLOCK_CANDLE=§eKerze
LAUFBAU_BLOCK_CANDLE_CAKE=§eKuchen mit Kerze
LAUFBAU_BLOCK_LECTERN=§eLectern
LAUFBAU_FACING_NORTH=§8-§7 Richtung Norden
LAUFBAU_FACING_SOUTH=§8-§7 Richtung Süden
LAUFBAU_FACING_WEST=§8-§7 Richtung Westen
LAUFBAU_FACING_EAST=§8-§7 Richtung Osten
LAUFBAU_FACING_UP=§8-§7 Richtung Oben
LAUFBAU_FACING_DOWN=§8-§7 Richtung Unten
LAUFBAU_COUNT_1=§8-§7 Anzahl 1
LAUFBAU_COUNT_2=§8-§7 Anzahl 2
LAUFBAU_COUNT_3=§8-§7 Anzahl 3
LAUFBAU_COUNT_4=§8-§7 Anzahl 4
LAUFBAU_LAYERS_8=§8-§7 Ebenen 8
LAUFBAU_LAYERS_7=§8-§7 Ebenen 7
LAUFBAU_LAYERS_6=§8-§7 Ebenen 6
LAUFBAU_LAYERS_3=§8-§7 Ebenen 3
LAUFBAU_LAYERS_2=§8-§7 Ebenen 2
LAUFBAU_TYPE_BOTTOM=§8-§7 Type Unten
LAUFBAU_TYPE_TOP=§8-§7 Type Oben
LAUFBAU_HALF_BOTTOM=§8-§7 Hälfte Unten
LAUFBAU_HALF_TOP=§8-§7 Hälfte Oben
LAUFBAU_OPEN=§8-§7 Geöffnet
LAUFBAU_ATTACHMENT_CEILING=§8-§7 Befestigung Decke
LAUFBAU_ATTACHMENT_FLOOR=§8-§7 Befestigung Boden
LAUFBAU_ATTACHMENT_DOUBLE_WALL=§8-§7 Befestigung beidseitige Wand
LAUFBAU_ATTACHMENT_SINGLE_WALL=§8-§7 Befestigung einseitige Wand
LAUFBAU_ATTACHMENT_WALL=§8-§7 Befestigung Wand
LAUFBAU_CONNECTION_FLOOR=§8-§7 Verbindung Boden
LAUFBAU_CONNECTION_NORTH=§8-§7 Verbindung Norden
LAUFBAU_CONNECTION_SOUTH=§8-§7 Verbindung Süden
LAUFBAU_CONNECTION_EAST=§8-§7 Verbindung Osten
LAUFBAU_CONNECTION_WEST=§8-§7 Verbindung Westen
LAUFBAU_CONNECTION_DOWN=§8-§7 Verbindung Unten
LAUFBAU_CONNECTION_UP=§8-§7 Verbindung Oben
LAUFBAU_HANGING=§8-§7 hängend
LAUFBAU_SHAPE_STRAIGHT=§8-§7 Form gerade
LAUFBAU_SHAPE_OUTER_LEFT=§8-§7 Form äußere links
LAUFBAU_SHAPE_INNER_LEFT=§8-§7 Form innere links
LAUFBAU_TILT_NONE=§8-§7 Neigung keine
LAUFBAU_TILT_PARTIAL=§8-§7 Neigung teilweise
# 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
SELECT_GLOBAL_REGION=§cDie globale Region kannst du nicht auswählen
SELECT_NO_TYPE=§cDiese Region hat keinen {0}
SELECT_NO_EXTENSION=§cDiese Region hat keine Ausfahrmaße
SELECT_MESSAGE=§7WorldEdit auswahl auf {0}, {1}, {2} und {3}, {4}, {5} gesetzt
SKULL_HELP=§8/§eskull §8[§eSpieler§8] §8-§7 Gibt einen SpielerKopf
SKULL_INVALID=§cUngültiger Spieler
SKULL_ITEM=§e{0}§8s Kopf
SPEED_HELP=§8/§espeed §8[§71§8-§710§8|§edefault§8] §8-§7 Setzte deine Flug- und Laufgeschindigkeit.
SPEED_CURRENT=§7Aktuelle geschwindigkeit§8: §e{0}
SPEED_TOO_SMALL=§c{0} ist zu klein
SPEED_TOO_HIGH=§c{0} ist zu hoch
SPEED_ITEM=§eGeschwindigkeit
SPEED_ITEM_LORE=§7Aktuell: §e
SPEED_TAB_NAME=Geschwindigkeit eingeben
WORLDEDIT_WAND=WorldEdit Wand
WORLDEDIT_LEFTCLICK=Left click: select pos #1
WORLDEDIT_RIGHTCLICK=Right click: select pos #2
TNT_CLICK_HEADER=§8---=== §eTNT §8===---
TNT_CLICK_ORDER=§eEntity Order§8: §e{0}
TNT_CLICK_FUSE_TIME=§eFuseTime§8: §e{0}
TNT_CLICK_POSITION_X=§7Position §eX§8: §e{0}
TNT_CLICK_POSITION_Y=§7Position §eY§8: §e{0}
TNT_CLICK_POSITION_Z=§7Position §eZ§8: §e{0}
TNT_CLICK_VELOCITY_X=§7Velocity §eX§8: §e{0}
TNT_CLICK_VELOCITY_Y=§7Velocity §eY§8: §e{0}
TNT_CLICK_VELOCITY_Z=§7Velocity §eZ§8: §e{0}
TNT_CLICK_COUNT=§7Anzahl §8: §e{0}
TNT_CLICK_ISOLATE=§eIsolieren
SELECT_ITEM_CHOOSE_EXTENSION=Extension auswählen
SELECT_ITEM_CHOOSE_SELECTION=Auswahl auswählen
SELECT_ITEM_NORMAL_EXTENSION=§eNormal
SELECT_ITEM_EXTENDED_EXTENSION=§eAusgefahren
SELECT_ITEM_SELECT=§eSelect
SELECT_ITEM_AUSWAHL=§7Auswahl: §7{0} {1}
SELECT_ITEM_RIGHT_CLICK=§7Rechtklick zum ändern
SELECT_ITEM_BAURAHMEN=§eBaurahmen
SELECT_ITEM_BAUPLATTFORM=§eBauplattform
SELECT_ITEM_TESTBLOCK=§eTestblock
CHESTFILLER_FILLED=§eKiste gefüllt
PISTON_HELP_1=§7Rechts Klick auf Piston mit einem Slime Ball berechnet dir die bewegten Blöcke.
PISTON_HELP_2=§7Die Anzahl ist Rot, wenn ein unmovable Block vorhanden ist.
PISTON_HELP_3=§7Die Anzahl ist Gelb, wenn zu viele Blöcke vorhanden sind.
PISTON_INFO=§7Bewegte Blöcke {0}{1}§8/§712
# Warp
WARP_LOC_X=§7X§8: §e{0}
WARP_LOC_Y=§7Y§8: §e{0}
WARP_LOC_Z=§7Z§8: §e{0}
WARP_EXISTS=§7Ein Warp mit dem namen §e{0} §7existiert bereits
WARP_NAME_RESERVED=§7Du kannst nicht §c{0} §7als name für einen Warp nutzen
WARP_CREATED=§7Der Warp §e{0} §7wurde erstellt
WARP_DELETE_HOVER=§e{0} §7löschen
WARP_DELETED=§e{0} §7wurde gelöscht
WARP_TELEPORT_HOVER=§7Zu §e{0} §7teleportieren
WARP_MATERIAL_CHOOSE=Material auswählen
WARP_GUI_NAME=Warps
WARP_GUI_NO=§cHier gibt es noch keine Warps
WARP_GUI_DISTANCE=§7Distanz: §e{0} §7Blöcke
WARP_GUI_LCLICK=§7Links klicken zum teleportieren
WARP_GUI_RCLICK=§7Rechts klicken zum editieren
WARP_INFO_NAME=§7Name: §e{0}
WARP_HELP_ADD=§8/§ewarp add §8[§7Name§8] §8- §7Erstelle einen neuen Warp Punkt
WARP_HELP_TELEPORT=§8/§ewarp §8[§7Name§8] §8- §7Teleportiere dich zu einen Warp-Punkt
WARP_HELP_INFO=§8/§ewarp info §8[§7Name§8] §8- §7Infos zu einem Punkt
WARP_HELP_DELETE=§8/§ewarp delete §8[§7Name§8] §8- §7Lösche einen Warp
WARP_HELP_GUI=§8/§ewarp gui §8- §7Öffne die Warp-GUI
WARP_HELP_LIST=§8/§ewarp list §8- §7Liste alle Warp-Punkt auf
# WORLD
STOP_HELP=§8/§estop §8- §7Stoppt den Server
STOP_MESSAGE=§eDer Server wird gestoppt
KICKALL_HELP=§8/§ekickall §8- §7Kickt alle Spieler vom Server außer den Owner
# Techhider
TECHHIDER_HELP=§8/§etechhider §8- §7Techhider umschalten
TECHHIDER_GLOBAL=§cKein Techhider in der globalen region
TECHHIDER_ON=§aTechhider aktiviert
TECHHIDER_OFF=§cTechHider deaktiviert
# XRAY
XRAY_HELP=§8/§exray §8- §7Xray umschalten
XRAY_GLOBAL=§cKein Xray in der globalen region
XRAY_ON=§aXray aktiviert
XRAY_OFF=§cXray deaktiviert
# WorldEdit
COLORREPLACE_HELP=§8//§ecolorreplace §8[§7color§8] §8[§7color§8] §8- §7Ersetzt eine Farbe mit einer anderen
TYPEREPLACE_HELP=§8//§etyreplace §8[§7type§8] §8[§7type§8] §8- §7Ersetzt einen Blockgruppe mit einer anderen
# Schematics
SCHEMATIC_GUI_ITEM=§eSchematics
@@ -0,0 +1,182 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.features.tpslimit.TPSFreezeUtils;
import de.steamwar.bausystem.linkage.LinkageUtils;
import de.steamwar.bausystem.region.loader.PrototypeLoader;
import de.steamwar.bausystem.region.loader.RegionLoader;
import de.steamwar.bausystem.region.loader.Updater;
import de.steamwar.bausystem.utils.TickListener;
import de.steamwar.bausystem.worlddata.WorldData;
import de.steamwar.command.AbstractValidator;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.message.Message;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.logging.Level;
public class BauSystem extends JavaPlugin implements Listener {
// This should be treated as final!
public static Message MESSAGE;
public static final boolean DEV_SERVER = !System.getProperty("user.home").endsWith("minecraft");
@Getter
private static BauSystem instance;
@Override
public void onEnable() {
// LOGGER
fixLogging();
MESSAGE = new Message("BauSystem", getClassLoader());
instance = this;
SWUtils.setBausystem(instance);
try {
PrototypeLoader.load();
RegionLoader.load();
} catch (SecurityException e) {
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
Bukkit.shutdown();
System.exit(1);
return;
}
new Updater(PrototypeLoader.file, PrototypeLoader::load);
new Updater(RegionLoader.file, RegionLoader::load);
SWCommandUtils.addValidator(Player.class, validator(Permission.BUILD));
SWCommandUtils.addValidator(CommandSender.class, validator(Permission.BUILD));
SWCommandUtils.addValidator("supervisor", validator(Permission.SUPERVISOR));
SWCommandUtils.addValidator("owner", validator(Permission.OWNER));
try {
LinkageUtils.link();
} catch (Exception e) {
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
Bukkit.shutdown();
System.exit(1);
return;
}
TickListener.impl.init();
}
private <T extends CommandSender> AbstractValidator<T, ?> validator(Permission permission) {
return (commandSender, object, messageSender) -> {
if (commandSender instanceof Player) {
if (permission.hasPermission((Player) commandSender)) {
return true;
}
messageSender.send("NO_PERMISSION");
return false;
}
return true;
};
}
@Override
public void onDisable() {
LinkageUtils.unlink();
WorldData.write();
Config.getInstance().saveAll();
TinyProtocol.instance.close();
}
private void fixLogging() {
System.setErr(new PrintStream(new OutputStream() {
private StringBuilder current = new StringBuilder();
@Override
public void write(int b) throws IOException {
if (b == '\n') {
String logging = current.toString();
if (logging.contains("SLF4J")) {
Bukkit.getLogger().info(logging);
} else {
Bukkit.getLogger().warning(logging);
}
current = new StringBuilder();
} else {
current.append((char) b);
}
}
}));
}
public static BukkitTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
return new BukkitRunnable() {
private int counter = 1;
@Override
public void run() {
if (TPSFreezeUtils.isFrozen()) return;
if (counter >= delay) {
runnable.run();
cancel();
return;
}
counter++;
}
}.runTaskTimer(plugin, 0, 1);
}
public static BukkitTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
return new BukkitRunnable() {
private int counter = 1;
private boolean first = true;
@Override
public void run() {
if (TPSFreezeUtils.isFrozen()) return;
if (counter >= (first ? delay : period)) {
first = false;
runnable.run();
counter = 1;
return;
}
counter++;
}
}.runTaskTimer(plugin, 0, 1);
}
public static void runTaskTimer(Plugin plugin, Consumer<BukkitTask> consumer, long delay, long period) {
AtomicReference<BukkitTask> task = new AtomicReference<>();
task.set(runTaskTimer(plugin, () -> consumer.accept(task.get()), delay, period));
}
}
@@ -0,0 +1,96 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.features.world.BauMemberUpdate;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.SteamwarUser;
import lombok.AllArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
@AllArgsConstructor
public enum Permission {
OWNER(bauweltMember -> false),
SUPERVISOR(bauweltMember -> {
return bauweltMember.isSupervisor();
}),
BUILD(bauweltMember -> {
if (isTempOnlySpectator(bauweltMember)) return false;
return bauweltMember.isBuild() || SUPERVISOR.permissionPredicate.test(bauweltMember);
}),
/**
* Only used for {@link BauMemberUpdate}
*/
REAL_SPECTATOR(bauweltMember -> {
return !bauweltMember.isBuild() && !bauweltMember.isSupervisor();
}),
/**
* Primarily used for {@link de.steamwar.bausystem.linkage.specific.GuiItem}
*/
MEMBER(bauweltMember -> {
return true;
});
private static final Set<Integer> TEMP_ONLY_SPECTATOR = new HashSet<>();
private static boolean isTempOnlySpectator(BauweltMember bauweltMember) {
return TEMP_ONLY_SPECTATOR.contains(bauweltMember.getMemberID());
}
public static boolean isTempOnlySpectator(Player player) {
return TEMP_ONLY_SPECTATOR.contains(SteamwarUser.get(player.getUniqueId()).getId());
}
public static void forceOnlySpectator(Player player) {
TEMP_ONLY_SPECTATOR.add(SteamwarUser.get(player.getUniqueId()).getId());
BauMemberUpdate.baumemberUpdate();
}
/**
* Only used by {@link BauMemberUpdate}
*/
public static void removeForceOnlySpectator(Player player) {
TEMP_ONLY_SPECTATOR.remove(SteamwarUser.get(player.getUniqueId()).getId());
}
private final Predicate<BauweltMember> permissionPredicate;
public boolean hasPermission(BauweltMember bauweltMember) {
if (bauweltMember == null) return false;
return permissionPredicate.test(bauweltMember);
}
public boolean hasPermission(Player member) {
if (SteamwarUser.get(member.getUniqueId()).getId() == BauServer.getInstance().getOwnerID()) {
return this != REAL_SPECTATOR;
}
BauweltMember bauweltMember = BauweltMember.getBauMember(BauServer.getInstance().getOwner(), member.getUniqueId());
if (bauweltMember == null) return this == REAL_SPECTATOR;
return permissionPredicate.test(bauweltMember);
}
}
@@ -0,0 +1,90 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem;
import de.steamwar.inventory.SWItem;
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.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.Plugin;
import java.util.function.Function;
@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;
}
for (int i = 0; i < player.getInventory().getSize(); i++) {
ItemStack current = player.getInventory().getItem(i);
if (current != null && current.isSimilar(itemStack)) {
player.getInventory().setItem(i, null);
itemStack = current;
break;
}
}
ItemStack current = player.getInventory().getItemInMainHand();
player.getInventory().setItemInMainHand(itemStack);
if (current.getType() != Material.AIR) {
player.getInventory().addItem(current);
}
}
public static SWItem setCustomModelData(SWItem item, int customModelData) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setCustomModelData(customModelData);
item.setItemMeta(itemMeta);
return item;
}
public static void sendToActionbar(Player p, String message) {
p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
}
public static void actionBar(Function<Player, String> message) {
Bukkit.getOnlinePlayers().forEach(player -> {
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message.apply(player)));
});
}
public static void message(Function<Player, String> message) {
Bukkit.getOnlinePlayers().forEach(player -> {
player.sendMessage(message.apply(player));
});
}
public static NamespacedKey getNamespaceKey(String name) {
return new NamespacedKey(getBausystem(), name);
}
}
@@ -0,0 +1,52 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.config;
import de.steamwar.linkage.Linked;
import de.steamwar.providers.BauServerInfo;
import de.steamwar.sql.SteamwarUser;
import lombok.Getter;
import java.util.UUID;
@Linked
public class BauServer {
@Getter
private static BauServer instance;
public BauServer() {
instance = this;
}
private Integer owner;
public UUID getOwner() {
return SteamwarUser.get(getOwnerID()).getUUID();
}
public int getOwnerID() {
//Lazy loading to improve startup time of the server in 1.15
if (owner == null) {
owner = BauServerInfo.getOwnerId();
}
return owner;
}
}
@@ -0,0 +1,147 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.configplayer;
import de.steamwar.bausystem.configplayer.serializer.ConfigurationSerializableSerializer;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.UserConfig;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import yapion.hierarchy.output.StringOutput;
import yapion.hierarchy.types.YAPIONObject;
import yapion.parser.YAPIONParser;
import yapion.serializing.SerializeManager;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
@Linked
public class Config implements Listener {
static {
SerializeManager.add(new ConfigurationSerializableSerializer());
}
@Getter
private static Config instance;
{
instance = this;
}
private final Map<UUID, YAPIONObject> playerConfigurations = new HashMap<>();
private static final Map<Integer, ConfigConverter> CONFIG_CONVERTER_MAP = new HashMap<>();
public static void addConfigConverter(ConfigConverter configConverter) {
CONFIG_CONVERTER_MAP.putIfAbsent(configConverter.version(), configConverter);
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
get(event.getPlayer());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
save(event.getPlayer());
playerConfigurations.remove(event.getPlayer().getUniqueId());
}
/**
* Get a PlayerConfig, optionally loads it from the DataBase and migrates it if necessary.
*
* @param player the player from whom to get the config.
* @return the config object
*/
public YAPIONObject get(Player player) {
UUID uuid = player.getUniqueId();
if (!playerConfigurations.containsKey(uuid)) {
String s = UserConfig.getConfig(uuid, "bausystem");
YAPIONObject yapionObject;
if (s == null) {
yapionObject = ConfigCreator.createDefaultConfig();
} else {
yapionObject = YAPIONParser.parse(s);
}
yapionObject = update(yapionObject);
playerConfigurations.put(uuid, yapionObject);
return yapionObject;
}
return playerConfigurations.get(uuid);
}
public void saveAll() {
playerConfigurations.forEach((uuid, yapionObject) -> {
String string = yapionObject.toYAPION(new StringOutput()).getResult().replaceAll("\\+", "\\");
UserConfig.updatePlayerConfig(uuid, "bausystem", string);
});
playerConfigurations.clear();
}
/**
* Save a PlayerConfig, this does not remove the key value mapping from the map.
*
* @param player the player to save the config.
*/
public void save(Player player) {
UUID uuid = player.getUniqueId();
if (playerConfigurations.containsKey(uuid)) {
YAPIONObject yapionObject = playerConfigurations.get(uuid);
String string = yapionObject.toYAPION(new StringOutput()).getResult().replaceAll("\\\\+", "\\\\");
UserConfig.updatePlayerConfig(uuid, "bausystem", string);
}
}
private YAPIONObject update(YAPIONObject yapionObject) {
int version = yapionObject.getPlainValue("@version");
while (version < ConfigCreator.currentVersion) {
ConfigConverter configConverter = CONFIG_CONVERTER_MAP.getOrDefault(version, null);
if (configConverter == null) {
Bukkit.getLogger().log(Level.SEVERE, "No updater found for version " + version);
return ConfigCreator.createDefaultConfig();
}
try {
configConverter.update(yapionObject);
} catch (Exception e) {
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
return ConfigCreator.createDefaultConfig();
}
int newVersion = yapionObject.getPlainValue("@version");
if (version == newVersion) {
Bukkit.getLogger().log(Level.SEVERE, "Version Tag was the same after conversion");
return ConfigCreator.createDefaultConfig();
}
if (newVersion < version) {
Bukkit.getLogger().log(Level.SEVERE, "Version Tag was earlier after conversion");
return ConfigCreator.createDefaultConfig();
}
version = newVersion;
}
return yapionObject;
}
}
@@ -0,0 +1,37 @@
package de.steamwar.bausystem.configplayer;
import yapion.hierarchy.types.YAPIONObject;
/**
* A new {@link ConfigConverter} should be written when you remove anything
* from the Config or modify any mayor part. When you move anything from
* any key to any other key you should write a new {@link ConfigConverter}.
* For adding any new key you should be able to get the default without
* having it in the Config. Anything you need to change you should also
* change the {@link ConfigCreator} accordingly, to produce the new Config.
*/
public interface ConfigConverter {
/**
* This describes the version this Converter can convert from. The version
* it should convert to is the version 1 above this number. But this is not
* a necessity. In the config Object as parameter given in {@link #update(YAPIONObject)}
* you should update the <b>@version</b> variable in the root object to the
* new version this converter produced.
*
* @return the version number
*/
int version();
/**
* This method should update everything needed to go from a lower config
* version to a higher. It should update the <b>@version</b> variable
* accordingly. Anything else is up the implementation. If anything goes wrong
* do not silently exit this method, throw an Exception. The updater Code will
* deal with it. Never leave the inputted object in a corrupted state.
*
* @param config the config object to update
*/
void update(YAPIONObject config);
}
@@ -0,0 +1,61 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.configplayer;
import de.steamwar.bausystem.features.hotbar.DefaultHotbar;
import lombok.experimental.UtilityClass;
import yapion.hierarchy.types.YAPIONObject;
@UtilityClass
public class ConfigCreator {
public static final int currentVersion = 1;
public YAPIONObject createDefaultConfig() {
YAPIONObject yapionObject = new YAPIONObject();
// This call should never be touched
yapionObject.add("@version", currentVersion);
// Any initialising goes into here
yapionObject.add("baugui", defaultBauGui());
// Default Hotbar Gui
yapionObject.add("hotbar", DefaultHotbar.defaultHotbar());
return yapionObject;
}
private YAPIONObject defaultBauGui() {
YAPIONObject yapionObject = new YAPIONObject();
// 0: ? | 1: ? | 2: 10 | 3: 3 | 4: 7 | 5: 17 | 6: 15 | 7: ? | 8: ?
// 9: 5 | 10: ? | 11: ? | 12: ? | 13: ? | 14: ? | 15: ? | 16: ? | 17: 16
// 18: 4 | 19: ? | 20: 19 | 21: 21 | 22: 9 | 23: 0 | 24: 1 | 25: ? | 26: 11
// 27: 6 | 28: ? | 29: ? | 30: ? | 31: ? | 32: ? | 33: ? | 34: ? | 35: 18
// 36: ? | 37: 23 | 38: 20 | 39: 8 | 40: 22 | 41: 26 | 42: 12 | 43: 14 | 44: ?
yapionObject.add("10", 2).add("3", 3).add("7", 4).add("17", 5).add("15", 6);
yapionObject.add("5", 9).add("4", 18).add("6", 27);
yapionObject.add("16", 17).add("11", 26).add("18", 35);
yapionObject.add("19", 20).add("21", 21).add("9", 22).add("0", 23).add("1", 24);
yapionObject.add("23", 37).add("20", 38).add("8", 39).add("22", 40).add("26", 41).add("12", 42).add("14", 43);
yapionObject.add("size", 45);
return yapionObject;
}
}
@@ -0,0 +1,90 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.configplayer.serializer;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import yapion.hierarchy.api.groups.YAPIONAnyType;
import yapion.hierarchy.types.YAPIONObject;
import yapion.serializing.api.SerializerObject;
import yapion.serializing.data.DeserializeData;
import yapion.serializing.data.SerializeData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import static yapion.utils.IdentifierUtils.TYPE_IDENTIFIER;
public class ConfigurationSerializableSerializer extends SerializerObject<ConfigurationSerializable> {
@Override
public Class<ConfigurationSerializable> type() {
return ConfigurationSerializable.class;
}
@Override
public boolean isInterface() {
return true;
}
@Override
public YAPIONObject serialize(SerializeData<ConfigurationSerializable> serializeData) {
YAPIONObject yapionObject = new YAPIONObject();
yapionObject.add(TYPE_IDENTIFIER, serializeData.object.getClass().getTypeName());
if (serializeData.object instanceof ItemStack) {
yapionObject.add(TYPE_IDENTIFIER, ItemStack.class.getTypeName());
}
if (serializeData.object instanceof ItemMeta) {
yapionObject.add(TYPE_IDENTIFIER, ItemMeta.class.getTypeName());
}
Map<String, Object> serializeDataMap = serializeData.object.serialize();
serializeDataMap.forEach((s, o) -> {
YAPIONAnyType yapionAnyType = serializeData.serialize(o);
if (yapionAnyType instanceof YAPIONObject) {
YAPIONObject object = (YAPIONObject) yapionAnyType;
if (object.containsKey(TYPE_IDENTIFIER) && object.getPlainValue(TYPE_IDENTIFIER).equals("com.google.common.collect.RegularImmutableList")) {
object.put(TYPE_IDENTIFIER, ArrayList.class.getTypeName());
}
}
yapionObject.add(s, yapionAnyType);
});
return yapionObject;
}
@Override
public ConfigurationSerializable deserialize(DeserializeData<YAPIONObject> deserializeData) {
Map<String, Object> deserializeDataMap = new HashMap<>();
deserializeData.object.forEach((s, yapionAnyType) -> {
if (s.equals(TYPE_IDENTIFIER)) {
if (yapionAnyType.toString().equals("(org.bukkit.inventory.meta.ItemMeta)")) {
deserializeDataMap.put("==", "ItemMeta");
} else {
deserializeDataMap.put("==", deserializeData.deserialize(yapionAnyType));
}
return;
}
deserializeDataMap.put(s, deserializeData.deserialize(yapionAnyType));
});
return ConfigurationSerialization.deserializeObject(deserializeDataMap);
}
}
@@ -0,0 +1,112 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.attributescopy;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.MinVersion;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@Linked
public class AttributeRemoveCommand extends SWCommand {
public AttributeRemoveCommand() {
super("removeattribute", "attributesremove");
}
@Register({"all"})
@Register({"*"})
public void genericCommand(@Validator Player player) {
ItemStack itemStack = player.getInventory().getItemInMainHand();
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setLore(new ArrayList<>());
itemStack.setItemMeta(itemMeta);
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_ALL", player);
}
@Register(description = "ATTRIBUTE_REMOVE_COMMAND_HELP")
public void genericCommand(@Validator Player player, @Mapper("attribute") String attribute) {
ItemStack itemStack = player.getInventory().getItemInMainHand();
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) {
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_NOT_FOUND", player);
return;
}
List<String> lore = itemMeta.getLore();
if (lore == null) {
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_NOT_FOUND", player);
return;
}
if (lore.isEmpty()) {
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_NOT_FOUND", player);
return;
}
if (!lore.get(0).equals("§eAttributes§8:")) {
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_NOT_FOUND", player);
return;
}
lore.removeIf(s -> s.startsWith("§8-§7 " + attribute + "§8:"));
if (lore.size() == 1) {
itemStack.setItemMeta(null);
} else {
itemMeta.setLore(lore);
itemStack.setItemMeta(itemMeta);
}
BauSystem.MESSAGE.send("ATTRIBUTE_REMOVE_SINGLE", player, attribute);
}
@Mapper(value = "attribute", local = true)
public TypeMapper<String> attribute() {
return new TypeMapper<String>() {
@Override
public Collection<String> tabCompletes(CommandSender commandSender, PreviousArguments previousArguments, String s) {
Player player = (Player) commandSender;
ItemStack itemStack = player.getInventory().getItemInMainHand();
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) return null;
List<String> lore = itemMeta.getLore();
if (lore == null) return null;
if (lore.isEmpty()) return null;
if (!lore.get(0).equals("§eAttributes§8:")) return null;
return lore.stream()
.skip(1)
.map(s1 -> s1.substring(6))
.map(s1 -> s1.substring(0, s1.indexOf("§8:")))
.collect(Collectors.toList());
}
@Override
public String map(CommandSender commandSender, PreviousArguments previousArguments, String s) {
return s;
}
};
}
}
@@ -0,0 +1,128 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.attributescopy;
import lombok.experimental.UtilityClass;
import org.bukkit.block.data.BlockData;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@UtilityClass
public class AttributeUtils {
private Map<Method, String> names = new HashMap<>();
private Map<Class<?>, List<Method>> getters = new HashMap<>();
private Map<Class<?>, Map<String, Method>> setters = new HashMap<>();
private void generate(BlockData blockData) {
Class<? extends BlockData> clazz = blockData.getClass();
if (getters.containsKey(clazz) && setters.containsKey(clazz)) return;
Map<String, List<Method>> methods = new HashMap<>();
for (Method declaredMethod : clazz.getMethods()) {
String s = declaredMethod.getName();
if (s.startsWith("get") && declaredMethod.getParameterCount() == 0) {
methods.computeIfAbsent(s.substring(3), aClass -> new ArrayList<>()).add(declaredMethod);
} else if (s.startsWith("is") && declaredMethod.getParameterCount() == 0) {
methods.computeIfAbsent(s.substring(2), aClass -> new ArrayList<>()).add(declaredMethod);
} else if (s.startsWith("set") && declaredMethod.getParameterCount() == 1) {
methods.computeIfAbsent(s.substring(3), aClass -> new ArrayList<>()).add(declaredMethod);
}
}
for (Map.Entry<String, List<Method>> entry : methods.entrySet()) {
if (entry.getValue().size() != 2) continue;
for (Method method : entry.getValue()) {
names.put(method, entry.getKey());
if (method.getName().startsWith("is") || method.getName().startsWith("get")) {
getters.computeIfAbsent(clazz, aClass -> new ArrayList<>()).add(method);
} else {
setters.computeIfAbsent(clazz, aClass -> new HashMap<>()).put(entry.getKey(), method);
}
}
}
}
public void copy(BlockData blockData, List<String> attributes) {
generate(blockData);
getters.getOrDefault(blockData.getClass(), new ArrayList<>()).forEach(method -> {
try {
Object invoke = method.invoke(blockData);
if (invoke != null) {
attributes.add("§8-§7 " + names.get(method) + "§8:§7 " + convert(invoke));
}
} catch (Exception e) {
// ignore
}
});
}
public void paste(BlockData blockData, List<String> attributes) {
generate(blockData);
for (String attribute : attributes) {
String[] split = attribute.split("§8:§7 ");
if (split.length != 2) continue;
String name = split[0].substring(6);
String value = split[1];
Method method = setters.getOrDefault(blockData.getClass(), new HashMap<>()).get(name);
if (method == null) continue;
try {
method.invoke(blockData, convert(value, method.getParameterTypes()[0]));
} catch (Exception e) {
// ignore
}
}
}
private String convert(Object o) {
if (o.getClass().isEnum()) {
return ((Enum<?>) o).name();
} else {
return o.toString();
}
}
private Object convert(String s, Class<?> type) {
if (type.isEnum()) {
return Enum.valueOf((Class<? extends Enum>) type, s);
} else if (type == int.class || type == Integer.class) {
return Integer.parseInt(s);
} else if (type == double.class || type == Double.class) {
return Double.parseDouble(s);
} else if (type == float.class || type == Float.class) {
return Float.parseFloat(s);
} else if (type == long.class || type == Long.class) {
return Long.parseLong(s);
} else if (type == short.class || type == Short.class) {
return Short.parseShort(s);
} else if (type == byte.class || type == Byte.class) {
return Byte.parseByte(s);
} else if (type == boolean.class || type == Boolean.class) {
return Boolean.parseBoolean(s);
} else {
return s;
}
}
}
@@ -0,0 +1,88 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.attributescopy;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
@Linked
public class AttributesCopyCommand extends SWCommand {
public AttributesCopyCommand() {
super("copyattributes", "attributescopy", "ac");
}
@Register
public void genericCommand(@Validator Player player) {
Block block = player.getTargetBlockExact(8, FluidCollisionMode.ALWAYS);
if (block == null) return;
ItemStack mainHand = player.getInventory().getItemInMainHand();
if (!(block.getType().isItem() && block.getType() == mainHand.getType() || isSame(block, mainHand))) {
BauSystem.MESSAGE.send("ATTRIBUTES_CANT_COPY", player);
return;
}
BlockData blockData = block.getBlockData();
List<String> attributesToCopy = new ArrayList<>();
if (block.getType() != mainHand.getType()) {
attributesToCopy.add("§8-§7 Material§8:§7 " + block.getType().name());
}
AttributeUtils.copy(blockData, attributesToCopy);
if (attributesToCopy.isEmpty()) {
BauSystem.MESSAGE.send("ATTRIBUTES_NO_COPY", player);
return;
}
ItemMeta itemMeta = mainHand.getItemMeta();
List<String> lore = new ArrayList<>(attributesToCopy);
lore.add(0, "§eAttributes§8:");
itemMeta.setLore(lore);
mainHand.setItemMeta(itemMeta);
player.getInventory().setItemInMainHand(mainHand);
BauSystem.MESSAGE.send("ATTRIBUTES_COPIED", player);
}
private boolean isSame(Block block, ItemStack itemStack) {
if (itemStack.getType() == Material.REDSTONE && block.getType() == Material.REDSTONE_WIRE) return true;
if (itemStack.getType() == Material.PLAYER_HEAD && block.getType() == Material.PLAYER_WALL_HEAD) return true;
if (itemStack.getType() == Material.ZOMBIE_HEAD && block.getType() == Material.ZOMBIE_WALL_HEAD) return true;
if (itemStack.getType() == Material.CREEPER_HEAD && block.getType() == Material.CREEPER_WALL_HEAD) return true;
if (itemStack.getType() == Material.DRAGON_HEAD && block.getType() == Material.DRAGON_WALL_HEAD) return true;
if (itemStack.getType() == Material.SKELETON_SKULL && block.getType() == Material.SKELETON_WALL_SKULL) return true;
if (itemStack.getType() == Material.WITHER_SKELETON_SKULL && block.getType() == Material.WITHER_SKELETON_WALL_SKULL) return true;
if (itemStack.getType() == Material.TORCH && block.getType() == Material.WALL_TORCH) return true;
if (itemStack.getType() == Material.SOUL_TORCH && block.getType() == Material.SOUL_WALL_TORCH) return true;
if (itemStack.getType() == Material.REDSTONE_TORCH && block.getType() == Material.REDSTONE_WALL_TORCH) return true;
if (itemStack.getType() == Material.WHEAT_SEEDS && block.getType() == Material.WHEAT) return true;
if (itemStack.getType().name().contains("_BANNER") && block.getType().name().contains("_WALL_BANNER")) return true;
return false;
}
}
@@ -0,0 +1,88 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.attributescopy;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.Skull;
import org.bukkit.block.data.BlockData;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.List;
@Linked
public class AttributesPlaceListener implements Listener {
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
ItemStack itemStack = event.getItemInHand();
ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta == null) return;
List<String> strings = itemMeta.getLore();
if (strings == null) return;
if (strings.isEmpty()) return;
if (!strings.get(0).equals("§eAttributes§8:")) return;
Material type = event.getBlock().getType();
OfflinePlayer offlinePlayer = null;
if (event.getBlock().getState() instanceof Skull) {
Skull skull = (Skull) event.getBlock().getState();
offlinePlayer = skull.getOwningPlayer();
}
OfflinePlayer finalPlayerProfile = offlinePlayer;
event.setCancelled(true);
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
Material material = strings.stream()
.filter(s -> s.startsWith("§8-§7 Material§8:§7 "))
.map(s -> s.replace("§8-§7 Material§8:§7 ", ""))
.map(String::toUpperCase)
.map(s -> {
try {
return Material.valueOf(s);
} catch (Exception e) {
return null;
}
})
.findFirst()
.orElse(type);
event.getBlock().setType(material, false);
Block block = event.getBlock();
BlockData blockData = block.getBlockData();
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
if (block.getState() instanceof Skull && finalPlayerProfile != null) {
Skull skull = (Skull) block.getState();
skull.setOwningPlayer(finalPlayerProfile);
skull.update(true, false);
}
}, 1);
AttributeUtils.paste(blockData, strings);
block.setBlockData(blockData, false);
}, 1);
}
}
@@ -0,0 +1,38 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.autostart;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class AutoStartCommand extends SWCommand {
public AutoStartCommand() {
super("timer", "autostarttimer", "at", "autostart");
}
@Register(description = "AUTOSTART_COMMAND_HELP")
public void genericCommand(@Validator Player p) {
SWUtils.giveItemToPlayer(p, AutostartListener.getWandItem(p));
}
}
@@ -0,0 +1,55 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.autostart;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@Linked
public class AutoStartGuiItem extends BauGuiItem {
public AutoStartGuiItem() {
super(24);
}
@Override
public ItemStack getItem(Player player) {
ItemStack itemStack = AutostartListener.getWandItem(player);
itemStack.setType(Material.FIREWORK_STAR);
return itemStack;
}
@Override
public boolean click(ClickType click, Player p) {
p.closeInventory();
p.performCommand("timer");
return false;
}
@Override
public Permission permission() {
return Permission.BUILD;
}
}
@@ -0,0 +1,150 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.autostart;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.RegionUtils;
import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.data.type.Chest;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
@Linked
public class AutostartListener implements Listener {
@Getter
public static AutostartListener instance;
{
instance = this;
}
public static ItemStack getWandItem(Player player) {
ItemStack itemStack = new SWItem(Material.FIREWORK_STAR, BauSystem.MESSAGE.parse("AUTOSTART_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("AUTOSTART_ITEM_LORE", player)), false, null).getItemStack();
ItemUtils.setItem(itemStack, "autostart");
return itemStack;
}
@Getter
private Map<Region, Long> regionStartTime = new HashMap<>();
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!ItemUtils.isItem(event.getItem(), "autostart")) {
return;
}
if (event.getClickedBlock() == null) {
return;
}
if (event.getClickedBlock().getBlockData() instanceof Chest) {
return;
}
if (event.getClickedBlock().getType() == Material.BEDROCK) {
event.getClickedBlock().setType(Material.SLIME_BLOCK);
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
event.getClickedBlock().setType(Material.BEDROCK, false);
}, 1);
}
activate(event.getPlayer());
}
@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
if (!(event.getPlayer() instanceof Player)) {
return;
}
if(!Permission.BUILD.hasPermission((Player) event.getPlayer())) return;
if (!ItemUtils.isItem(event.getPlayer().getInventory().getItemInMainHand(), "autostart")) {
return;
}
if (event.getInventory().getLocation() == null) {
return;
}
if (event.getInventory().getLocation().getBlock().getBlockData() instanceof Chest) {
activate((Player) event.getPlayer());
}
}
public void activate(Player player) {
Region region = Region.getRegion(player.getLocation());
if (region.isGlobal()) {
BauSystem.MESSAGE.send("AUTOSTART_MESSAGE_NO_REGION", player);
return;
}
if (!region.hasType(RegionType.TESTBLOCK)) {
BauSystem.MESSAGE.send("AUTOSTART_MESSAGE_NO_REGION", player);
return;
}
if (regionStartTime.containsKey(region)) {
BauSystem.MESSAGE.send("AUTOSTART_MESSAGE_RESET", player);
} else {
BauSystem.MESSAGE.send("AUTOSTART_MESSAGE_START", player);
}
regionStartTime.put(region, TPSUtils.currentRealTick.get());
}
@EventHandler
public void onEntityExplode(EntityExplodeEvent event) {
if (regionStartTime.isEmpty()) {
return;
}
event.blockList().forEach(block -> {
Region region = Region.getRegion(block.getLocation());
if (!regionStartTime.containsKey(region)) return;
if (!region.hasType(RegionType.TESTBLOCK)) return;
if (!region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) return;
long tickDiff = TPSUtils.currentRealTick.get() - regionStartTime.remove(region);
long preFightDurationInSeconds = getPreFightDurationInSeconds(region);
RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT1", tickDiff);
RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT2", preFightDurationInSeconds, ((preFightDurationInSeconds * 20) - tickDiff));
RegionUtils.message(region, "AUTOSTART_MESSAGE_RESULT3");
});
}
private int getPreFightDurationInSeconds(Region region) {
File file = region.gameModeConfig();
if (file == null) return 30;
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
return config.getInt("Times.PreFightDuration", 30);
}
}
@@ -0,0 +1,154 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.backup;
import com.sk89q.worldedit.EditSession;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.region.Color;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.bausystem.region.flags.flagvalues.ColorMode;
import de.steamwar.bausystem.region.tags.Tag;
import de.steamwar.bausystem.utils.PasteBuilder;
import de.steamwar.command.SWCommand;
import de.steamwar.command.SWCommandUtils;
import de.steamwar.command.TypeMapper;
import de.steamwar.command.TypeValidator;
import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import de.steamwar.linkage.Linked;
import net.md_5.bungee.api.chat.ClickEvent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Linked
public class BackupCommand extends SWCommand {
public BackupCommand() {
super("backup", "bu");
}
static boolean checkGlobalRegion(Region region, Player p) {
if (region.isGlobal()) {
BauSystem.MESSAGE.send("BACKUP_REGION_NO_REGION", p);
return true;
}
return false;
}
@Register(value = "create", description = "BACKUP_HELP_CREATE")
public void backupCreate(@Validator("owner") Player p) {
Region region = Region.getRegion(p.getLocation());
if (checkGlobalRegion(region, p)) {
return;
}
if (!region.get(Tag.CHANGED)) {
BauSystem.MESSAGE.send("BACKUP_CREATE_NO_CHANGE", p);
return;
}
if (region.backup()) {
BauSystem.MESSAGE.send("BACKUP_CREATE_SUCCESS", p);
} else {
BauSystem.MESSAGE.send("BACKUP_CREATE_FAILURE", p);
}
}
@Register(value = "load", description = "BACKUP_HELP_LOAD")
public void backupLoad(@Validator("owner") Player p, @Mapper("backupName") String backupName) {
Region region = Region.getRegion(p.getLocation());
if (checkGlobalRegion(region, p)) {
return;
}
File backupFile = region.getBackupFile(backupName.replace('_', ' '));
if (backupFile == null) {
BauSystem.MESSAGE.send("BACKUP_LOAD_FAILURE", p);
return;
}
EditSession editSession = new PasteBuilder(new PasteBuilder.FileProvider(backupFile))
.pastePoint(region.getMinPoint().add(region.getPrototype().getSizeX() / 2, 0, region.getPrototype().getSizeZ() / 2))
.minPoint(region.getMinPoint())
.maxPoint(region.getMaxPoint())
.waterLevel(region.getWaterLevel())
.run();
region.remember(editSession);
BauSystem.MESSAGE.send("BACKUP_LOAD", p);
}
@Register(value = "list", description = "BACKUP_HELP_LIST")
public void backupList(Player p) {
Region region = Region.getRegion(p.getLocation());
if (checkGlobalRegion(region, p)) {
return;
}
List<String> backups = listBackup(p);
BauSystem.MESSAGE.send("BACKUP_LIST_HEAD", p, backups.size());
backups.forEach(s -> {
BauSystem.MESSAGE.send("BACKUP_LIST_ENTRY", p, "/backup load " + s, new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/backup load " + s), s);
});
}
@Register(value = "gui", description = "BACKUP_HELP_GUI")
public void backupGui(Player p) {
Region region = Region.getRegion(p.getLocation());
if (checkGlobalRegion(region, p)) {
return;
}
List<String> backups = listBackup(p);
List<SWListInv.SWListEntry<String>> swListEntries = new ArrayList<>();
List<String> lore = Arrays.asList(BauSystem.MESSAGE.parse("BACKUP_LORE", p));
for (int i = 0; i < backups.size(); i++) {
String s = backups.get(i);
SWItem swItem = new SWItem(Material.BRICK, BauSystem.MESSAGE.parse("BACKUP_ITEM_NAME", p, s), lore, false, clickType -> {});
swItem.getItemStack().setAmount(i + 1);
swListEntries.add(new SWListInv.SWListEntry<>(swItem, s));
}
SWListInv<String> swListInv = new SWListInv<>(p, BauSystem.MESSAGE.parse("BACKUP_INV_NAME", p), swListEntries, (clickType, s) -> {
p.getOpenInventory().close();
p.performCommand("backup load " + s);
});
swListInv.open();
}
@Mapper(value = "backupName", local = true)
public TypeMapper<String> backupMapper() {
return SWCommandUtils.createMapper(s -> s, (commandSender, s) -> listBackup((Player) commandSender));
}
private List<String> listBackup(Player p) {
Region region = Region.getRegion(p.getLocation());
if (checkGlobalRegion(region, p)) {
return Collections.emptyList();
}
try {
return region.listBackup().stream().map(s -> s.substring(0, s.length() - 6).replace(' ', '_')).collect(Collectors.toList());
} catch (NullPointerException e) {
return Collections.emptyList();
}
}
}
@@ -0,0 +1,83 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.bau;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.core.Core;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
@Linked
public class BauInfoBauGuiItem extends BauGuiItem {
public BauInfoBauGuiItem() {
super(7);
}
@Override
public ItemStack getItem(Player player) {
SWItem itemStack;
if (!player.getName().endsWith("")) {
itemStack = SWItem.getPlayerSkull(SteamwarUser.get(BauServer.getInstance().getOwner()).getUserName());
} else {
itemStack = new SWItem(Material.PLAYER_HEAD, "");
}
itemStack.setName(BauSystem.MESSAGE.parse("BAU_INFO_ITEM_NAME", player));
Region region = Region.getRegion(player.getLocation());
List<String> stringList = new ArrayList<>();
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.PROTECT && region.getFloorLevel() == 0) {
continue;
}
if (flag == Flag.ITEMS && Core.getVersion() < 19) {
continue;
}
Flag.Value<?> value = region.get(flag);
if (value != null) {
stringList.add(BauSystem.MESSAGE.parse("BAU_INFO_ITEM_LORE_" + flag.name(), player, BauSystem.MESSAGE.parse(value.getChatValue(), player)));
}
}
itemStack.setLore(stringList);
return itemStack.getItemStack();
}
@Override
public boolean click(ClickType click, Player p) {
return false;
}
@Override
public Permission permission() {
return Permission.MEMBER;
}
}
@@ -0,0 +1,73 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.bau;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
import de.steamwar.linkage.Linked;
import de.steamwar.techhider.TechHider;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.stream.Collectors;
@Linked
public class ForceSpectatorCommand extends SWCommand {
public ForceSpectatorCommand() {
super("forcespectator");
}
@Register
public void forceSpectator(@Validator("supervisor") Player player, @Mapper("builder") Player other) {
Permission.forceOnlySpectator(other);
}
@Mapper("builder")
public TypeMapper<Player> spectatorMapper() {
return new TypeMapper<>() {
@Override
public Player map(CommandSender commandSender, String[] previousArguments, String s) {
Player player = Bukkit.getPlayer(s);
if (player == null) {
return null;
}
if (Permission.BUILD.hasPermission(player) && !Permission.SUPERVISOR.hasPermission(player)) {
return player;
}
return null;
}
@Override
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
return Bukkit.getOnlinePlayers().stream()
.filter(Permission.BUILD::hasPermission)
.filter(player -> !Permission.SUPERVISOR.hasPermission(player))
.map(Player::getName)
.collect(Collectors.toList());
}
};
}
}
@@ -0,0 +1,86 @@
package de.steamwar.bausystem.features.bau;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.config.BauServer;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.flags.Flag;
import de.steamwar.command.SWCommand;
import de.steamwar.core.TPSWatcher;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.BauweltMember;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.entity.Player;
import java.util.*;
@Linked
public class InfoCommand extends SWCommand {
@LinkedInstance
public BauServer bauServer;
public InfoCommand() {
super("bauinfo");
}
@Register(description = "BAU_INFO_COMMAND_HELP")
public void genericCommand(Player p) {
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_OWNER", p, SteamwarUser.get(bauServer.getOwnerID()).getUserName());
Region region = Region.getRegion(p.getLocation());
for (Flag flag : Flag.getFlags()) {
if (flag == Flag.PROTECT && region.getFloorLevel() == 0) {
continue;
}
Flag.Value<?> value = region.get(flag);
if (value != null) {
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_FLAG", p, BauSystem.MESSAGE.parse(flag.getChatValue(), p), BauSystem.MESSAGE.parse(value.getChatValue(), p));
}
}
if (Permission.BUILD.hasPermission(p)) {
List<BauweltMember> members = BauweltMember.getMembers(bauServer.getOwnerID());
Map<Permission, List<BauweltMember>> memberByPermission = new HashMap<>();
members.forEach(member -> {
if (Permission.SUPERVISOR.hasPermission(member)) {
memberByPermission.computeIfAbsent(Permission.SUPERVISOR, __ -> new ArrayList<>()).add(member);
} else if (Permission.BUILD.hasPermission(member)) {
memberByPermission.computeIfAbsent(Permission.BUILD, __ -> new ArrayList<>()).add(member);
} else {
memberByPermission.computeIfAbsent(Permission.MEMBER, __ -> new ArrayList<>()).add(member);
}
});
List<BauweltMember> supervisor = memberByPermission.getOrDefault(Permission.SUPERVISOR, Collections.emptyList());
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§eSupervisor", supervisor.size(), supervisor.isEmpty() ? "§8<none>" : joining(supervisor));
List<BauweltMember> builder = memberByPermission.getOrDefault(Permission.BUILD, Collections.emptyList());
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§6Builder", builder.size(), builder.isEmpty() ? "§8<none>" : joining(builder));
List<BauweltMember> spectator = memberByPermission.getOrDefault(Permission.MEMBER, Collections.emptyList());
BauSystem.MESSAGE.send("BAU_INFO_COMMAND_MEMBER", p, "§7Spectator", spectator.size(), spectator.isEmpty() ? "§8<none>" : joining(spectator));
}
StringBuilder tpsMessage = new StringBuilder();
tpsMessage.append(BauSystem.MESSAGE.parsePrefixed("BAU_INFO_COMMAND_TPS", p));
tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_SECOND));
tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_SECONDS));
tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE));
tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES));
tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES));
p.sendMessage(tpsMessage.toString());
}
private String joining(List<BauweltMember> bauweltMembers) {
StringBuilder st = new StringBuilder();
for (int i = 0; i < bauweltMembers.size(); i++) {
if (i != 0) {
st.append("§8, ");
}
st.append("§7");
st.append(SteamwarUser.get(bauweltMembers.get(i).getMemberID()).getUserName());
}
return st.toString();
}
}
@@ -0,0 +1,96 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.cannon;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.cannon.depth.Depth;
import de.steamwar.bausystem.features.cannon.depth.DepthManager;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.linkage.Linked;
import org.bukkit.Bukkit;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.stream.Collectors;
@Linked
public class CannonDetector implements Listener {
private Map<TNTPrimed, Vector> velocities = new HashMap<>();
private Map<TNTPrimed, Set<UUID>> propulsionOfProjectile = new HashMap<>();
@EventHandler(priority = EventPriority.LOW)
public void onEntityExplode(EntityExplodeEvent event) {
if (!(event.getEntity() instanceof TNTPrimed)) {
return;
}
TNTPrimed tnt = (TNTPrimed) event.getEntity();
propulsionOfProjectile.remove(tnt);
DepthManager.update(tnt, event.blockList());
List<TNTPrimed> tnts = Bukkit.getWorlds().get(0).getEntitiesByClass(TNTPrimed.class)
.stream()
.filter(entity -> entity != tnt)
.filter(entity -> entity.getFuseTicks() > 1)
.filter(entity -> entity.getLocation().distance(event.getLocation()) <= 8)
.collect(Collectors.toList());
if (tnts.isEmpty()) {
return;
}
boolean isEmpty = velocities.isEmpty();
tnts.forEach(tntPrimed -> {
velocities.put(tntPrimed, tntPrimed.getVelocity().clone());
propulsionOfProjectile.computeIfAbsent(tntPrimed, __ -> new HashSet<>()).add(tnt.getUniqueId());
});
if (!isEmpty) {
return;
}
BauSystem.runTaskLater(BauSystem.getInstance(), () -> {
Map<CannonKey, List<TNTPrimed>> grouped = new HashMap<>();
velocities.forEach((tntPrimed, vector) -> {
boolean xBiggest = Math.abs(vector.getX()) > Math.abs(vector.getZ());
boolean zBiggest = Math.abs(vector.getZ()) > Math.abs(vector.getX());
Vector vec = new Vector(xBiggest ? Math.signum(vector.getX()) : 0, Math.round(vector.getY() * 100), zBiggest ? Math.signum(vector.getZ()) : 0);
grouped.computeIfAbsent(new CannonKey(propulsionOfProjectile.get(tntPrimed), vec), ignored -> new ArrayList<>()).add(tntPrimed);
});
grouped.forEach((cannonKey, tntPrimeds) -> {
if (tntPrimeds.size() <= 5) return;
Region region = Region.getRegion(tntPrimeds.get(0).getLocation());
if (region.isGlobal()) return;
if (!region.hasType(RegionType.TESTBLOCK)) return;
Depth depth = new Depth(region);
DepthManager.init(tntPrimeds, depth);
});
velocities.clear();
}, 1);
}
}
@@ -0,0 +1,37 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.cannon;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
import java.util.Set;
import java.util.UUID;
@AllArgsConstructor
@EqualsAndHashCode
@Getter
public final class CannonKey {
private Set<UUID> propulsions;
private Vector velocityVector;
}
@@ -0,0 +1,109 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.cannon.depth;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.RegionUtils;
import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Depth {
private Region region;
private Vector minVector = null;
private Vector maxVector = null;
private int tntCount = 0;
public Depth(Region region) {
this.region = region;
}
public void update(List<Block> blocks) {
List<Block> blocksList = blocks.stream()
.filter(block -> region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION))
.collect(Collectors.toList());
tntCount++;
for (Block block : blocksList) {
internalUpdate(block);
}
}
public void finish() {
if (maxVector == null || minVector == null) return;
Vector dimensions = maxVector.subtract(minVector);
dimensions.setX(Math.abs(dimensions.getX()));
dimensions.setY(Math.abs(dimensions.getY()));
dimensions.setZ(Math.abs(dimensions.getZ()));
RegionUtils.message(region, player -> {
player.spigot().sendMessage(getMessage(player, dimensions.getBlockX() + 1, dimensions.getBlockY() + 1, dimensions.getBlockZ() + 1, tntCount));
});
}
private void internalUpdate(Block block) {
if (minVector == null) {
minVector = block.getLocation().toVector();
}
minVector.setX(Math.min(minVector.getX(), block.getX()));
minVector.setY(Math.min(minVector.getY(), block.getY()));
minVector.setZ(Math.min(minVector.getZ(), block.getZ()));
if (maxVector == null) {
maxVector = block.getLocation().toVector();
}
maxVector.setX(Math.max(maxVector.getX(), block.getX()));
maxVector.setY(Math.max(maxVector.getY(), block.getY()));
maxVector.setZ(Math.max(maxVector.getZ(), block.getZ()));
}
private static BaseComponent[] getMessage(Player player, int x, int y, int z, int tntCount) {
final Set<Integer> dimensions = new HashSet<>();
dimensions.add(x);
dimensions.add(y);
dimensions.add(z);
int max = getMax(dimensions);
TextComponent headerComponent = new TextComponent(BauSystem.MESSAGE.parse("DEPTH_COUNTER_MESSAGE", player));
TextComponent depthComponent = new TextComponent(BauSystem.MESSAGE.parse("DEPTH_COUNTER_COUNT", player, x == max ? "§e" : "§7", x, y == max ? "§e" : "§7", y, z == max ? "§e" : "§7", z));
depthComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent[]{new TextComponent(BauSystem.MESSAGE.parse("DEPTH_COUNTER_HOVER", player))}));
TextComponent tntComponent = new TextComponent(BauSystem.MESSAGE.parse("DEPTH_COUNTER_TNT", player, tntCount));
return new BaseComponent[]{headerComponent, depthComponent, tntComponent};
}
private static int getMax(Set<Integer> values) {
return values.stream().max(Integer::compare).orElse(0);
}
}
@@ -0,0 +1,48 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.cannon.depth;
import lombok.experimental.UtilityClass;
import org.bukkit.block.Block;
import org.bukkit.entity.TNTPrimed;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@UtilityClass
public class DepthManager {
private Map<TNTPrimed, Depth> depths = new HashMap<>();
public void init(List<TNTPrimed> list, Depth depth) {
for (TNTPrimed tnt : list) {
depths.putIfAbsent(tnt, depth);
}
}
public void update(TNTPrimed tnt, List<Block> blocks) {
Depth depth = depths.remove(tnt);
if (depth == null) return;
depth.update(blocks);
if (depths.containsValue(depth)) return;
depth.finish();
}
}
@@ -0,0 +1,107 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.countingwand;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.inventory.SWItem;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@UtilityClass
public class Countingwand {
public static ItemStack getWandItem(Player player) {
ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack();
ItemUtils.setItem(itemStack, "countingwand");
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setCustomModelData(1);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
private final Map<String, Pair<Point, Point>> selections = new HashMap<>();
public boolean isCountingwand(ItemStack itemStack) {
return ItemUtils.isItem(itemStack, "countingwand");
}
public void checkSelection(final Point point, final boolean pos1, final Player p) {
Pair<Point, Point> selection = selections.get(p.getUniqueId().toString());
final boolean newPos;
if (selection != null) {
if (pos1) {
newPos = !point.equals(selection.setKey(point));
} else {
newPos = !point.equals(selection.setValue(point));
}
} else {
if (pos1) {
selection = new Pair<>(point, null);
} else {
selection = new Pair<>(null, point);
}
selections.put(p.getUniqueId().toString(), selection);
newPos = true;
}
if (newPos) {
String dimension = getDimensions(p, selection.getKey(), selection.getValue());
String volume = getVolume(p, selection.getKey(), selection.getValue());
if (pos1) {
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_RCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
} else {
BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_LCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
}
}
}
public void removePlayer(Player p) {
selections.remove(p.getUniqueId().toString());
}
public String getVolume(Player player, final Point point1, final Point point2) {
if (point1 == null || point2 == null) {
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, 0);
}
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, getAmount(point1, point2));
}
public String getDimensions(Player player, final Point point1, final Point point2) {
if (point1 == null || point2 == null) {
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, 0, 0, 0);
}
return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
}
public int getAmount(final Point point1, final Point point2) {
return (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
}
}
@@ -0,0 +1,39 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.countingwand;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class CountingwandCommand extends SWCommand {
public CountingwandCommand() {
super("countingwand", "/countingwand", "cwand", "/cwand", "zollstock", "/zollstock");
}
@Register(description = "COUNTINGWAND_COMMAND_HELP")
public void genericCommand(final Player p) {
SWUtils.giveItemToPlayer(p, Countingwand.getWandItem(p));
}
}
@@ -0,0 +1,53 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.countingwand;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@Linked
public class CountingwandGuiItem extends BauGuiItem {
public CountingwandGuiItem() {
super(22);
}
@Override
public ItemStack getItem(Player player) {
return Countingwand.getWandItem(player);
}
@Override
public boolean click(ClickType click, Player p) {
p.closeInventory();
p.performCommand("countingwand");
return false;
}
@Override
public Permission permission() {
return Permission.MEMBER;
}
}
@@ -0,0 +1,75 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.countingwand;
import de.steamwar.bausystem.region.Point;
import de.steamwar.linkage.Linked;
import org.bukkit.FluidCollisionMode;
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.PlayerQuitEvent;
import org.bukkit.util.RayTraceResult;
import java.util.Objects;
@Linked
public class CountingwandListener implements Listener {
@EventHandler
public void onBlockBreak(final BlockBreakEvent event) {
if (!Countingwand.isCountingwand(event.getPlayer().getInventory().getItemInMainHand())) {
return;
}
event.setCancelled(true);
Countingwand.checkSelection(Point.fromLocation(event.getBlock().getLocation()), true, event.getPlayer());
}
@EventHandler
public void onPlayerInteract(final PlayerInteractEvent event) {
if (!Countingwand.isCountingwand(event.getItem())) {
return;
}
if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_AIR) {
RayTraceResult rayTraceResult = event.getPlayer().rayTraceBlocks(200, FluidCollisionMode.NEVER);
if (rayTraceResult == null) {
return;
}
Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(rayTraceResult.getHitBlock()).getLocation()), event.getAction() == Action.LEFT_CLICK_AIR, event.getPlayer());
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
event.setCancelled(true);
Countingwand.checkSelection(Point.fromLocation(Objects.requireNonNull(event.getClickedBlock()).getLocation()), false, event.getPlayer());
}
@EventHandler
public void onLeave(PlayerQuitEvent event) {
Countingwand.removePlayer(event.getPlayer());
}
}
@@ -0,0 +1,141 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.design.endstone;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DesignEndStone {
private static final World WORLD = Bukkit.getWorlds().get(0);
private int minX, minY, minZ, maxX, maxY, maxZ;
private REntityServer entityServer = new REntityServer();
private List<REntity> entities = new ArrayList<>();
private Set<Location> locations = new HashSet<>();
private boolean wsOrAs;
private double maxBlastResistance;
public DesignEndStone(Region region) {
this.minX = region.getMinPointBuild().getX();
this.minY = region.getMinPointBuild().getY();
this.minZ = region.getMinPointBuild().getZ();
this.maxX = region.getMaxPointBuild().getX();
this.maxY = region.getMaxPointBuild().getY();
this.maxZ = region.getMaxPointBuild().getZ();
wsOrAs = region.getName().startsWith("ws") || region.getName().startsWith("as");
maxBlastResistance = wsOrAs ? 6.1 : 9.0;
entityServer.setCallback((player, rEntity, entityAction) -> {
if (entityAction != REntityServer.EntityAction.ATTACK) return;
Location location = new Location(WORLD, rEntity.getX(), rEntity.getY(), rEntity.getZ());
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
location.getBlock().breakNaturally();
calc();
}, 1);
});
}
public void calc() {
entities.forEach(REntity::die);
entities.clear();
locations.clear();
calc(minX, minY, minZ, maxX, maxY, minZ, 0, 0, 1, maxZ - minZ);
calc(minX, minY, maxZ, maxX, maxY, maxZ, 0, 0, -1, maxZ - minZ);
calc(minX, minY, minZ, minX, maxY, maxZ, 1, 0, 0, maxX - minX);
calc(maxX, minY, minZ, maxX, maxY, maxZ, -1, 0, 0, maxX - minX);
if (wsOrAs) {
calc(minX, minY, minZ, maxX, minY, maxZ, 0, 1, 0, maxY - minY + 1);
} else {
int airBlocks = 0;
double minAirBlocks = (maxX - minX) * (maxZ - minZ) * 0.1;
for (int x = minX; x < maxX; x++) {
for (int z = minZ; z < maxZ; z++) {
if (WORLD.getBlockAt(x, minY, z).getType().isAir()) {
airBlocks++;
if (airBlocks > minAirBlocks) break;
}
}
}
if (airBlocks > minAirBlocks) {
calc(minX, minY, minZ, maxX, minY, maxZ, 0, 1, 0, maxY - minY + 1);
}
}
calc(minX, maxY, minZ, maxX, maxY, maxZ, 0, -1, 0, maxY - minY + 1);
}
private void calc(int minX, int minY, int minZ, int maxX, int maxY, int maxZ, int dirX, int dirY, int dirZ, int steps) {
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
for (int z = minZ; z <= maxZ; z++) {
for (int step = 0; step < steps; step++) {
int cx = x + step * dirX;
int cy = y + step * dirY;
int cz = z + step * dirZ;
Material material = WORLD.getBlockAt(cx, cy, cz).getType();
if (material != Material.WATER && material != Material.LAVA && material.getBlastResistance() >= maxBlastResistance) {
Location location = new Location(WORLD, cx + 0.5, cy, cz + 0.5);
if (!locations.add(location)) break;
RFallingBlockEntity entity = new RFallingBlockEntity(entityServer, location, Material.RED_STAINED_GLASS);
entity.setNoGravity(true);
entity.setGlowing(true);
entities.add(entity);
break;
} else if (!material.isAir() && material != Material.WATER && material != Material.LAVA) {
break;
}
}
}
}
}
}
public void toggle(Player player) {
if (entityServer.getPlayers().contains(player)) {
entityServer.removePlayer(player);
BauSystem.MESSAGE.sendPrefixless("DESIGN_ENDSTONE_DISABLE", player, ChatMessageType.ACTION_BAR);
} else {
entityServer.addPlayer(player);
calc();
BauSystem.MESSAGE.sendPrefixless("DESIGN_ENDSTONE_ENABLE", player, ChatMessageType.ACTION_BAR);
}
}
public boolean removePlayer(Player player) {
entityServer.removePlayer(player);
return entityServer.getPlayers().isEmpty();
}
}
@@ -0,0 +1,97 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.design.endstone;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.command.SWCommand;
import de.steamwar.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.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@Linked
public class DesignEndStoneCommand extends SWCommand implements Listener {
public DesignEndStoneCommand() {
super("designendstone");
}
private Map<Region, DesignEndStone> designEndStoneMap = new HashMap<>();
@Register(description = "DESIGN_ENDSTONE_COMMAND_HELP")
public void genericCommand(@Validator Player player) {
Region region = Region.getRegion(player.getLocation());
if (!region.hasType(RegionType.BUILD)) {
BauSystem.MESSAGE.send("DESIGN_ENDSTONE_REGION_ERROR", player);
return;
}
designEndStoneMap.computeIfAbsent(region, DesignEndStone::new).toggle(player);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
disableDesignEndStone(event.getPlayer());
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(this::disableDesignEndStone);
}
private void disableDesignEndStone(Player player) {
new HashSet<>(designEndStoneMap.entrySet()).forEach(regionDesignEndStoneEntry -> {
if (regionDesignEndStoneEntry.getValue().removePlayer(player)) {
designEndStoneMap.remove(regionDesignEndStoneEntry.getKey());
}
});
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
update(event.getBlock().getLocation());
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
BauSystem.runTaskLater(BauSystem.getInstance(), () -> {
update(event.getBlock().getLocation());
}, 1);
}
private void update(Location location) {
Region region = Region.getRegion(location);
DesignEndStone designEndStone = designEndStoneMap.get(region);
if (designEndStone == null) {
return;
}
designEndStone.calc();
}
}
@@ -0,0 +1,44 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.detonator;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
public enum Detoblock {
SWITCH(0, true, "DETONATOR_BUTTON_SWITCH"),
WOOD_BUTTON(30, "DETONATOR_BUTTON_WOOD_BUTTON"),
STONE_BUTTON(20, "DETONATOR_BUTTON_STONE_BUTTON"),
PRESSURE_PLATE(30, "DETONATOR_BUTTON_PRESSURE_PLATE"),
WEIGHTED_PRESSURE_PLATE(20, "DETONATOR_BUTTON_WEIGHTED-PRESSURE_PLATE"),
TRIPWIRE(30, "DETONATOR_BUTTON_TRIPWIRE"),
NOTEBLOCK(1, "DETONATOR_BUTTON_NOTEBLOCK"),
DAYLIGHTSENSOR(0, true, "DETONATOR_BUTTON_DAYLIGHTSENSOR"),
POWERABLE(0, true, "DETONATOR_BUTTON_POWERABLE"),
INVALID(-1, "DETONATOR_BUTTON_INVALID");
private final int time;
private boolean toggle;
private final String name;
}
@@ -0,0 +1,225 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.detonator;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.features.autostart.AutostartListener;
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
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.*;
import org.bukkit.block.data.type.DaylightDetector;
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.*;
@UtilityClass
public class Detonator {
private static final Map<Player, REntityServer> 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<Location> locs) {
if (ENTITIES_MAP.containsKey(p)) return;
REntityServer entities = new REntityServer();
entities.setCallback((player, rEntity, entityAction) -> {
Vector vector = new Vector(rEntity.getX(), rEntity.getY(), rEntity.getZ());
DetonatorListener.addLocationToDetonator(vector.toLocation(player.getWorld()).getBlock().getLocation(), player);
DetonatorListener.HAS_UPDATED.add(player);
});
entities.addPlayer(p);
ENTITIES_MAP.put(p, entities);
locs.forEach(location -> {
RFallingBlockEntity entity = new RFallingBlockEntity(entities, location.clone().add(HALF), Material.RED_STAINED_GLASS);
entity.setNoGravity(true);
});
}
public static void hideDetonator(Player p) {
ENTITIES_MAP.remove(p).close();
}
public static boolean hasActiveDetonatorShow(Player p) {
return ENTITIES_MAP.containsKey(p);
}
public static void activateDetonator(DetonatorStorage detonator) {
Player p = detonator.getPlayer();
if (Config.getInstance().get(p).getPlainValueOrDefault("detonator-autostart", false)) {
AutostartListener.instance.activate(p);
}
Map<Integer, Set<Block>> deactivate = new HashMap<>();
Set<Location> 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();
if (s == 1) {
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_POINT_ACT", p));
} else {
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_POINTS_ACT", p, s));
}
if (!invalid.isEmpty()) {
int invalidPoints = invalid.size();
if (invalidPoints == 1) {
BauSystem.MESSAGE.send("DETONATOR_INVALID_POINT", p);
} else {
BauSystem.MESSAGE.send("DETONATOR_INVALID_POINTS", p, invalidPoints);
}
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();
FaceAttachable.AttachedFace face = sw.getAttachedFace();
if (face == FaceAttachable.AttachedFace.FLOOR) {
update(block.getRelative(BlockFace.DOWN));
} else if (face == FaceAttachable.AttachedFace.CEILING) {
update(block.getRelative(BlockFace.UP));
} else {
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));
}
}
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 DaylightDetector) {
DaylightDetector detector = (DaylightDetector) data;
detector.setInverted(state);
}
if (data instanceof AnaloguePowerable) {
AnaloguePowerable powerable = (AnaloguePowerable) data;
if (block.getType() == Material.REDSTONE_WIRE) {
powerable.setPower(state ? 15 : 0);
} else {
powerable.setPower(state ? 1 : 0);
}
}
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 DaylightDetector) {
DaylightDetector detector = (DaylightDetector) data;
return detector.isInverted();
}
if (data instanceof AnaloguePowerable) {
AnaloguePowerable powerable = (AnaloguePowerable) data;
return powerable.getPower() > 0;
}
return false;
}
static Detoblock getBlock(Block block) {
switch (block.getType()) {
case LEVER:
return Detoblock.SWITCH;
case TRIPWIRE:
return Detoblock.TRIPWIRE;
case NOTE_BLOCK:
return Detoblock.NOTEBLOCK;
case DAYLIGHT_DETECTOR:
return Detoblock.DAYLIGHTSENSOR;
case HEAVY_WEIGHTED_PRESSURE_PLATE:
case LIGHT_WEIGHTED_PRESSURE_PLATE:
return Detoblock.WEIGHTED_PRESSURE_PLATE;
default:
if (block.getType().name().contains("STONE_BUTTON")) {
return Detoblock.STONE_BUTTON;
} else if (block.getType().name().contains("BUTTON")) {
return Detoblock.WOOD_BUTTON;
} else if (block.getType().name().contains("PRESSURE_PLATE")) {
return Detoblock.PRESSURE_PLATE;
} else if (block.getBlockData() instanceof Powerable) {
return Detoblock.POWERABLE;
} else {
return Detoblock.INVALID;
}
}
}
}
@@ -0,0 +1,52 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.detonator;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@Linked
public class DetonatorBauGuiItem extends BauGuiItem {
public DetonatorBauGuiItem() {
super(8);
}
@Override
public ItemStack getItem(Player player) {
return DetonatorCommand.getWAND(player);
}
@Override
public boolean click(ClickType click, Player p) {
p.closeInventory();
p.performCommand("detonator wand");
return false;
}
@Override
public Permission permission() {
return Permission.BUILD;
}
}
@@ -0,0 +1,87 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.detonator;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
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
public class DetonatorCommand extends SWCommand {
public static ItemStack getWAND(Player player) {
ItemStack wand = new ItemStack(Material.BLAZE_ROD);
ItemStorage.setDetonator(wand);
ItemMeta meta = wand.getItemMeta();
meta.setDisplayName(BauSystem.MESSAGE.parse("DETONATOR_WAND_NAME", player));
meta.setLore(Arrays.asList(BauSystem.MESSAGE.parse("DETONATOR_WAND_LORE_1", player),
BauSystem.MESSAGE.parse("DETONATOR_WAND_LORE_2", player),
BauSystem.MESSAGE.parse("DETONATOR_WAND_LORE_3", player)));
meta.setCustomModelData(3);
wand.setItemMeta(meta);
ItemUtils.setItem(wand, "detonator");
return wand;
}
public DetonatorCommand() {
super("detonator", "dt");
}
@Register(value = "wand", description = "DETONATOR_HELP_WAND")
public void giveWand(@Validator Player p) {
SWUtils.giveItemToPlayer(p, getWAND(p));
}
@Register(value = "click", description = "DETONATOR_HELP_CLICK")
public void clickDetonator(@Validator Player p) {
Detonator.activateDetonator(new ItemStorage(p));
}
@Register(value = "clear", description = "DETONATOR_HELP_CLEAR")
public void clearDetonator(Player p) {
DetonatorStorage storage = new ItemStorage(p);
storage.clear();
storage.write();
}
@Register(value = "autostart", description = "DETONATOR_HELP_AUTOSTART")
public void toggleAutostartTimer(Player p) {
boolean current = Config.getInstance().get(p).getPlainValueOrDefault("detonator-autostart", false);
Config.getInstance().get(p).put("detonator-autostart", !current);
if (!current) {
BauSystem.MESSAGE.send("DETONATOR_AUTOSTART_ENABLE", p);
} else {
BauSystem.MESSAGE.send("DETONATOR_AUTOSTART_DISABLE", p);
}
}
}
@@ -0,0 +1,129 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.detonator;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.detonator.storage.DetonatorStorage;
import de.steamwar.bausystem.features.detonator.storage.ItemStorage;
import de.steamwar.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.HashSet;
import java.util.Set;
@Linked
public class DetonatorListener implements Listener {
static final Set<Player> HAS_UPDATED = new HashSet<>();
static void addLocationToDetonator(Location location, Player p) {
Detoblock detoblock = Detonator.getBlock(location.getBlock());
if (detoblock == Detoblock.INVALID) {
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_INVALID_BLOCK", p));
return;
}
DetonatorStorage detonator = new ItemStorage(p);
if (!p.isSneaking()) {
detonator.clear();
}
if (detonator.getLocations().contains(location)) {
detonator.removeLocation(location);
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_LOC_REMOVE", p, BauSystem.MESSAGE.parse(detoblock.getName(), p)));
} else {
detonator.addLocation(location);
SWUtils.sendToActionbar(p, BauSystem.MESSAGE.parse("DETONATOR_LOC_ADD", p, BauSystem.MESSAGE.parse(detoblock.getName(), p)));
}
detonator.write();
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
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(!Permission.BUILD.hasPermission(event.getPlayer())) return;
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 (!Permission.BUILD.hasPermission(event.getPlayer()) ||!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(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (Detonator.isDetonator(event.getPlayer().getInventory().getItemInMainHand())) {
HAS_UPDATED.add(event.getPlayer());
}
}
@EventHandler
public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (Detonator.isDetonator(event.getMainHandItem()) || Detonator.isDetonator(event.getOffHandItem())) {
HAS_UPDATED.add(event.getPlayer());
}
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<Location> getLocations();
void removeLocation(Location location);
void clear();
void write();
Player getPlayer();
}
@@ -0,0 +1,191 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
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.Collections;
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<NamespacedKey> DETOLOCATION_BUILDER = integer -> SWUtils.getNamespaceKey("deto_loc_" + integer);
@Getter
private final Player p;
private final List<Location> 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<Location> 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<Location> read() {
List<Location> tempLocs = new LinkedList<>();
if (itemStack == null) {
return Collections.emptyList();
}
ItemMeta meta = itemStack.getItemMeta();
if (meta == null) {
return Collections.emptyList();
}
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<Location> 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);
}
}
@@ -0,0 +1,120 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.gui.editor.BauGuiMapping;
import de.steamwar.bausystem.linkage.LinkageUtils;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.inventory.SWInventory;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.*;
@UtilityClass
public class BauGUI {
private static final Map<Integer, BauGuiItem> ITEMS = new HashMap<>();
public static Map<Integer, BauGuiItem> getITEMS() {
if (ITEMS.isEmpty()) LinkageUtils.linkGUIItems();
return ITEMS;
}
private static final Set<Player> OPEN_INVS = new HashSet<>();
private static boolean updating = false;
public static ItemStack getGUI_ITEM(Player p) {
ItemStack GUI_ITEM = new ItemStack(Material.NETHER_STAR);
ItemMeta meta = GUI_ITEM.getItemMeta();
meta.setDisplayName(ChatColor.YELLOW + BauSystem.MESSAGE.parse("GUI_NAME", p));
GUI_ITEM.setItemMeta(meta);
return GUI_ITEM;
}
public static void addItem(BauGuiItem item) {
if (ITEMS.containsKey(item.getId())) {
throw new IllegalArgumentException("Duplicate Id Key: " + item.getId() + ". From Classes: " + ITEMS.get(item.getId()).getClass().getName() + " and " + item.getClass().getName());
}
ITEMS.put(item.getId(), item);
}
public static void openBauGui(Player p) {
if (!updating) {
OPEN_INVS.add(p);
}
BauGuiMapping mapping = BauGuiMapping.getGuiMapping(p);
SWInventory inv = new SWInventory(p, mapping.getSize(), BauSystem.MESSAGE.parse("GUI_NAME", p));
getITEMS().values().forEach(item -> {
if (!mapping.isShown(item.getId())) {
return;
}
inv.setItem(mapping.getSlot(item.getId()), permissionLore(item.getItem(p), item.permission(), p), clickType -> {
if (item.permission().hasPermission(p)) {
if (item.click(clickType, p)) {
update();
}
} else {
p.closeInventory();
BauSystem.MESSAGE.send("NO_PERMISSION", p);
}
});
});
inv.addCloseCallback(clickType -> {
if (!updating) {
OPEN_INVS.remove(p);
}
});
inv.open();
}
public static void update() {
updating = true;
OPEN_INVS.forEach(BauGUI::openBauGui);
updating = false;
}
public static void giveItem(Player p) {
SWUtils.giveItemToPlayer(p, getGUI_ITEM(p));
}
private static ItemStack permissionLore(ItemStack itemStack, Permission permission, Player p) {
ItemMeta meta = itemStack.getItemMeta();
if (!permission.hasPermission(p)) {
List<String> lore = meta.getLore();
if (lore == null) {
lore = Collections.singletonList(BauSystem.MESSAGE.parse("NO_PERMISSION", p));
} else {
lore.add(BauSystem.MESSAGE.parse("NO_PERMISSION", p));
}
meta.setLore(lore);
}
itemStack.setItemMeta(meta);
return itemStack;
}
}
@@ -0,0 +1,49 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui;
import de.steamwar.bausystem.features.gui.editor.BauGuiEditor;
import de.steamwar.command.SWCommand;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class BauGUICommand extends SWCommand {
public BauGUICommand() {
super("gui", "baugui", "g");
}
@Register(help = true)
public void genericHelp(Player p, String... args) {
BauGUI.openBauGui(p);
}
@Register("item")
public void giveItem(Player p) {
BauGUI.giveItem(p);
}
@Register("editor")
public void openEditor(Player p) {
BauGuiEditor.openGuiEditor(p, new SWItem().getItemStack());
}
}
@@ -0,0 +1,60 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
@Linked
public class BauGuiBauGuiItem extends BauGuiItem {
public BauGuiBauGuiItem() {
super(14);
}
@Override
public ItemStack getItem(Player player) {
return new SWItem(Material.NETHER_STAR, ChatColor.YELLOW + BauSystem.MESSAGE.parse("GUI_NAME", player),
Arrays.asList(BauSystem.MESSAGE.parse("GUI_ITEM_LORE1", player), BauSystem.MESSAGE.parse("GUI_ITEM_LORE2", player)), false, clickType -> {
}).getItemStack();
}
@Override
public boolean click(ClickType click, Player p) {
p.closeInventory();
BauGUI.giveItem(p);
return false;
}
@Override
public Permission permission() {
return Permission.MEMBER;
}
}
@@ -0,0 +1,43 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui;
import de.steamwar.linkage.Linked;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
@Linked
public class BauGuiListener implements Listener {
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getItem() == null) {
return;
}
if (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR) {
if (event.getItem().isSimilar(BauGUI.getGUI_ITEM(event.getPlayer()))) {
BauGUI.openBauGui(event.getPlayer());
}
}
}
}
@@ -0,0 +1,233 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui.editor;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.gui.BauGUI;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import de.steamwar.linkage.Linked;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.*;
@Linked
public class BauGuiEditor implements Listener {
@Getter
private static final List<Player> open_Edits = new ArrayList<>();
public static void openGuiEditor(Player p, ItemStack cursor) {
BauGuiMapping mapping = BauGuiMapping.getGuiMapping(p);
Inventory inv = Bukkit.createInventory(null, mapping.getSize() + 9, BauSystem.MESSAGE.parse("GUI_EDITOR_TITLE", p));
for (Map.Entry<Integer, Integer> e : mapping.getMapping().entrySet()) {
if (e.getValue() >= 0) {
if (e.getValue() < mapping.getSize()) {
inv.setItem(e.getValue(), addId(BauGUI.getITEMS().get(e.getKey()).getItem(p), e.getKey()));
}
}
}
for (int j = mapping.getSize(); j < mapping.getSize() + 9; j++) {
inv.setItem(j, new SWItem(Material.WHITE_STAINED_GLASS_PANE, "").getItemStack());
}
inv.setItem(mapping.getSize() + 3, new SWItem(mapping.getSize() == 9 * 5 ? Material.GRAY_STAINED_GLASS_PANE : Material.LIME_STAINED_GLASS_PANE, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_ROW_P", p)).getItemStack());
inv.setItem(mapping.getSize() + 2, new SWItem(mapping.getSize() == 9 ? Material.GRAY_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_ROW_M", p)).getItemStack());
inv.setItem(mapping.getSize() + 5, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_TRASH", p), Arrays.asList(BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_TRASH_LORE", p)), false, clickType -> {
}).getItemStack());
inv.setItem(mapping.getSize() + 6, new SWItem(Material.SCUTE, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_MORE", p)).getItemStack());
inv.setItem(mapping.getSize() + 8, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_CLOSE", p)).getItemStack());
p.openInventory(inv);
p.getOpenInventory().setCursor(cursor == null ? new SWItem().getItemStack() : cursor);
open_Edits.add(p);
BauGuiMapping.startWatchdog();
}
private static ItemStack addId(ItemStack itemStack, int id) {
ItemMeta meta = itemStack.getItemMeta();
meta.getPersistentDataContainer().set(new NamespacedKey(BauSystem.getInstance(), "gui-item-id"), PersistentDataType.INTEGER, id);
itemStack.setItemMeta(meta);
return itemStack;
}
private static int getId(ItemStack itemStack) {
ItemMeta meta = itemStack.getItemMeta();
return meta.getPersistentDataContainer().get(new NamespacedKey(BauSystem.getInstance(), "gui-item-id"), PersistentDataType.INTEGER);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (!open_Edits.contains(event.getWhoClicked())) {
return;
}
ItemStack i = event.getCurrentItem();
Player p = (Player) event.getWhoClicked();
BauGuiMapping mapping = BauGuiMapping.getGuiMapping(p);
if (event.getClickedInventory() == p.getInventory()) {
event.setCancelled(true);
}
if (event.getHotbarButton() != -1) {
event.setCancelled(true);
}
if (i == null) {
return;
}
if (event.getSlot() - mapping.getSize() >= 0) {
event.setCancelled(true);
}
switch (event.getSlot() - mapping.getSize()) {
case 2:
if (mapping.getSize() == 9) {
return;
}
saveMapping(p);
mapping.setSize(mapping.getSize() - 9);
openGuiEditor(p, event.getCursor());
break;
case 3:
if (mapping.getSize() == 9 * 5) {
return;
}
saveMapping(p);
mapping.setSize(mapping.getSize() + 9);
openGuiEditor(p, event.getCursor());
break;
case 5:
event.getView().setCursor(new SWItem().getItemStack());
break;
case 6:
saveMapping(p);
List<SWListInv.SWListEntry<BauGuiItem>> items = new ArrayList<>();
for (BauGuiItem item : BauGUI.getITEMS().values()) {
if (mapping.isShown(item.getId())) {
continue;
}
SWItem ip = new SWItem();
ip.setItemStack(item.getItem(p));
items.add(new SWListInv.SWListEntry(ip, item));
}
if (items.isEmpty()) {
return;
}
SWListInv<BauGuiItem> inv = new SWListInv<>(p, BauSystem.MESSAGE.parse("GUI_EDITOR_TITLE_MORE", p), items, (clickType, item) -> {
openGuiEditor(p, addId(item.getItem(p), item.getId()));
});
inv.open();
break;
case 8:
saveMapping(p);
BauGUI.openBauGui(p);
break;
default:
}
}
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
if (open_Edits.contains(event.getEntity())) {
event.setCancelled(true);
}
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if (open_Edits.contains(event.getPlayer())) {
event.setCancelled(true);
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
open_Edits.remove(event.getPlayer());
}
@EventHandler
public void onInventoryDrag(InventoryDragEvent event) {
if (open_Edits.contains(event.getWhoClicked())) {
if (event.getRawSlots().stream().anyMatch(integer -> event.getView().getInventory(integer) == event.getWhoClicked().getInventory())) {
event.setCancelled(true);
}
}
}
private void saveMapping(Player p) {
saveMapping(p.getOpenInventory(), BauGuiMapping.getGuiMapping(p));
}
private void saveMapping(InventoryView view, BauGuiMapping mapping) {
if (mapping.isSaved()) {
return;
}
HashMap<Integer, Integer> newMapping = new HashMap<>();
for (int i = 0; i < view.getTopInventory().getContents().length; i++) {
ItemStack itemStack = view.getTopInventory().getContents()[i];
if (itemStack == null || itemStack.getType() == Material.AIR || i >= mapping.getSize()) continue;
newMapping.put(getId(itemStack), i);
}
for (Map.Entry<Integer, BauGuiItem> e : BauGUI.getITEMS().entrySet()) {
if (!newMapping.containsKey(e.getKey())) {
newMapping.put(e.getKey(), -1);
}
}
mapping.setMapping(newMapping);
mapping.save();
}
@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
if (!open_Edits.contains(event.getPlayer())) {
return;
}
Player p = (Player) event.getPlayer();
saveMapping(event.getView(), BauGuiMapping.getGuiMapping(p));
open_Edits.remove(p);
}
}
@@ -0,0 +1,54 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui.editor;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
@Linked
public class BauGuiEditorGuiItem extends BauGuiItem {
public BauGuiEditorGuiItem() {
super(25);
}
@Override
public Permission permission() {
return Permission.MEMBER;
}
@Override
public ItemStack getItem(Player player) {
return new SWItem(Material.IRON_PICKAXE, BauSystem.MESSAGE.parse("GUI_EDITOR_ITEM_NAME", player)).getItemStack();
}
@Override
public boolean click(ClickType click, Player p) {
p.performCommand("gui editor");
return false;
}
}
@@ -0,0 +1,138 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.gui.editor;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.features.gui.BauGUI;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import yapion.hierarchy.types.YAPIONObject;
import java.util.*;
public class BauGuiMapping {
private static final HashMap<UUID, BauGuiMapping> fromUUID = new HashMap<>();
private static final List<BauGuiMapping> mappings = new ArrayList<>();
private static BukkitTask task;
public static void startWatchdog() {
if (task == null) {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), bukkitTask -> {
mappings.forEach(BauGuiMapping::tick);
if (BauGuiEditor.getOpen_Edits().isEmpty()) {
bukkitTask.cancel();
task = null;
}
}, 1, 1);
}
}
@Getter
private final YAPIONObject object;
@Getter
private final Player owner;
@Getter
@Setter
private boolean saved;
protected BauGuiMapping(YAPIONObject object, Player p) {
this.object = object;
this.owner = p;
fromUUID.put(p.getUniqueId(), this);
mappings.add(this);
}
public static BauGuiMapping getGuiMapping(Player p) {
BauGuiMapping mapping = fromUUID.get(p.getUniqueId());
if (mapping == null) {
YAPIONObject yapionObject = Config.getInstance().get(p);
mapping = new BauGuiMapping(yapionObject.getObject("baugui"), p);
}
return mapping;
}
public boolean isShown(int id) {
return object.getPlainValueOrDefault(Integer.toString(id), -1) >= 0;
}
public int getSlot(int id) {
return object.getPlainValue(Integer.toString(id));
}
public Map<Integer, Integer> getMapping() {
return internalReadMap();
}
public void setMapping(Map<Integer, Integer> mapping) {
internalWriteMap(mapping);
}
public int getSize() {
return object.getPlainValueOrDefault("size", 45);
}
public void setSize(int size) {
if (size % 9 != 0) {
return;
}
object.add("size", size);
}
private void tick() {
this.saved = false;
}
public void save() {
if (saved) return;
YAPIONObject config = Config.getInstance().get(owner);
config.add("baugui", object);
Config.getInstance().save(owner);
saved = true;
}
private Map<Integer, Integer> internalReadMap() {
Map<Integer, Integer> map = new HashMap<>();
for (Map.Entry<Integer, BauGuiItem> e : BauGUI.getITEMS().entrySet()) {
Integer value = object.getPlainValueOrDefault(e.getKey().toString(), -1);
if (value == -1) continue;
map.put(e.getKey(), value);
}
return map;
}
private void internalWriteMap(Map<Integer, Integer> map) {
for (Map.Entry<Integer, BauGuiItem> e : BauGUI.getITEMS().entrySet()) {
object.remove(e.getKey().toString());
Integer value = map.getOrDefault(e.getKey(), -1);
if (value == -1) continue;
object.add(e.getKey().toString(), value);
}
}
}
@@ -0,0 +1,93 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.hotbar;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.core.Core;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import yapion.hierarchy.types.YAPIONArray;
import yapion.hierarchy.types.YAPIONObject;
import yapion.hierarchy.types.YAPIONValue;
import yapion.parser.YAPIONParser;
import yapion.serializing.YAPIONDeserializer;
import yapion.serializing.YAPIONSerializer;
import java.util.HashSet;
import java.util.Set;
@UtilityClass
public class DefaultHotbar {
private final YAPIONArray DEFAULT_HOTBAR = YAPIONParser.parse("{[{@type(org.bukkit.inventory.ItemStack)v(2230)type(WOODEN_AXE)meta{@type(org.bukkit.inventory.meta.ItemMeta)meta-type(UNSPECIFIC)display-name(WorldEdit Wand)lore{@type(java.util.ArrayList)values[Left click: select pos #1,Right click: select pos #2]}}},{@type(org.bukkit.inventory.ItemStack)v(2230)type(COMPASS)meta{@type(org.bukkit.inventory.meta.ItemMeta)meta-type(UNSPECIFIC)display-name(Navigation Wand)lore{@type(java.util.ArrayList)values[Left click: jump to location,Right click: pass through walls]}}},null,null,null,null,null,null,{@type(org.bukkit.inventory.ItemStack)v(2230)type(NETHER_STAR)meta{@type(org.bukkit.inventory.meta.ItemMeta)meta-type(UNSPECIFIC)display-name(§eBau GUI)}},null,null,{@type(org.bukkit.inventory.ItemStack)v(3117)type(ELYTRA)},null]}").getArray("");
public void updateHotbar(Player p) {
ItemStack[] hotbar = new ItemStack[13];
System.arraycopy(p.getInventory().getContents(), 0, hotbar, 0, 9);
System.arraycopy(p.getInventory().getArmorContents(), 0, hotbar, 9, 4);
YAPIONArray yapionArray = new YAPIONArray();
for (ItemStack itemStack : hotbar) {
if (itemStack != null) {
yapionArray.add(YAPIONSerializer.serialize(itemStack));
} else {
yapionArray.add(new YAPIONValue<>(null));
}
}
Config.getInstance().get(p).add("hotbar-" + Core.getVersion(), yapionArray);
Config.getInstance().save(p);
}
public void setHotbar(Player p) {
ItemStack[] hotbar = getItems(p);
ItemStack[] inv = p.getInventory().getContents();
ItemStack[] armor = p.getInventory().getArmorContents();
System.arraycopy(hotbar, 0, inv, 0, 9);
System.arraycopy(hotbar, 9, armor, 0, 4);
p.getInventory().setContents(inv);
p.getInventory().setArmorContents(armor);
}
public ItemStack[] getItems(Player p) {
Config.getInstance().get(p).remap("hotbar", "hotbar-19");
YAPIONArray yapionArray = Config.getInstance().get(p).getYAPIONArrayOrSetDefault("hotbar-" + Core.getVersion(), defaultHotbar());
ItemStack[] hotbar = new ItemStack[13];
Set<Integer> invalid = new HashSet<>();
yapionArray.forEach((integer, yapionAnyType) -> {
if (yapionAnyType instanceof YAPIONValue) {
hotbar[integer] = null;
} else {
try {
hotbar[integer] = YAPIONDeserializer.deserialize((YAPIONObject) yapionAnyType);
} catch (Exception e) {
invalid.add(integer);
hotbar[integer] = null;
}
}
});
invalid.forEach(i -> yapionArray.set(i, new YAPIONValue<>(null)));
if (!invalid.isEmpty()) Config.getInstance().save(p);
return hotbar;
}
public YAPIONArray defaultHotbar() {
return DEFAULT_HOTBAR;
}
}
@@ -0,0 +1,60 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.hotbar;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.command.SWCommand;
import de.steamwar.inventory.SWInventory;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@Linked
public class HotbarCommand extends SWCommand {
public HotbarCommand() {
super("hotbar", "hb");
addDefaultHelpMessage("HOTBAR_HELP_GENERIC");
}
@Register(value = "load", description = "HOTBAR_HELP_LOAD")
public void loadHotbar(@Validator Player p) {
DefaultHotbar.setHotbar(p);
BauSystem.MESSAGE.send("HOTBAR_LOADED", p);
}
@Register(value = "save", description = "HOTBAR_HELP_SAVE")
public void saveHotbar(Player p) {
DefaultHotbar.updateHotbar(p);
BauSystem.MESSAGE.send("HOTBAR_SAVED", p);
}
@Register(value = "show", description = "HOTBAR_HELP_SHOW")
public void showHotbar(Player p) {
SWInventory inv = new SWInventory(p, 18, BauSystem.MESSAGE.parse("HOTBAR_INVENTORY", p));
ItemStack[] hotbar = DefaultHotbar.getItems(p);
for (int i = 0; i < hotbar.length; i++) {
if (hotbar[i] == null) continue;
inv.setItem(i, hotbar[i], clickType -> {
});
}
inv.open();
}
}
@@ -0,0 +1,48 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.hotbar;
import de.steamwar.bausystem.Permission;
import de.steamwar.linkage.Linked;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
@Linked
public class HotbarListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (allNull(event.getPlayer().getInventory().getContents()) && allNull(event.getPlayer().getInventory().getArmorContents())) {
DefaultHotbar.setHotbar(event.getPlayer());
}
}
private boolean allNull(Object[] arr) {
for (Object o : arr) {
if (o != null) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,42 @@
package de.steamwar.bausystem.features.inventoryfiller;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.bausystem.linkage.specific.BauGuiItem;
import de.steamwar.inventory.SWItem;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
@Linked
public class InventoryFillBauGuiItem extends BauGuiItem {
public InventoryFillBauGuiItem() {
super(34);
}
@LinkedInstance
public InventoryFillerCommand command;
@Override
public Permission permission() {
return Permission.MEMBER;
}
@Override
public ItemStack getItem(Player player) {
String loreKey = Config.getInstance().get(player).getPlainValueOrDefault("inventoryfill", false) ? "OTHER_ITEMS_INVENTORY_FILL_LORE_ACTIVE" : "OTHER_ITEMS_INVENTORY_FILL_LORE_INACTIVE";
return new SWItem(Material.HOPPER, BauSystem.MESSAGE.parse("OTHER_ITEMS_INVENTORY_FILL_NAME", player), Collections.singletonList(BauSystem.MESSAGE.parse(loreKey, player)), false, clickType -> {}).getItemStack();
}
@Override
public boolean click(ClickType click, Player p) {
command.toggle(p);
return false;
}
}
@@ -0,0 +1,124 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.inventoryfiller;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.linkage.Linked;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Container;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@Linked
public class InventoryFiller implements Listener {
@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("inventoryfill", false)) return;
if (!event.getPlayer().isSneaking()) return;
Block block = event.getPlayer().getTargetBlockExact(5);
if (block == null) return;
if (!(block.getState() instanceof Container)) return;
Container container = (Container) block.getState();
Inventory inventory = container.getInventory();
ItemStack itemStack = event.getItemDrop().getItemStack().clone();
itemStack.setAmount(itemStack.getType().getMaxStackSize());
event.setCancelled(true);
for (int i = 0; i < inventory.getSize(); i++) {
inventory.setItem(i, itemStack);
}
BauSystem.MESSAGE.sendPrefixless("CHESTFILLER_FILLED", event.getPlayer(), ChatMessageType.ACTION_BAR);
}
/**
* For MacOS user: https://www.curseforge.com/minecraft/mc-mods/shift-scroll-fix
*/
@EventHandler
public void onPlayerItemHeld(PlayerItemHeldEvent event) {
if(!Permission.BUILD.hasPermission(event.getPlayer())) return;
if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("inventoryfill", false)) return;
if (!event.getPlayer().isSneaking()) return;
ItemStack itemStack = event.getPlayer().getInventory().getItemInMainHand();
if (itemStack.getType() == Material.AIR) return;
Block block = event.getPlayer().getTargetBlockExact(5);
if (block == null) return;
if (!(block.getState() instanceof Container)) return;
Container container = (Container) block.getState();
Inventory inventory = container.getInventory();
event.setCancelled(true);
int upperBound = event.getPreviousSlot() + 4;
if (upperBound > 8) upperBound -= 8;
int lowerBound = event.getPreviousSlot() - 5;
if (lowerBound < 0) lowerBound += 8;
int direction = 0;
if (event.getPreviousSlot() != 0 && (event.getNewSlot() > event.getPreviousSlot() || (upperBound < event.getPreviousSlot() && event.getNewSlot() < upperBound))) {
direction = 1;
} else if (event.getPreviousSlot() == 0 && event.getNewSlot() > upperBound) {
direction = -1;
} else if (event.getNewSlot() < event.getPreviousSlot() || (lowerBound > event.getPreviousSlot() && event.getNewSlot() >= lowerBound)) {
direction = -1;
} else if (event.getPreviousSlot() == 0) {
direction = 1;
}
int count = 0;
int emptySlot = -1;
int filledSlot = -1;
for (int i = 0; i < inventory.getSize(); i++) {
ItemStack current = inventory.getItem(i);
if (current == null) {
if (emptySlot == -1) emptySlot = i;
continue;
}
if (current.getType() == itemStack.getType()) {
count += current.getAmount();
int emptyAmount = itemStack.getType().getMaxStackSize() - current.getAmount();
if (direction == -1) filledSlot = Math.max(filledSlot, i);
if (emptyAmount > 0) filledSlot = Math.min(i, filledSlot);
if (emptyAmount > 0 && filledSlot == -1) filledSlot = i;
}
}
int slotToUse = direction == -1 ? filledSlot : (filledSlot == -1 ? emptySlot : filledSlot);
if (slotToUse == -1) return;
ItemStack current = inventory.getItem(slotToUse);
if (current == null) {
ItemStack now = itemStack.clone();
now.setAmount(1);
inventory.setItem(slotToUse, now);
} else {
current.setAmount(current.getAmount() + direction);
}
BauSystem.MESSAGE.sendPrefixless("CHESTFILLER_COUNT", event.getPlayer(), ChatMessageType.ACTION_BAR, itemStack.getType(), count + direction);
}
}
@@ -0,0 +1,28 @@
package de.steamwar.bausystem.features.inventoryfiller;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.configplayer.Config;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class InventoryFillerCommand extends SWCommand {
public InventoryFillerCommand() {
super("inventoryfill");
}
@Register(description = {"INVENTORY_FILL_HELP", "INVENTORY_FILL_INFO"})
public void toggle(Player player) {
boolean inventoryFill = Config.getInstance().get(player).getPlainValueOrDefault("inventoryfill", false);
Config.getInstance().get(player).put("inventoryfill", !inventoryFill);
if (!inventoryFill) {
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("INVENTORY_FILL_ENABLE", player));
BauSystem.MESSAGE.send("INVENTORY_FILL_INFO", player);
}else {
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("INVENTORY_FILL_DISABLE", player));
}
}
}
@@ -0,0 +1,34 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.killchecker;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Cuboid {
private double x;
private double y;
private double z;
private double dx;
private double dy;
private double dz;
}
@@ -0,0 +1,115 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.killchecker;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.bausystem.utils.bossbar.BossBarService;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import de.steamwar.linkage.LinkedInstance;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Linked
public class KillcheckerCommand extends SWCommand implements Listener {
private Map<Region, KillcheckerVisualizer> visualizers = new HashMap<>();
@LinkedInstance
public BossBarService bossBarService;
public KillcheckerCommand() {
super("killchecker");
addDefaultHelpMessage("KILLCHECKER_INFO");
addDefaultHelpMessage("KILLCHECKER_INFO2");
}
@Register(value = "enable", description = "KILLCHECKER_HELP_ENABLE")
public void genericCommand(@Validator Player player, @OptionalValue("-outline") @StaticValue(value = {"-area", "-outline"}, allowISE = true) boolean onlyOutline) {
Region region = Region.getRegion(player.getLocation());
KillcheckerVisualizer killcheckerVisualizer = visualizers.computeIfAbsent(region, region1 -> new KillcheckerVisualizer(region1, bossBarService));
killcheckerVisualizer.recalc();
killcheckerVisualizer.show(player, onlyOutline);
BauSystem.MESSAGE.send("KILLCHECKER_ENABLE", player);
}
@Register(value = "disable", description = "KILLCHECKER_HELP_DISABLE")
public void disableCommand(Player player) {
Region region = Region.getRegion(player.getLocation());
KillcheckerVisualizer killcheckerVisualizer = visualizers.get(region);
if (killcheckerVisualizer != null) {
if (killcheckerVisualizer.hide(player)) {
visualizers.remove(region);
}
}
BauSystem.MESSAGE.send("KILLCHECKER_DISABLE", player);
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(this::hide);
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
hide(event.getPlayer());
}
private void hide(Player player) {
new HashSet<>(visualizers.entrySet()).forEach(regionKillcheckerVisualizerEntry -> {
if (regionKillcheckerVisualizerEntry.getValue().hide(player)) {
visualizers.remove(regionKillcheckerVisualizerEntry.getKey());
}
});
}
private void recalc(Block block) {
Region region = Region.getRegion(block.getLocation());
KillcheckerVisualizer killcheckerVisualizer = visualizers.get(region);
if (killcheckerVisualizer != null) {
killcheckerVisualizer.recalc();
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
recalc(event.getBlock());
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
recalc(event.getBlock());
}, 1);
}
}
@@ -0,0 +1,390 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.killchecker;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.utils.RegionExtensionType;
import de.steamwar.bausystem.region.utils.RegionType;
import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar;
import de.steamwar.bausystem.utils.bossbar.BossBarService;
import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RFallingBlockEntity;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.boss.BarColor;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class KillcheckerVisualizer {
private static final Material[] MATERIALS = new Material[]{
Material.LIME_STAINED_GLASS,
Material.LIME_CONCRETE,
Material.GREEN_STAINED_GLASS,
Material.GREEN_CONCRETE,
Material.YELLOW_STAINED_GLASS,
Material.YELLOW_CONCRETE,
Material.ORANGE_STAINED_GLASS,
Material.ORANGE_CONCRETE,
Material.RED_STAINED_GLASS,
Material.RED_CONCRETE,
Material.PURPLE_STAINED_GLASS,
Material.PURPLE_CONCRETE,
Material.BLACK_STAINED_GLASS,
Material.BLACK_CONCRETE,
};
private static final World WORLD = Bukkit.getWorlds().get(0);
private static final double SURROUND = 4.5;
private final Point minPoint;
private final Point maxPoint;
private final int yArea;
private final int zArea;
private final int xArea;
private final Region region;
private final BossBarService bossBarService;
public KillcheckerVisualizer(Region region, BossBarService bossBarService) {
this.region = region;
this.minPoint = region.getMinPoint(RegionType.BUILD, RegionExtensionType.NORMAL);
this.maxPoint = region.getMaxPoint(RegionType.BUILD, RegionExtensionType.NORMAL);
yArea = (maxPoint.getX() - minPoint.getX()) * (maxPoint.getZ() - minPoint.getZ());
zArea = (maxPoint.getX() - minPoint.getX()) * (maxPoint.getY() - minPoint.getY());
xArea = (maxPoint.getY() - minPoint.getY()) * (maxPoint.getZ() - minPoint.getZ());
this.bossBarService = bossBarService;
}
private final REntityServer outline = new REntityServer();
private final REntityServer inner = new REntityServer();
private final Map<Point, Integer> killCount = new HashMap<>();
private final Set<Point> outlinePointsCache = new HashSet<>();
private final Map<Point, REntity> rEntities = new HashMap<>();
private double percent = 0;
private int kills = 0;
private int cannonCount = 0;
public void recalc() {
Set<Cuboid> cuboids = new HashSet<>();
Set<Point> points = new HashSet<>();
for (int x = minPoint.getX() + 1; x < maxPoint.getX(); x++) {
for (int y = minPoint.getY(); y < maxPoint.getY(); y++) {
for (int z = minPoint.getZ() + 1; z < maxPoint.getZ(); z++) {
if (points.contains(new Point(x, y, z))) continue;
Block block = WORLD.getBlockAt(x, y, z);
if (block.getType().isAir()) continue;
String name = block.getType().name();
if (!name.endsWith("_WOOL") && !name.endsWith("_STAINED_GLASS") && !name.endsWith("_CONCRETE") && !name.endsWith("_TERRACOTTA")) continue;
if (name.equals("_GLAZED_TERRACOTTA")) continue;
Cuboid cuboid = create(block.getType(), x, y, z);
cuboids.add(cuboid);
for (int dx = (int) cuboid.getX(); dx <= cuboid.getDx(); dx++) {
for (int dy = (int) cuboid.getY(); dy <= cuboid.getDy(); dy++) {
for (int dz = (int) cuboid.getZ(); dz <= cuboid.getDz(); dz++) {
points.add(new Point(dx, dy, dz));
}
}
}
}
}
}
cannonCount = cuboids.size();
Map<Point, Integer> kill = new HashMap<>();
int yKills = 0;
int yCount = 0;
Set<Point> yPoints = new HashSet<>();
for (int x = minPoint.getX(); x <= maxPoint.getX(); x++) {
for (int z = minPoint.getZ(); z <= maxPoint.getZ(); z++) {
Set<Cuboid> cuboidSet = new HashSet<>();
for (Cuboid cuboid : cuboids) {
if (x >= cuboid.getX() - SURROUND && x < cuboid.getDx() + SURROUND && z >= cuboid.getZ() - SURROUND && z < cuboid.getDz() + SURROUND) {
cuboidSet.add(cuboid);
}
}
if (cuboidSet.size() > 1) {
yCount++;
yKills += splitIntoDoubleKills(cuboidSet.size());
Point p2 = new Point(x, maxPoint.getY() + 1, z);
yPoints.add(p2);
kill.put(p2, Math.max(kill.getOrDefault(p2, 0), cuboidSet.size()));
}
}
}
int xKills = 0;
int xCount = 0;
Set<Point> xPoints = new HashSet<>();
for (int y = minPoint.getY(); y <= maxPoint.getY(); y++) {
for (int z = minPoint.getZ(); z <= maxPoint.getZ(); z++) {
Set<Cuboid> cuboidSet = new HashSet<>();
for (Cuboid cuboid : cuboids) {
if (y >= cuboid.getY() - SURROUND && y < cuboid.getDy() + SURROUND && z >= cuboid.getZ() - SURROUND && z < cuboid.getDz() + SURROUND) {
cuboidSet.add(cuboid);
}
}
if (cuboidSet.size() > 1) {
xCount++;
xKills += splitIntoDoubleKills(cuboidSet.size());
Point p1 = new Point(minPoint.getX() - 1, y, z);
xPoints.add(p1);
kill.put(p1, Math.max(kill.getOrDefault(p1, 0), cuboidSet.size()));
Point p2 = new Point(maxPoint.getX() + 1, y, z);
xPoints.add(p2);
kill.put(p2, Math.max(kill.getOrDefault(p2, 0), cuboidSet.size()));
}
}
}
int zKills = 0;
int zCount = 0;
Set<Point> zPoints = new HashSet<>();
for (int x = minPoint.getX(); x <= maxPoint.getX(); x++) {
for (int y = minPoint.getY(); y <= maxPoint.getY(); y++) {
Set<Cuboid> cuboidSet = new HashSet<>();
for (Cuboid cuboid : cuboids) {
if (x >= cuboid.getX() - SURROUND && x < cuboid.getDx() + SURROUND && y >= cuboid.getY() - SURROUND && y < cuboid.getDy() + SURROUND) {
cuboidSet.add(cuboid);
}
}
if (cuboidSet.size() > 1) {
zCount++;
zKills += splitIntoDoubleKills(cuboidSet.size());
Point p1 = new Point(x, y, minPoint.getZ() - 1);
zPoints.add(p1);
kill.put(p1, Math.max(kill.getOrDefault(p1, 0), cuboidSet.size()));
Point p2 = new Point(x, y, maxPoint.getZ() + 1);
zPoints.add(p2);
kill.put(p2, Math.max(kill.getOrDefault(p2, 0), cuboidSet.size()));
}
}
}
Set<Point> outlinePoints = new HashSet<>();
yPoints.forEach(point -> {
Point p1 = new Point(point.getX() - 1, point.getY(), point.getZ());
Point p2 = new Point(point.getX() + 1, point.getY(), point.getZ());
Point p3 = new Point(point.getX(), point.getY(), point.getZ() - 1);
Point p4 = new Point(point.getX(), point.getY(), point.getZ() + 1);
Point p5 = new Point(point.getX() - 1, point.getY(), point.getZ() - 1);
Point p6 = new Point(point.getX() - 1, point.getY(), point.getZ() + 1);
Point p7 = new Point(point.getX() + 1, point.getY(), point.getZ() - 1);
Point p8 = new Point(point.getX() + 1, point.getY(), point.getZ() + 1);
int count = kill.get(point);
int surrounded = 0;
if (kill.getOrDefault(p1, 0) == count) surrounded++;
if (kill.getOrDefault(p2, 0) == count) surrounded++;
if (kill.getOrDefault(p3, 0) == count) surrounded++;
if (kill.getOrDefault(p4, 0) == count) surrounded++;
if (surrounded != 4) outlinePoints.add(point);
if (kill.getOrDefault(p5, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p6, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p7, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p8, 0) != count) outlinePoints.add(point);
});
xPoints.forEach(point -> {
Point p1 = new Point(point.getX(), point.getY() - 1, point.getZ());
Point p2 = new Point(point.getX(), point.getY() + 1, point.getZ());
Point p3 = new Point(point.getX(), point.getY(), point.getZ() - 1);
Point p4 = new Point(point.getX(), point.getY(), point.getZ() + 1);
Point p5 = new Point(point.getX(), point.getY() - 1, point.getZ() - 1);
Point p6 = new Point(point.getX(), point.getY() - 1, point.getZ() + 1);
Point p7 = new Point(point.getX(), point.getY() + 1, point.getZ() - 1);
Point p8 = new Point(point.getX(), point.getY() + 1, point.getZ() + 1);
int count = kill.get(point);
int surrounded = 0;
if (kill.getOrDefault(p1, 0) == count) surrounded++;
if (kill.getOrDefault(p2, 0) == count) surrounded++;
if (kill.getOrDefault(p3, 0) == count) surrounded++;
if (kill.getOrDefault(p4, 0) == count) surrounded++;
if (surrounded != 4) outlinePoints.add(point);
if (kill.getOrDefault(p5, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p6, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p7, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p8, 0) != count) outlinePoints.add(point);
});
zPoints.forEach(point -> {
Point p1 = new Point(point.getX() - 1, point.getY(), point.getZ());
Point p2 = new Point(point.getX() + 1, point.getY(), point.getZ());
Point p3 = new Point(point.getX(), point.getY() - 1, point.getZ());
Point p4 = new Point(point.getX(), point.getY() + 1, point.getZ());
Point p5 = new Point(point.getX() - 1, point.getY() - 1, point.getZ());
Point p6 = new Point(point.getX() - 1, point.getY() + 1, point.getZ());
Point p7 = new Point(point.getX() + 1, point.getY() - 1, point.getZ());
Point p8 = new Point(point.getX() + 1, point.getY() + 1, point.getZ());
int count = kill.get(point);
int surrounded = 0;
if (kill.getOrDefault(p1, 0) == count) surrounded++;
if (kill.getOrDefault(p2, 0) == count) surrounded++;
if (kill.getOrDefault(p3, 0) == count) surrounded++;
if (kill.getOrDefault(p4, 0) == count) surrounded++;
if (surrounded != 4) outlinePoints.add(point);
if (kill.getOrDefault(p5, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p6, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p7, 0) != count) outlinePoints.add(point);
if (kill.getOrDefault(p8, 0) != count) outlinePoints.add(point);
});
double xPercent = zCount / (double) xArea;
double yPercent = yCount / (double) yArea;
double zPercent = xCount / (double) zArea;
percent = (xPercent + yPercent + zPercent) / 3;
kills = zKills + yKills + xKills;
outline.getPlayers().forEach(this::updateBossBar);
Set<Point> pointSet = new HashSet<>(killCount.keySet());
Set<Point> outlinePointsCacheLast = new HashSet<>(outlinePointsCache);
outlinePointsCache.clear();
for (Point point : pointSet) {
if (!kill.containsKey(point)) {
rEntities.get(point).die();
rEntities.remove(point);
killCount.remove(point);
}
}
kill.forEach((point, count) -> {
if (rEntities.containsKey(point)) {
if (killCount.get(point) == count && outlinePoints.contains(point) == outlinePointsCacheLast.contains(point)) return;
rEntities.get(point).die();
}
RFallingBlockEntity entity = new RFallingBlockEntity(outlinePoints.contains(point) ? outline : inner, point.toLocation(WORLD, 0.5, 0, 0.5), MATERIALS[Math.min(count - 1, MATERIALS.length) - 1]);
entity.setNoGravity(true);
rEntities.put(point, entity);
if (outlinePoints.contains(point)) outlinePointsCache.add(point);
killCount.put(point, count);
});
}
private int splitIntoDoubleKills(int kills) {
return kills * (kills - 1) / 2;
}
private void updateBossBar(Player player) {
BauSystemBossbar bossbar = bossBarService.get(player, region, "killchecker");
bossbar.setTitle(BauSystem.MESSAGE.parse("KILLCHECKER_BOSSBAR", player, kills, ((int) (percent * 1000) / 10.0), cannonCount));
bossbar.setProgress(Math.min(Math.max(percent, 0), 1));
if (percent >= 0.35) {
bossbar.setColor(BarColor.RED);
} else if (percent >= 0.25) {
bossbar.setColor(BarColor.PURPLE);
} else if (percent >= 0.15) {
bossbar.setColor(BarColor.YELLOW);
} else {
bossbar.setColor(BarColor.GREEN);
}
}
private Cuboid create(Material type, int x, int y, int z) {
Set<Point> checked = new HashSet<>();
Set<Point> points = new HashSet<>();
points.add(new Point(x, y, z));
while (!points.isEmpty()) {
Point point = points.iterator().next();
points.remove(point);
if (!checked.add(point)) continue;
if (point.getX() < minPoint.getX() || point.getX() > maxPoint.getX()) continue;
if (point.getY() < minPoint.getY() || point.getY() > maxPoint.getY()) continue;
if (point.getZ() < minPoint.getZ() || point.getZ() > maxPoint.getZ()) continue;
if (WORLD.getBlockAt(point.getX() + 1, point.getY(), point.getZ()).getType() == type) {
points.add(new Point(point.getX() + 1, point.getY(), point.getZ()));
}
if (WORLD.getBlockAt(point.getX(), point.getY() + 1, point.getZ()).getType() == type) {
points.add(new Point(point.getX(), point.getY() + 1, point.getZ()));
}
if (WORLD.getBlockAt(point.getX(), point.getY(), point.getZ() + 1).getType() == type) {
points.add(new Point(point.getX(), point.getY(), point.getZ() + 1));
}
if (WORLD.getBlockAt(point.getX() - 1, point.getY(), point.getZ()).getType() == type) {
points.add(new Point(point.getX() - 1, point.getY(), point.getZ()));
}
if (WORLD.getBlockAt(point.getX(), point.getY() - 1, point.getZ()).getType() == type) {
points.add(new Point(point.getX(), point.getY() - 1, point.getZ()));
}
if (WORLD.getBlockAt(point.getX(), point.getY(), point.getZ() - 1).getType() == type) {
points.add(new Point(point.getX(), point.getY(), point.getZ() - 1));
}
}
int minX = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE;
int maxY = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE;
int maxZ = Integer.MIN_VALUE;
for (Point point : checked) {
if (point.getX() < minX) minX = point.getX();
if (point.getX() > maxX) maxX = point.getX();
if (point.getY() < minY) minY = point.getY();
if (point.getY() > maxY) maxY = point.getY();
if (point.getZ() < minZ) minZ = point.getZ();
if (point.getZ() > maxZ) maxZ = point.getZ();
}
return new Cuboid(minX, minY, minZ, maxX, maxY, maxZ);
}
public void show(Player player, boolean onlyOutline) {
outline.addPlayer(player);
if (!onlyOutline) {
inner.addPlayer(player);
} else {
inner.removePlayer(player);
}
updateBossBar(player);
}
public boolean hide(Player player) {
outline.removePlayer(player);
inner.removePlayer(player);
bossBarService.remove(player, region, "killchecker");
if (outline.getPlayers().isEmpty() && inner.getPlayers().isEmpty()) {
outline.close();
inner.close();
return true;
}
return false;
}
}
@@ -0,0 +1,380 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.loader.elements.LoaderElement;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.impl.LoaderTNT;
import de.steamwar.bausystem.features.loader.elements.impl.LoaderWait;
import de.steamwar.bausystem.shared.EnumDisplay;
import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
public class Loader implements Listener {
private static final Map<Player, Loader> LOADER_MAP = new HashMap<>();
public static Loader getLoader(Player player) {
return LOADER_MAP.get(player);
}
public static void newLoader(Player player) {
LOADER_MAP.put(player, new Loader(player));
}
private final Player p;
@Getter
private Stage stage = Stage.SETUP;
private LoaderRecorder recorder;
private List<LoaderElement> elements = new ArrayList<>();
private int currentElement = 0;
private long waitTime = 0;
public Loader(Player p) {
this.p = p;
this.recorder = new LoaderRecorder(p, elements);
Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance());
BauSystem.runTaskTimer(BauSystem.getInstance(), () -> {
if (stage != Stage.RUNNING) return;
if(!Permission.BUILD.hasPermission(p)) return;
if (waitTime > 0) {
waitTime--;
return;
}
if (currentElement >= elements.size()) {
currentElement = 0;
if (stage == Stage.SINGLE) {
stage = Stage.PAUSE;
return;
}
}
while (currentElement < elements.size()) {
LoaderElement element = elements.get(currentElement);
currentElement++;
element.execute(delay -> waitTime = delay);
if (waitTime > 0) {
if (element instanceof LoaderTNT) currentElement--;
return;
}
}
}, 0, 1);
}
public void single() {
if (stage == Stage.END) return;
if (stage == Stage.RUNNING) return;
stage = Stage.SINGLE;
if (recorder != null) {
recorder.stop();
recorder = null;
}
if (elements.isEmpty()) {
BauSystem.MESSAGE.send("LOADER_NOTHING_RECORDED", p);
stop();
}
}
public void start() {
if (stage == Stage.END) return;
if (stage == Stage.RUNNING) return;
stage = Stage.RUNNING;
if (recorder != null) {
recorder.stop();
recorder = null;
}
if (elements.isEmpty()) {
BauSystem.MESSAGE.send("LOADER_NOTHING_RECORDED", p);
stop();
}
}
public void pause() {
if (stage == Stage.END) return;
if (stage == Stage.PAUSE) return;
stage = Stage.PAUSE;
if (recorder != null) {
recorder.stop();
recorder = null;
}
}
public void stop() {
stage = Stage.END;
if (recorder != null) {
recorder.stop();
recorder = null;
}
elements.clear();
LOADER_MAP.remove(p);
}
public boolean setTicksBetweenShots(int delay) {
if (elements.size() == 0) return false;
LoaderElement loaderElement = elements.get(elements.size() - 1);
if (loaderElement instanceof LoaderWait) {
((LoaderWait) loaderElement).setDelay(delay);
return true;
}
return false;
}
public void setTicksBetweenBlocks(int delay) {
for (int i = 0; i < elements.size() - 1; i++) {
LoaderElement loaderElement = elements.get(i);
if (loaderElement instanceof LoaderWait) {
((LoaderWait) loaderElement).setDelay(delay);
}
}
}
public void gui(SettingsSorting settingsSorting) {
List<SWListInv.SWListEntry<LoaderElement>> list = new ArrayList<>();
AtomicBoolean allWait = new AtomicBoolean(true);
Runnable updateRunnable = () -> {
list.clear();
for (int i = 0; i < elements.size(); i++) {
LoaderElement previous = i > 0 ? elements.get(i - 1) : null;
LoaderElement current = elements.get(i);
LoaderElement next = i < elements.size() - 1 ? elements.get(i + 1) : null;
if (!settingsSorting.shouldShow(previous, current, next)) {
continue;
}
if ((!(current instanceof LoaderWait))) {
allWait.set(false);
}
SWItem item = current.menu(p);
if (current instanceof LoaderInteractionElement<?>) {
LoaderInteractionElement<?> interactionElement = (LoaderInteractionElement<?>) current;
List<String> lore = new ArrayList<>();
if (item.getItemMeta() != null && item.getItemMeta().getLore() != null) {
lore.addAll(item.getItemMeta().getLore());
lore.add("§8");
}
lore.add(BauSystem.MESSAGE.parse("LOADER_SETTING_MODES", p, interactionElement.size()));
lore.add(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p));
item.setLore(lore);
} else {
List<String> lore = new ArrayList<>();
if (item.getItemMeta() != null && item.getItemMeta().getLore() != null) {
lore.addAll(item.getItemMeta().getLore());
lore.add("§8");
}
lore.add(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", p));
item.setLore(lore);
}
list.add(new SWListInv.SWListEntry<>(item, current));
}
if (list.isEmpty()) {
allWait.set(false);
}
};
updateRunnable.run();
SWListInv<LoaderElement> swListInv = new SWListInv<>(p, BauSystem.MESSAGE.parse("LOADER_GUI_TITLE", p), false, list, (clickType, loaderElement) -> {});
swListInv.setCallback((clickType, entry) -> entry.click(p, () -> {
updateRunnable.run();
swListInv.open();
}));
SWItem settingItem = new SWItem(settingsSorting.getMaterial(), "§e" + BauSystem.MESSAGE.parse(settingsSorting.getName(), p), clickType -> {
if (clickType == ClickType.LEFT) {
int index = settingsSorting.ordinal() + 1;
if (index >= SettingsSorting.LENGTH) {
index = 0;
}
gui(SettingsSorting.values()[index]);
} else if (clickType == ClickType.RIGHT) {
int index = settingsSorting.ordinal() - 1;
if (index < 0) {
index = SettingsSorting.LENGTH - 1;
}
gui(SettingsSorting.values()[index]);
}
});
List<String> strings = new ArrayList<>();
for (SettingsSorting setting : SettingsSorting.values()) {
if (setting == settingsSorting) {
strings.add("§e> §7" + BauSystem.MESSAGE.parse(setting.getName(), p));
} else {
strings.add("§8> §7" + BauSystem.MESSAGE.parse(setting.getName(), p));
}
}
settingItem.setLore(strings);
swListInv.setItem(48, settingItem);
if (allWait.get()) {
SWItem setWait = new SWItem(Material.PAPER, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_SET_ALL", p), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("LOADER_GUI_SHOW_WAITS_TITLE", p), "");
swAnvilInv.setCallback(s -> {
try {
long delay = Math.max(Long.parseLong(s), 0);
list.forEach(loaderElementSWListEntry -> {
((LoaderWait) loaderElementSWListEntry.getObject()).setDelay(delay);
});
} catch (NumberFormatException ignored) {
}
gui(settingsSorting);
});
swAnvilInv.open();
});
swListInv.setItem(50, setWait);
} else {
swListInv.setItem(50, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§8"));
}
swListInv.open();
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
if (event.getPlayer() != p) return;
stop();
}
public String getProgress() {
return Math.max(currentElement, 1) + "§8/§7" + elements.size();
}
public enum SettingsSorting {
ALL {
@Override
public Material getMaterial() {
return Material.STRUCTURE_VOID;
}
@Override
public String getName() {
return "LOADER_GUI_SHOW_ALL";
}
@Override
public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) {
return true;
}
},
WAIT {
@Override
public Material getMaterial() {
return Material.CLOCK;
}
@Override
public String getName() {
return "LOADER_GUI_SHOW_WAITS";
}
@Override
public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) {
return current instanceof LoaderWait;
}
},
WAIT_BETWEEN_TNT {
@Override
public Material getMaterial() {
return Material.REDSTONE_BLOCK;
}
@Override
public String getName() {
return "LOADER_GUI_SHOW_WAITS_BETWEEN_TNT";
}
@Override
public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) {
return previous instanceof LoaderTNT && current instanceof LoaderWait && next instanceof LoaderTNT;
}
},
INTERACTIONS {
@Override
public Material getMaterial() {
return Material.REPEATER;
}
@Override
public String getName() {
return "LOADER_GUI_SHOW_INTERACTIONS";
}
@Override
public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) {
return current instanceof LoaderInteractionElement && !(current instanceof LoaderTNT);
}
},
TNT {
@Override
public Material getMaterial() {
return Material.TNT;
}
@Override
public String getName() {
return "LOADER_GUI_SHOW_TNT";
}
@Override
public boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next) {
return current instanceof LoaderTNT;
}
},
;
public static int LENGTH = SettingsSorting.values().length;
public abstract Material getMaterial();
public abstract String getName();
public abstract boolean shouldShow(LoaderElement previous, LoaderElement current, LoaderElement next);
}
@AllArgsConstructor
public enum Stage implements EnumDisplay {
SETUP("LOADER_SETUP"),
RUNNING("LOADER_RUNNING"),
SINGLE("LOADER_SINGLE"),
PAUSE("LOADER_PAUSE"),
END("LOADER_END");
@Getter
private final String chatValue;
}
}
@@ -0,0 +1,122 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@Linked
public class LoaderCommand extends SWCommand implements Listener {
public LoaderCommand() {
super("loader");
}
private boolean loaderNullCheck(Loader loader, Player p) {
if (loader == null) {
BauSystem.MESSAGE.send("LOADER_NO_LOADER", p);
return true;
}
return false;
}
@Register(value = "setup", description = "LOADER_HELP_SETUP")
public void setupLoader(@Validator Player player) {
if (Loader.getLoader(player) != null) {
BauSystem.MESSAGE.send("LOADER_SETUP_STOP_FIRST", player);
return;
}
Loader.newLoader(player);
BauSystem.MESSAGE.send("LOADER_NEW", player);
BauSystem.MESSAGE.send("LOADER_HOW_TO_START", player);
}
@Register(value = "start", description = "LOADER_HELP_START")
public void startLoader(@Validator Player player) {
Loader loader = Loader.getLoader(player);
if (loaderNullCheck(loader, player)) return;
loader.start();
BauSystem.MESSAGE.send("LOADER_ACTIVE", player);
}
@Register(value = "stop", description = "LOADER_HELP_STOP")
public void stopLoader(@Validator Player player) {
Loader loader = Loader.getLoader(player);
if (loaderNullCheck(loader, player)) return;
loader.stop();
BauSystem.MESSAGE.send("LOADER_STOP", player);
}
@Register(value = "pause", description = "LOADER_HELP_PAUSE")
public void pauseLoader(@Validator Player player) {
Loader loader = Loader.getLoader(player);
if (loaderNullCheck(loader, player)) return;
loader.pause();
BauSystem.MESSAGE.send("LOADER_PAUSED", player);
}
@Register(value = "gui", description = "LOADER_HELP_GUI")
public void guiLoader(@Validator Player player) {
Loader loader = Loader.getLoader(player);
if (loaderNullCheck(loader, player)) return;
loader.gui(Loader.SettingsSorting.ALL);
}
@Register(value = "wait", description = "LOADER_HELP_WAIT")
public void shotDelayLoader(@Validator Player p, @Min(intValue = 1) @ErrorMessage("LOADER_SMALL_TIME") int delay) {
Loader loader = Loader.getLoader(p);
if (loaderNullCheck(loader, p)) return;
if (loader.setTicksBetweenShots(delay)) {
BauSystem.MESSAGE.send("LOADER_NEW_TIME", p, delay);
} else {
BauSystem.MESSAGE.send("LOADER_SMALL_TIME", p);
}
}
@Register(value = "speed", description = "LOADER_HELP_SPEED")
public void speedLoader(@Validator Player p, @Min(intValue = 0) @ErrorMessage("LOADER_SMALL_TIME") int delay) {
Loader loader = Loader.getLoader(p);
if (loaderNullCheck(loader, p)) return;
BauSystem.MESSAGE.send("LOADER_NEW_LOAD_TIME", p, delay);
loader.setTicksBetweenBlocks(delay);
}
@Register(value = "single", description = "LOADER_HELP_SINGLE")
public void singleLoader(@Validator Player p) {
Loader loader = Loader.getLoader(p);
if (loaderNullCheck(loader, p)) return;
loader.single();
BauSystem.MESSAGE.send("LOADER_SINGLE_CMD", p);
}
@EventHandler
public void onBauMemberUpdate(BauMemberUpdateEvent event) {
event.getNewSpectator().forEach(player -> {
Loader loader = Loader.getLoader(player);
if (loader == null) return;
loader.stop();
});
}
}
@@ -0,0 +1,231 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.SWUtils;
import de.steamwar.bausystem.features.loader.elements.LoaderElement;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.impl.*;
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.EquipmentSlot;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class LoaderRecorder implements Listener {
private Player player;
private List<LoaderElement> loaderElementList;
private long lastInteraction = TPSUtils.currentRealTick.get();
public LoaderRecorder(Player player, List<LoaderElement> loaderElementList) {
this.player = player;
this.loaderElementList = loaderElementList;
Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance());
}
public void stop() {
addWaitTime(true);
HandlerList.unregisterAll(this);
player = null;
blockSet.clear();
}
private void addWaitTime(boolean last) {
if (loaderElementList.isEmpty()) {
lastInteraction = TPSUtils.currentRealTick.get();
return;
}
if (loaderElementList.get(loaderElementList.size() - 1) instanceof LoaderWait) {
return;
}
long diff = TPSUtils.currentRealTick.get() - lastInteraction;
if (last) diff = 120;
lastInteraction = TPSUtils.currentRealTick.get();
loaderElementList.add(new LoaderWait(diff));
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
if (event.getPlayer() != player) return;
if (event.getBlock().getType() != Material.TNT) return;
addWaitTime(false);
loaderElementList.add(new LoaderTNT(event.getBlock().getLocation()));
message("LOADER_BUTTON_TNT");
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if (event.getPlayer() != player) return;
boolean removedOne = false;
for (int i = 0; i < loaderElementList.size(); i++) {
LoaderElement element = loaderElementList.get(i);
if (!(element instanceof LoaderInteractionElement)) continue;
LoaderInteractionElement interactionElement = (LoaderInteractionElement) element;
if (interactionElement.getLocation().equals(event.getBlock().getLocation())) {
loaderElementList.remove(i);
if (i > 0) {
loaderElementList.remove(i - 1);
}
removedOne = true;
break;
}
}
if (removedOne) {
if (event.getBlock().getType() != Material.TNT) {
event.setCancelled(true);
}
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("LOADER_MESSAGE_UNINTERACT", player));
}
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getPlayer() != player) return;
if (player.isSneaking()) return;
if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.PHYSICAL) return;
if (event.getClickedBlock().getType() == Material.OBSERVER) return;
if (event.getHand() == EquipmentSlot.OFF_HAND) return;
addWaitTime(false);
Block block = event.getClickedBlock();
getLoaderInteractionElement(block, (loaderInteractionElement, s) -> {
loaderElementList.add(loaderInteractionElement);
message(s);
});
}
private Map<Location, Long> blockSet = new HashMap<>();
private Map<Location, LoaderMovement> movementSet = new HashMap<>();
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if (event.getPlayer() != player) return;
Block fromBlock = event.getFrom().getBlock();
Block toBlock = event.getTo().getBlock();
calcMovementBlocks(fromBlock, toBlock);
fromBlock = fromBlock.getRelative(0, 1, 0);
toBlock = toBlock.getRelative(0, 1, 0);
calcMovementBlocks(fromBlock, toBlock);
}
private void calcMovementBlocks(Block fromBlock, Block toBlock) {
if (!blockSet.containsKey(toBlock.getLocation())) {
Long startTime = blockSet.remove(fromBlock.getLocation());
LoaderMovement loaderMovement = movementSet.remove(fromBlock.getLocation());
if (loaderMovement != null && startTime != null) {
loaderMovement.setInitialTicks(TPSUtils.currentRealTick.get() - startTime);
}
blockSet.put(toBlock.getLocation(), TPSUtils.currentRealTick.get());
addWaitTime(false);
loaderMovement = null;
Material type = toBlock.getType();
switch (type) {
case TRIPWIRE:
loaderMovement = new LoaderMovement(toBlock.getLocation(), "LOADER_BUTTON_TRIPWIRE", Material.STRING);
message("LOADER_BUTTON_TRIPWIRE");
break;
case LIGHT_WEIGHTED_PRESSURE_PLATE:
case HEAVY_WEIGHTED_PRESSURE_PLATE:
loaderMovement = new LoaderMovement(toBlock.getLocation(), "LOADER_BUTTON_WEIGHTED_PRESSURE_PLATE", type);
message("LOADER_BUTTON_WEIGHTED_PRESSURE_PLATE");
break;
default:
if (type.name().endsWith("PRESSURE_PLATE")) {
loaderMovement = new LoaderMovement(toBlock.getLocation(), "LOADER_BUTTON_PRESSURE_PLATE", type);
message("LOADER_BUTTON_PRESSURE_PLATE");
}
break;
}
if (loaderMovement != null) {
movementSet.put(toBlock.getLocation(), loaderMovement);
loaderElementList.add(loaderMovement);
}
}
}
public static void getLoaderInteractionElement(Block block, BiConsumer<LoaderInteractionElement<?>, String> consumer) {
Material type = block.getType();
switch (type) {
case COMPARATOR:
consumer.accept(new LoaderComparator(block.getLocation()), "LOADER_BUTTON_COMPARATOR");
break;
case REPEATER:
consumer.accept(new LoaderRepeater(block.getLocation()), "LOADER_BUTTON_REPEATER");
break;
case NOTE_BLOCK:
consumer.accept(new LoaderNoteBlock(block.getLocation()), "LOADER_BUTTON_NOTEBLOCK");
break;
case LEVER:
consumer.accept(new LoaderLever(block.getLocation()), "LOADER_BUTTON_SWITCH");
break;
case DAYLIGHT_DETECTOR:
consumer.accept(new LoaderDaylightDetector(block.getLocation()), "LOADER_BUTTON_DAYLIGHT_DETECTOR");
break;
case LECTERN:
consumer.accept(new LoaderLectern(block.getLocation()), "LOADER_BUTTON_LECTERN");
break;
case IRON_TRAPDOOR:
case IRON_DOOR:
break;
default:
if (type.name().endsWith("_TRAPDOOR")) {
consumer.accept(new LoaderOpenable(block.getLocation(), "LOADER_BUTTON_TRAPDOOR", type), "LOADER_BUTTON_TRAPDOOR");
} else if (type.name().endsWith("_DOOR")) {
consumer.accept(new LoaderOpenable(block.getLocation(), "LOADER_BUTTON_DOOR", type), "LOADER_BUTTON_DOOR");
} else if (type.name().endsWith("FENCE_GATE")) {
consumer.accept(new LoaderOpenable(block.getLocation(), "LOADER_BUTTON_FENCEGATE", type), "LOADER_BUTTON_FENCEGATE");
} else if (type.name().endsWith("STONE_BUTTON")) {
consumer.accept(new LoaderTicks(block.getLocation(), "LOADER_BUTTON_STONE_BUTTON", type, 20), "LOADER_BUTTON_STONE_BUTTON");
} else if (type.name().endsWith("BUTTON")) {
consumer.accept(new LoaderTicks(block.getLocation(), "LOADER_BUTTON_WOOD_BUTTON", type, 30), "LOADER_BUTTON_WOOD_BUTTON");
}
break;
}
}
private void message(String type) {
SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("LOADER_MESSAGE_INTERACT", player, BauSystem.MESSAGE.parse(type, player), loaderElementList.size()));
}
}
@@ -0,0 +1,55 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.utils.ScoreboardElement;
import de.steamwar.linkage.Linked;
import org.bukkit.entity.Player;
@Linked
public class LoaderScoreboardElement implements ScoreboardElement {
@Override
public ScoreboardGroup getGroup() {
return ScoreboardGroup.OTHER;
}
@Override
public int order() {
return 2;
}
@Override
public String get(Region region, Player p) {
if(!Permission.BUILD.hasPermission(p)) return null;
Loader loader = Loader.getLoader(p);
if (loader == null) return null;
if (loader.getStage() == Loader.Stage.RUNNING) {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_LOADER", p) + "§8: §a" + loader.getProgress();
} else if (loader.getStage() == Loader.Stage.PAUSE) {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_LOADER", p) + "§8: §c" + loader.getProgress();
} else {
return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_LOADER", p) + "§8: " + BauSystem.MESSAGE.parse(loader.getStage().getChatValue(), p);
}
}
}
@@ -0,0 +1,31 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements;
import de.steamwar.inventory.SWItem;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public interface LoaderElement {
SWItem menu(Player player);
void execute(Consumer<Long> delay);
void click(Player player, Runnable backAction);
}
@@ -0,0 +1,310 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements;
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 lombok.Getter;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.*;
import org.bukkit.block.data.type.Door;
import org.bukkit.block.data.type.Switch;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public abstract class LoaderInteractionElement<T extends Enum<T> & LoaderSettingsEnum> implements LoaderElement {
@Getter
protected final Location location;
protected int currentShot = 0;
protected T defaultSetting;
protected T newSetting;
protected T[] allSettings;
protected List<T> elements = new ArrayList<>();
protected List<Integer> extraPower = new ArrayList<>();
protected List<Long> extraTicks = new ArrayList<>();
protected int settingsGuiSize = 0;
protected LoaderInteractionElement(Location location, T defaultSetting, T newSetting, T[] allSettings) {
this.location = location;
this.defaultSetting = defaultSetting;
this.newSetting = newSetting;
this.allSettings = allSettings;
elements.add(defaultSetting);
extraPower.add(0);
extraTicks.add(0L);
for (T element : allSettings) {
settingsGuiSize = Math.max(element.getPos(), settingsGuiSize);
}
while (settingsGuiSize % 9 != 0) settingsGuiSize++;
settingsGuiSize += 9;
}
@Override
public void execute(Consumer<Long> delay) {
if (currentShot >= elements.size()) currentShot = 0;
if (checkBlockInWorld()) {
BlockData blockData = location.getBlock().getBlockData();
elements.get(currentShot).execute(location, blockData, this, extraPower.get(currentShot), extraTicks.get(currentShot), delay);
}
currentShot++;
if (currentShot >= elements.size()) currentShot = 0;
}
@Override
public void click(Player player, Runnable backAction) {
List<SWListInv.SWListEntry<Integer>> entries = new ArrayList<>();
Runnable updateRunnable = () -> {
entries.clear();
for (int i = 0; i < elements.size(); i++) {
SWItem swItem = elements.get(i).menu(player, this, extraPower.get(i), extraTicks.get(i));
swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player)));
entries.add(new SWListInv.SWListEntry<>(swItem, i));
}
};
updateRunnable.run();
SWListInv<Integer> listInv = new SWListInv<>(player, "Interaction Settings", false, entries, (clickType, entry) -> {});
listInv.setCallback((clickType, entry) -> {
openIndividualSettingsMenu(player, entry, () -> {
updateRunnable.run();
listInv.open();
}, () -> {
elements.remove((int) entry);
extraPower.remove((int) entry);
extraTicks.remove((int) entry);
if (elements.isEmpty()) {
elements.add(newSetting);
extraPower.add(0);
extraTicks.add(1L);
}
click(player, backAction);
});
});
listInv.setItem(48, new SWItem(Material.ARROW, "§7Back", clickType -> {
backAction.run();
}));
listInv.setItem(50, new SWItem(Material.GHAST_SPAWN_EGG, "§7Insert another Setting", clickType -> {
elements.add(defaultSetting);
extraPower.add(0);
extraTicks.add(1L);
openIndividualSettingsMenu(player, elements.size() - 1, () -> {
updateRunnable.run();
listInv.open();
}, () -> {
elements.remove(elements.size() - 1);
extraPower.remove(extraPower.size() - 1);
extraTicks.remove(extraTicks.size() - 1);
if (elements.isEmpty()) {
elements.add(newSetting);
extraPower.add(0);
extraTicks.add(1L);
}
click(player, backAction);
});
}));
listInv.open();
}
private void openIndividualSettingsMenu(Player player, int index, Runnable back, Runnable delete) {
T currentElement = elements.get(index);
int guiSize = settingsGuiSize;
int powerStart = guiSize - 9;
if (currentElement.hasPower(this)) {
guiSize += 18;
}
int ticksStart = guiSize - 9;
if (currentElement.hasTicks(this)) {
guiSize += 9;
}
SWInventory swInventory = new SWInventory(player, guiSize, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_TITLE", player));
for (int i = guiSize - 9; i < guiSize; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7", clickType -> {}));
swInventory.setItem(guiSize - 9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_BACK", player)).getItemStack(), clickType -> back.run());
swInventory.setItem(guiSize - 5, new SWItem(Material.WOODEN_AXE, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_COPY", player)).getItemStack(), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_GUI_COPY_TITLE", player), "1");
swAnvilInv.setCallback(s -> {
try {
int count = Integer.parseInt(s);
if (count < 1) count = 1;
if (count > 65536) count = 65536;
int power = extraPower.get(index);
long ticks = extraTicks.get(index);
for (int i = 0; i < count; i++) {
elements.add(currentElement);
extraPower.add(power);
extraTicks.add(ticks);
}
if (count == 1) {
openIndividualSettingsMenu(player, elements.size() - 1, back, delete);
} else {
back.run();
}
} catch (NumberFormatException e) {
back.run();
}
});
swAnvilInv.open();
});
swInventory.setItem(guiSize - 1, new SWItem(Material.BARRIER, BauSystem.MESSAGE.parse("LOADER_GUI_SETTINGS_DELETE", player)).getItemStack(), clickType -> delete.run());
for (T element : allSettings) {
SWItem item = element.menu(player, this, extraPower.get(index), extraTicks.get(index));
if (element == currentElement) {
item.setEnchanted(true);
}
swInventory.setItem(element.getPos(), item.getItemStack(), clickType -> {
elements.set(index, element);
openIndividualSettingsMenu(player, index, back, delete);
});
}
if (currentElement.hasPower(this)) {
for (int power = 0; power < 16; power++) {
int finalPowerPosition = power;
if (power >= 9) finalPowerPosition++;
SWItem powerItem = new SWItem(Material.REDSTONE, BauSystem.MESSAGE.parse("LOADER_SETTING_POWER", player, power), Arrays.asList(), false, clickType -> {});
powerItem.getItemStack().setAmount(Math.max(power, 1));
if (extraPower.get(index) == power) powerItem.setEnchanted(true);
int finalPower = power;
swInventory.setItem(finalPowerPosition + powerStart, powerItem.getItemStack(), clickType -> {
extraPower.set(index, finalPower);
openIndividualSettingsMenu(player, index, back, delete);
});
}
}
if (currentElement.hasTicks(this)) {
swInventory.setItem(ticksStart + 3, new SWItem(SWItem.getDye(1), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> {
long ticks = extraTicks.get(index);
ticks -= clickType.isShiftClick() ? 5 : 1;
if (ticks < 1) ticks = 1;
extraTicks.set(index, ticks);
openIndividualSettingsMenu(player, index, back, delete);
});
SWItem ticksItem = new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS", player, extraTicks.get(index)), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player)), false, clickType -> {});
ticksItem.getItemStack().setAmount((int) Math.min(extraTicks.get(index), 64));
swInventory.setItem(ticksStart + 4, ticksItem.getItemStack(), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_NAME", player), extraTicks.get(index) + "");
swAnvilInv.setCallback(s -> {
try {
long ticks = Long.parseLong(s);
if (ticks < 1) ticks = 1;
extraTicks.set(index, ticks);
} catch (NumberFormatException ignored) {
}
openIndividualSettingsMenu(player, index, back, delete);
});
swAnvilInv.open();
});
swInventory.setItem(ticksStart + 5, new SWItem(SWItem.getDye(10), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> {
long ticks = extraTicks.get(index);
ticks += clickType.isShiftClick() ? 5 : 1;
extraTicks.set(index, ticks);
openIndividualSettingsMenu(player, index, back, delete);
});
}
swInventory.open();
}
protected void update(BlockData blockData) {
Block block = location.getBlock();
if (blockData instanceof Door) {
Door door = (Door) blockData;
block.setBlockData(door);
if (door.getHalf() == Bisected.Half.BOTTOM) {
updateBlock(block.getRelative(BlockFace.UP), door.isOpen() ? 15 : 0);
} else {
updateBlock(block.getRelative(BlockFace.DOWN), door.isOpen() ? 15 : 0);
}
} else if (blockData instanceof Switch) {
Switch sw = (Switch) blockData;
updateBlock(block, sw);
FaceAttachable.AttachedFace face = sw.getAttachedFace();
if (face == FaceAttachable.AttachedFace.FLOOR) {
updateBlock(block.getRelative(BlockFace.DOWN), sw.isPowered() ? 15 : 0);
} else if (face == FaceAttachable.AttachedFace.CEILING) {
updateBlock(block.getRelative(BlockFace.UP), sw.isPowered() ? 15 : 0);
} else {
updateBlock(block.getRelative(sw.getFacing().getOppositeFace()), sw.isPowered() ? 15 : 0);
}
} else if (blockData instanceof Powerable) {
updateBlock(block, blockData);
updateBlock(block.getRelative(BlockFace.DOWN), ((Powerable) blockData).isPowered() ? 15 : 0);
} else if (blockData instanceof AnaloguePowerable) {
updateBlock(block, blockData);
updateBlock(block.getRelative(BlockFace.DOWN), ((AnaloguePowerable) blockData).getPower());
} else {
updateBlock(block, blockData);
}
}
private void updateBlock(Block block, int powered) {
BlockData data = block.getBlockData();
if (data instanceof Door) {
Door door = (Door) data;
door.setOpen(powered > 0);
block.setBlockData(door);
return;
} else if (data instanceof Powerable) {
Powerable powerable = (Powerable) data;
powerable.setPowered(powered > 0);
} else if (data instanceof AnaloguePowerable) {
AnaloguePowerable analoguePowerable = (AnaloguePowerable) data;
analoguePowerable.setPower(powered);
}
updateBlock(block, data);
}
private void updateBlock(Block block, BlockData data) {
block.setType(Material.BARRIER);
block.setBlockData(data);
}
public abstract boolean checkBlockInWorld();
protected final String translateItemName(String name, Player player) {
return BauSystem.MESSAGE.parse("LOADER_SETTING_NAME", player, BauSystem.MESSAGE.parse(name, player));
}
public int size() {
return elements.size();
}
}
@@ -0,0 +1,44 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public interface LoaderSettingsEnum<T, P extends LoaderInteractionElement<E>, E extends Enum<E> & LoaderSettingsEnum<T, P, E>> {
int getPos();
SWItem menu(Player player, P parent, int power, long ticks);
default boolean hasPower(P parent) {
return false;
}
default boolean hasTicks(P parent) {
return false;
}
void execute(Location location, T blockData, P parent, int power, long ticks, Consumer<Long> delay);
default String translateItemName(String name, String mode, Player player, Object... args) {
return BauSystem.MESSAGE.parse("LOADER_GUI_ITEM_NAME", player, BauSystem.MESSAGE.parse(name, player), BauSystem.MESSAGE.parse(mode, player, args));
}
}
@@ -0,0 +1,122 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.type.Comparator;
import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.function.Consumer;
public class LoaderComparator extends LoaderInteractionElement<LoaderComparator.ComparatorSettingsEnum> {
public LoaderComparator(Location location) {
super(location, ComparatorSettingsEnum.INTERACT, ComparatorSettingsEnum.NOOP, ComparatorSettingsEnum.values());
}
public enum ComparatorSettingsEnum implements LoaderSettingsEnum<Comparator, LoaderComparator, ComparatorSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer<Long> delay) {
blockData.setMode(blockData.getMode() == Comparator.Mode.COMPARE ? Comparator.Mode.SUBTRACT : Comparator.Mode.COMPARE);
parent.update(blockData);
}
},
COMPARE {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) {
return new SWItem(Material.COMPARATOR, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_COMPARE", player));
}
@Override
public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer<Long> delay) {
blockData.setMode(Comparator.Mode.COMPARE);
parent.update(blockData);
}
},
SUBTRACT {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderComparator parent, int power, long ticks) {
return new SWItem(Material.COMPARATOR, translateItemName("LOADER_BUTTON_COMPARATOR", "LOADER_INTERACTION_SUBTRACT", player));
}
@Override
public void execute(Location location, Comparator blockData, LoaderComparator parent, int power, long ticks, Consumer<Long> delay) {
blockData.setMode(Comparator.Mode.SUBTRACT);
parent.update(blockData);
}
}
}
@Override
public SWItem menu(Player player) {
SWItem swItem = new SWItem(Material.COMPARATOR, "§7Comparator");
swItem.setLore(Arrays.asList("§7Modes§8: §e" + elements.size(), "§8", "§7Click to edit"));
return swItem;
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.COMPARATOR;
}
}
@@ -0,0 +1,126 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.type.DaylightDetector;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderDaylightDetector extends LoaderInteractionElement<LoaderDaylightDetector.DaylightSettingsEnum> {
public LoaderDaylightDetector(Location location) {
super(location, DaylightSettingsEnum.INTERACT, DaylightSettingsEnum.NOOP, DaylightSettingsEnum.values());
}
public enum DaylightSettingsEnum implements LoaderSettingsEnum<DaylightDetector, LoaderDaylightDetector, DaylightSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer<Long> delay) {
blockData.setInverted(!blockData.isInverted());
blockData.setPower(15 - blockData.getPower());
parent.update(blockData);
}
},
DAY_MODE {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) {
return new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_UNPOWERED", player));
}
@Override
public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer<Long> delay) {
if (blockData.isInverted()) {
blockData.setInverted(false);
blockData.setPower(15 - blockData.getPower());
parent.update(blockData);
}
}
},
NIGHT_MODE {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderDaylightDetector parent, int power, long ticks) {
return new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", "LOADER_INTERACTION_POWERED", player));
}
@Override
public void execute(Location location, DaylightDetector blockData, LoaderDaylightDetector parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.isInverted()) {
blockData.setInverted(true);
blockData.setPower(15 - blockData.getPower());
parent.update(blockData);
}
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(Material.DAYLIGHT_DETECTOR, translateItemName("LOADER_BUTTON_DAYLIGHT_DETECTOR", player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.DAYLIGHT_DETECTOR;
}
}
@@ -0,0 +1,520 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Lectern;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import java.util.function.Consumer;
public class LoaderLectern extends LoaderInteractionElement<LoaderLectern.LecternSettingsEnum> {
public LoaderLectern(Location location) {
super(location, LecternSettingsEnum.NEXT_PAGE, LecternSettingsEnum.NOOP, LecternSettingsEnum.values());
}
public enum LecternSettingsEnum implements LoaderSettingsEnum<org.bukkit.block.data.type.Lectern, LoaderLectern, LecternSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
}
},
PREVIOUS_PAGE {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_PREV", player));
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
if (lectern.getPage() > 0) {
lectern.setPage(lectern.getPage() - 1);
parent.update(blockData);
}
}
},
NEXT_PAGE {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE_NEXT", player));
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (lectern.getPage() < pages) {
lectern.setPage(lectern.getPage() + 1);
parent.update(blockData);
}
}
},
PAGE_1 {
@Override
public int getPos() {
return 9;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 1));
swItem.getItemStack().setAmount(1);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (1 <= pages) {
lectern.setPage(1);
parent.update(blockData);
}
}
},
PAGE_2 {
@Override
public int getPos() {
return 10;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 2));
swItem.getItemStack().setAmount(2);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (2 <= pages) {
lectern.setPage(2);
parent.update(blockData);
}
}
},
PAGE_3 {
@Override
public int getPos() {
return 11;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 3));
swItem.getItemStack().setAmount(3);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (3 <= pages) {
lectern.setPage(3);
parent.update(blockData);
}
}
},
PAGE_4 {
@Override
public int getPos() {
return 12;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 4));
swItem.getItemStack().setAmount(4);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (4 <= pages) {
lectern.setPage(4);
parent.update(blockData);
}
}
},
PAGE_5 {
@Override
public int getPos() {
return 13;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 5));
swItem.getItemStack().setAmount(5);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (5 <= pages) {
lectern.setPage(5);
parent.update(blockData);
}
}
},
PAGE_6 {
@Override
public int getPos() {
return 14;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 6));
swItem.getItemStack().setAmount(6);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (6 <= pages) {
lectern.setPage(6);
parent.update(blockData);
}
}
},
PAGE_7 {
@Override
public int getPos() {
return 15;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 7));
swItem.getItemStack().setAmount(7);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (7 <= pages) {
lectern.setPage(7);
parent.update(blockData);
}
}
},
PAGE_8 {
@Override
public int getPos() {
return 16;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 8));
swItem.getItemStack().setAmount(8);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (8 <= pages) {
lectern.setPage(8);
parent.update(blockData);
}
}
},
PAGE_9 {
@Override
public int getPos() {
return 17;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 9));
swItem.getItemStack().setAmount(9);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (9 <= pages) {
lectern.setPage(9);
parent.update(blockData);
}
}
},
PAGE_10 {
@Override
public int getPos() {
return 19;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 10));
swItem.getItemStack().setAmount(10);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (10 <= pages) {
lectern.setPage(10);
parent.update(blockData);
}
}
},
PAGE_11 {
@Override
public int getPos() {
return 20;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 11));
swItem.getItemStack().setAmount(11);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (11 <= pages) {
lectern.setPage(11);
parent.update(blockData);
}
}
},
PAGE_12 {
@Override
public int getPos() {
return 21;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 12));
swItem.getItemStack().setAmount(12);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (12 <= pages) {
lectern.setPage(12);
parent.update(blockData);
}
}
},
PAGE_13 {
@Override
public int getPos() {
return 23;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 13));
swItem.getItemStack().setAmount(13);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (13 <= pages) {
lectern.setPage(13);
parent.update(blockData);
}
}
},
PAGE_14 {
@Override
public int getPos() {
return 24;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 14));
swItem.getItemStack().setAmount(14);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (14 <= pages) {
lectern.setPage(14);
parent.update(blockData);
}
}
},
PAGE_15 {
@Override
public int getPos() {
return 25;
}
@Override
public SWItem menu(Player player, LoaderLectern parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", "LOADER_INTERACTION_PAGE", player, 15));
swItem.getItemStack().setAmount(15);
return swItem;
}
@Override
public void execute(Location location, org.bukkit.block.data.type.Lectern blockData, LoaderLectern parent, int power, long ticks, Consumer<Long> delay) {
if (!blockData.hasBook()) return;
Lectern lectern = (Lectern) location.getBlock().getState();
ItemStack itemStack = lectern.getInventory().getItem(0);
if (itemStack == null) return;
int pages = ((BookMeta) itemStack.getItemMeta()).getPages().size();
if (15 <= pages) {
lectern.setPage(15);
parent.update(blockData);
}
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(Material.LECTERN, translateItemName("LOADER_BUTTON_LECTERN", player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.LECTERN;
}
}
@@ -0,0 +1,119 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.type.Switch;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderLever extends LoaderInteractionElement<LoaderLever.LeverSettingsEnum> {
public LoaderLever(Location location) {
super(location, LeverSettingsEnum.INTERACT, LeverSettingsEnum.NOOP, LeverSettingsEnum.values());
}
public enum LeverSettingsEnum implements LoaderSettingsEnum<Switch, LoaderLever, LeverSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderLever parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderLever parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer<Long> delay) {
blockData.setPowered(!blockData.isPowered());
parent.update(blockData);
}
},
POWER_OFF {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderLever parent, int power, long ticks) {
return new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_INACTIVE", player));
}
@Override
public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer<Long> delay) {
blockData.setPowered(false);
parent.update(blockData);
}
},
POWER_ON {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderLever parent, int power, long ticks) {
return new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_SWITCH", "LOADER_INTERACTION_ACTIVE", player));
}
@Override
public void execute(Location location, Switch blockData, LoaderLever parent, int power, long ticks, Consumer<Long> delay) {
blockData.setPowered(true);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(Material.LEVER, translateItemName("LOADER_BUTTON_LECTERN", player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.LEVER;
}
}
@@ -0,0 +1,165 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.AnaloguePowerable;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Powerable;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderMovement extends LoaderInteractionElement<LoaderMovement.MovementSettingsEnum> {
private String name;
private Material material;
private boolean analogue;
public LoaderMovement(Location location, String name, Material material) {
super(location, MovementSettingsEnum.NO_WAIT_FOR, MovementSettingsEnum.NOOP, MovementSettingsEnum.values());
this.name = name;
this.material = material;
this.analogue = location.getBlock().getBlockData() instanceof AnaloguePowerable;
}
public void setInitialTicks(long ticks) {
if (ticks < 1) ticks = 1;
extraTicks.set(currentShot, ticks);
}
public enum MovementSettingsEnum implements LoaderSettingsEnum<BlockData, LoaderMovement, MovementSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer<Long> delay) {
}
},
NO_WAIT_FOR {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) {
SWItem swItem = new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_WAIT_FOR", player));
swItem.getItemStack().setAmount((int) Math.min(ticks, 64));
return swItem;
}
@Override
public boolean hasPower(LoaderMovement parent) {
return parent.analogue;
}
@Override
public boolean hasTicks(LoaderMovement parent) {
return true;
}
@Override
public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer<Long> delay) {
if (blockData instanceof AnaloguePowerable) {
AnaloguePowerable analoguePowerable = (AnaloguePowerable) location.getBlock().getBlockData();
analoguePowerable.setPower(power);
parent.update(analoguePowerable);
} else if (blockData instanceof Powerable) {
Powerable powerable = (Powerable) location.getBlock().getBlockData();
if (ticks < 0) {
powerable.setPowered(power > 0);
} else {
powerable.setPowered(true);
}
parent.update(powerable);
}
BauSystem.runTaskLater(BauSystem.getInstance(), () -> {
if (blockData instanceof AnaloguePowerable) {
AnaloguePowerable analoguePowerable = (AnaloguePowerable) blockData;
analoguePowerable.setPower(0);
parent.update(analoguePowerable);
} else {
Powerable powerable = (Powerable) blockData;
powerable.setPowered(false);
parent.update(powerable);
}
}, ticks);
}
},
WAIT_FOR {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderMovement parent, int power, long ticks) {
SWItem swItem = new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_NO_WAIT_FOR", player));
swItem.getItemStack().setAmount((int) Math.min(ticks, 64));
return swItem;
}
@Override
public boolean hasPower(LoaderMovement parent) {
return parent.analogue;
}
@Override
public boolean hasTicks(LoaderMovement parent) {
return true;
}
@Override
public void execute(Location location, BlockData blockData, LoaderMovement parent, int power, long ticks, Consumer<Long> delay) {
NO_WAIT_FOR.execute(location, blockData, parent, power, ticks, delay);
delay.accept(ticks);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(material, translateItemName(name, player));
}
@Override
public boolean checkBlockInWorld() {
if (material == Material.STRING && location.getBlock().getType() == Material.TRIPWIRE) return true;
return location.getBlock().getType() == material;
}
}
@@ -0,0 +1,87 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Instrument;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.type.NoteBlock;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderNoteBlock extends LoaderInteractionElement<LoaderNoteBlock.NoteBlockSettingsEnum> {
public LoaderNoteBlock(Location location) {
super(location, NoteBlockSettingsEnum.INTERACT, NoteBlockSettingsEnum.NOOP, NoteBlockSettingsEnum.values());
}
public enum NoteBlockSettingsEnum implements LoaderSettingsEnum<NoteBlock, LoaderNoteBlock, NoteBlockSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderNoteBlock parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, NoteBlock blockData, LoaderNoteBlock parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderNoteBlock parent, int power, long ticks) {
return new SWItem(Material.NOTE_BLOCK, translateItemName("LOADER_BUTTON_NOTEBLOCK", "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, NoteBlock blockData, LoaderNoteBlock parent, int power, long ticks, Consumer<Long> delay) {
if (blockData.getInstrument() == Instrument.BANJO) blockData.setInstrument(Instrument.BIT);
else blockData.setInstrument(Instrument.BANJO);
parent.update(blockData);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(Material.NOTE_BLOCK, translateItemName("LOADER_BUTTON_NOTEBLOCK", player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.NOTE_BLOCK;
}
}
@@ -0,0 +1,125 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.Openable;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderOpenable extends LoaderInteractionElement<LoaderOpenable.OpenableSettingsEnum> {
private String name;
private Material material;
public LoaderOpenable(Location location, String name, Material material) {
super(location, OpenableSettingsEnum.INTERACT, OpenableSettingsEnum.NOOP, OpenableSettingsEnum.values());
this.name = name;
this.material = material;
}
public enum OpenableSettingsEnum implements LoaderSettingsEnum<Openable, LoaderOpenable, OpenableSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName(parent.name, "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer<Long> delay) {
blockData.setOpen(!blockData.isOpen());
parent.update(blockData);
}
},
CLOSED {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) {
return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_CLOSED", player));
}
@Override
public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer<Long> delay) {
blockData.setOpen(false);
parent.update(blockData);
}
},
OPEN {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderOpenable parent, int power, long ticks) {
return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_OPEN", player));
}
@Override
public void execute(Location location, Openable blockData, LoaderOpenable parent, int power, long ticks, Consumer<Long> delay) {
blockData.setOpen(true);
parent.update(blockData);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(material, translateItemName(name, player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == material;
}
}
@@ -0,0 +1,169 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.type.Repeater;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderRepeater extends LoaderInteractionElement<LoaderRepeater.RepeaterSettingsEnum> {
public LoaderRepeater(Location location) {
super(location, RepeaterSettingsEnum.INTERACT, RepeaterSettingsEnum.NOOP, RepeaterSettingsEnum.values());
}
public enum RepeaterSettingsEnum implements LoaderSettingsEnum<Repeater, LoaderRepeater, RepeaterSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 1;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
}
},
INTERACT {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
return new SWItem(Material.STICK, translateItemName("LOADER_BUTTON_REPEATER", "LOADER_INTERACTION_INTERACT", player));
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
int repeaterDelay = blockData.getDelay();
repeaterDelay++;
if (repeaterDelay > 4) repeaterDelay = 1;
blockData.setDelay(repeaterDelay);
parent.update(blockData);
}
},
DELAY_1 {
@Override
public int getPos() {
return 4;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 1));
swItem.getItemStack().setAmount(1);
return swItem;
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
blockData.setDelay(1);
parent.update(blockData);
}
},
DELAY_2 {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 2));
swItem.getItemStack().setAmount(2);
return swItem;
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
blockData.setDelay(2);
parent.update(blockData);
}
},
DELAY_3 {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 3));
swItem.getItemStack().setAmount(3);
return swItem;
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
blockData.setDelay(3);
parent.update(blockData);
}
},
DELAY_4 {
@Override
public int getPos() {
return 7;
}
@Override
public SWItem menu(Player player, LoaderRepeater parent, int power, long ticks) {
SWItem swItem = new SWItem(Material.REPEATER, BauSystem.MESSAGE.parse("LOADER_SETTING_REPEATER", player, 4));
swItem.getItemStack().setAmount(4);
return swItem;
}
@Override
public void execute(Location location, Repeater blockData, LoaderRepeater parent, int power, long ticks, Consumer<Long> delay) {
blockData.setDelay(4);
parent.update(blockData);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(Material.REPEATER, translateItemName("LOADER_BUTTON_REPEATER", player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == Material.REPEATER;
}
}
@@ -0,0 +1,98 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.function.Consumer;
public class LoaderTNT extends LoaderInteractionElement<LoaderTNT.TNTSettingsEnum> {
public LoaderTNT(Location location) {
super(location, TNTSettingsEnum.PLACE, TNTSettingsEnum.NOOP, TNTSettingsEnum.values());
}
public enum TNTSettingsEnum implements LoaderSettingsEnum<BlockData, LoaderTNT, TNTSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderTNT parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName("LOADER_BUTTON_TNT", "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, BlockData blockData, LoaderTNT parent, int power, long ticks, Consumer<Long> delay) {
}
},
PLACE {
@Override
public int getPos() {
return 3;
}
@Override
public SWItem menu(Player player, LoaderTNT parent, int power, long ticks) {
return new SWItem(Material.TNT, translateItemName("LOADER_BUTTON_TNT", "LOADER_INTERACTION_PLACE", player));
}
@Override
public void execute(Location location, BlockData blockData, LoaderTNT parent, int power, long ticks, Consumer<Long> delay) {
location.getBlock().setType(Material.TNT);
}
}
}
@Override
public SWItem menu(Player player) {
SWItem item = new SWItem(Material.TNT, BauSystem.MESSAGE.parse("LOADER_SETTING_TNT_NAME", player));
item.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TNT_X", player, location.getBlockX()), BauSystem.MESSAGE.parse("LOADER_SETTING_TNT_Y", player, location.getBlockY()), BauSystem.MESSAGE.parse("LOADER_SETTING_TNT_Z", player, location.getBlockZ())));
return item;
}
@Override
public void execute(Consumer<Long> delay) {
Block block = location.getBlock();
if (block.getType() != Material.AIR && block.getType() != Material.WATER) {
delay.accept(1L);
return;
}
super.execute(delay);
}
@Override
public boolean checkBlockInWorld() {
return true;
}
}
@@ -0,0 +1,116 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.loader.elements.LoaderInteractionElement;
import de.steamwar.bausystem.features.loader.elements.LoaderSettingsEnum;
import de.steamwar.inventory.SWItem;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.data.Powerable;
import org.bukkit.entity.Player;
import java.util.function.Consumer;
public class LoaderTicks extends LoaderInteractionElement<LoaderTicks.TicksSettingsEnum> {
private String name;
private Material material;
private int ticks;
public LoaderTicks(Location location, String name, Material material, int ticks) {
super(location, TicksSettingsEnum.NO_WAIT_FOR, TicksSettingsEnum.NOOP, TicksSettingsEnum.values());
this.name = name;
this.material = material;
this.ticks = ticks;
}
public enum TicksSettingsEnum implements LoaderSettingsEnum<Powerable, LoaderTicks, TicksSettingsEnum> {
NOOP {
@Override
public int getPos() {
return 2;
}
@Override
public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) {
return new SWItem(Material.STRUCTURE_VOID, translateItemName(parent.name, "LOADER_INTERACTION_NOOP", player));
}
@Override
public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer<Long> delay) {
}
},
NO_WAIT_FOR {
@Override
public int getPos() {
return 5;
}
@Override
public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) {
return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_NO_WAIT_FOR", player, ticks));
}
@Override
public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer<Long> delay) {
Powerable powerable = (Powerable) location.getBlock().getBlockData();
powerable.setPowered(true);
parent.update(powerable);
BauSystem.runTaskLater(BauSystem.getInstance(), () -> {
powerable.setPowered(false);
parent.update(powerable);
}, parent.ticks);
}
},
WAIT_FOR {
@Override
public int getPos() {
return 6;
}
@Override
public SWItem menu(Player player, LoaderTicks parent, int power, long ticks) {
return new SWItem(parent.material, translateItemName(parent.name, "LOADER_INTERACTION_WAIT_FOR", player, ticks));
}
@Override
public void execute(Location location, Powerable blockData, LoaderTicks parent, int power, long ticks, Consumer<Long> delay) {
NO_WAIT_FOR.execute(location, blockData, parent, power, ticks, delay);
delay.accept((long) parent.ticks);
}
}
}
@Override
public SWItem menu(Player player) {
return new SWItem(material, translateItemName(name, player));
}
@Override
public boolean checkBlockInWorld() {
return location.getBlock().getType() == material;
}
}
@@ -0,0 +1,89 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
*/
package de.steamwar.bausystem.features.loader.elements.impl;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.loader.elements.LoaderElement;
import de.steamwar.inventory.SWAnvilInv;
import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Arrays;
import java.util.function.Consumer;
public class LoaderWait implements LoaderElement {
@Getter
@Setter
private long delay;
public LoaderWait(long delay) {
this.delay = delay;
}
@Override
public SWItem menu(Player player) {
SWItem swItem = new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("LOADER_SETTING_WAIT", player, delay));
swItem.getItemStack().setAmount((int) Math.max(Math.min(delay, 64), 1));
if (delay == 0) swItem.setEnchanted(true);
swItem.setLore(Arrays.asList(BauSystem.MESSAGE.parse("LOADER_GUI_CLICK_TO_EDIT", player)));
return swItem;
}
@Override
public void execute(Consumer<Long> wait) {
wait.accept(delay);
}
@Override
public void click(Player player, Runnable backAction) {
SWInventory swInventory = new SWInventory(player, 18, BauSystem.MESSAGE.parse("LOADER_GUI_WAIT_TITLE", player));
for (int i = 9; i < 18; i++) swInventory.setItem(i, new SWItem(Material.GRAY_STAINED_GLASS_PANE, "§7"));
swInventory.setItem(9, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("LOADER_GUI_WAIT_BACK", player)).getItemStack(), clickType -> backAction.run());
swInventory.setItem(3, new SWItem(SWItem.getDye(1), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_REMOVE_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> {
delay -= clickType.isShiftClick() ? 5 : 1;
if (delay < 0) delay = 0;
swInventory.setItem(4, menu(player));
});
swInventory.setItem(4, menu(player).getItemStack(), clickType -> {
SWAnvilInv swAnvilInv = new SWAnvilInv(player, BauSystem.MESSAGE.parse("LOADER_SETTING_WAIT_NAME", player), delay + "");
swAnvilInv.setCallback(s -> {
try {
delay = Long.parseLong(s);
if (delay < 0) delay = 0;
} catch (NumberFormatException ignored) {
}
click(player, backAction);
});
swAnvilInv.open();
});
swInventory.setItem(5, new SWItem(SWItem.getDye(10), BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE", player), Arrays.asList(BauSystem.MESSAGE.parse("LOADER_SETTING_TICKS_ADD_ONE_SHIFT", player)), false, clickType -> {}).getItemStack(), clickType -> {
delay += clickType.isShiftClick() ? 5 : 1;
swInventory.setItem(4, menu(player));
});
swInventory.open();
}
}

Some files were not shown because too many files have changed in this diff Show More