diff --git a/BauSystem/BauSystem_21/src/de/steamwar/bausystem/utils/TickManager21.java b/BauSystem/BauSystem_21/src/de/steamwar/bausystem/utils/TickManager21.java
index af3792f7..ad6ca6c2 100644
--- a/BauSystem/BauSystem_21/src/de/steamwar/bausystem/utils/TickManager21.java
+++ b/BauSystem/BauSystem_21/src/de/steamwar/bausystem/utils/TickManager21.java
@@ -100,7 +100,6 @@ public class TickManager21 implements TickManager {
manager.setFrozen(true);
bukkitTask.cancel();
}, 1, 1);
- manager.tick();
}
@Override
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/dev/CreateKitCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/dev/CreateKitCommand.java
new file mode 100644
index 00000000..8008dc25
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/dev/CreateKitCommand.java
@@ -0,0 +1,63 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2026 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.bausystem.features.dev;
+
+import de.steamwar.bausystem.BauSystem;
+import de.steamwar.command.SWCommand;
+import de.steamwar.linkage.Linked;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.io.IOException;
+
+@Linked
+public class CreateKitCommand extends SWCommand {
+
+ public CreateKitCommand() {
+ super("createkit");
+ if (!BauSystem.DEV_SERVER) unregister();
+ }
+
+ @Register
+ public void onCommand(Player player, String name) {
+ YamlConfiguration yaml = new YamlConfiguration();
+
+ yaml.set("Items", player.getInventory().getContents());
+ yaml.set("Armor", player.getInventory().getArmorContents());
+ yaml.set("Effects", player.getActivePotionEffects());
+ yaml.set("LeaderAllowed", true);
+ yaml.set("MemberAllowed", true);
+ yaml.set("EnterStage", 0);
+ yaml.set("TNT", true);
+
+ YamlConfiguration kits = new YamlConfiguration();
+
+ kits.set("Kits." + name, yaml);
+
+ try {
+ kits.save(new File("new.kits.yaml"));
+
+ player.sendMessage("Kit created!");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java
index 7222acab..91a9d650 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/region/FreezeListener.java
@@ -46,6 +46,16 @@ import org.bukkit.event.player.PlayerInteractEvent;
@Linked
public class FreezeListener implements Listener, ScoreboardElement {
+ @EventHandler
+ public void onBlockExplode(BlockExplodeEvent e) {
+ if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
+ e.setCancelled(true);
+ BlockState state = e.getBlock().getState();
+ Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
+ state.update(true, false);
+ }, 1L);
+ }
+
@EventHandler
public void onEntitySpawn(EntitySpawnEvent e) {
if (Region.getRegion(e.getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java
index adfec3a5..b6ad62a0 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java
@@ -150,11 +150,13 @@ public class SimulatorObserverGui extends SimulatorScrollGui {
Consumer setter = observerPhase::setTickOffset;
return new SWItem[] {
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
observer,
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java
index d7d54981..16f036b0 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java
@@ -32,6 +32,7 @@ import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.Arrays;
@@ -97,6 +98,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
//Tick Offset
int offset = observer.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(offset < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.setTickOffset(Math.min(max, offset + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -113,6 +115,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(19, offsetItem);
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -120,6 +123,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
//Order
int order = observer.getOrder();
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -138,6 +142,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(22, orderItem);
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java
index c31687f5..cd424170 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.Arrays;
@@ -67,6 +68,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
// Base Tick
int baseTicks = observer.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -81,6 +83,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
inventory.setItem(18, baseTick);
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
observer.changeBaseTicks(-baseTicks);
} else {
@@ -91,6 +94,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -102,12 +106,14 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(0, clickType.isShiftClick() ? 5 : 1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
@@ -119,12 +125,14 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(0, clickType.isShiftClick() ? -5 : -1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
@@ -136,6 +144,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
observer.move(0, 0, clickType.isShiftClick() ? -5 : -1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneGui.java
index 847ba882..fcaecd9a 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneGui.java
@@ -165,11 +165,13 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui setter = redstoneSubPhase.place ? redstoneSubPhase.phase::setTickOffset : redstoneSubPhase.phase::setLifetime;
return new SWItem[] {
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
redstone,
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstonePhaseSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstonePhaseSettingsGui.java
index 37825397..cf7726bd 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstonePhaseSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstonePhaseSettingsGui.java
@@ -31,6 +31,7 @@ import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.Arrays;
@@ -98,6 +99,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
//Tick Offset
int offset = redstone.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(offset < maxOffset ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setTickOffset(Math.min(maxOffset, offset + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -114,6 +116,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(19, offsetItem);
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -121,6 +124,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
//Lifetime
int lifetime = redstone.getLifetime();
inventory.setItem(11, new SWItem(SWItem.getDye(lifetime < maxLifetime ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setLifetime(Math.min(maxLifetime, lifetime + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -137,6 +141,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(20, lifetimeItem);
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setLifetime(Math.max(0, lifetime - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -144,6 +149,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
//Order
int order = redstone.getOrder();
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -162,6 +168,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(22, orderItem);
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneSettingsGui.java
index 23206e27..a2901797 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorRedstoneSettingsGui.java
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.Arrays;
@@ -66,6 +67,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
// Base Tick
int baseTicks = redstone.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -80,6 +82,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
inventory.setItem(18, baseTick);
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
redstone.changeBaseTicks(-baseTicks);
} else {
@@ -90,6 +93,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
//Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -101,12 +105,14 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
//Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(0, clickType.isShiftClick() ? 5 : 1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -118,12 +124,14 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(0, clickType.isShiftClick() ? -5 : -1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
//Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(0, 0, clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -135,6 +143,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
redstone.move(0, 0, clickType.isShiftClick() ? -5 : -1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java
index a089f806..08d3628d 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTGui.java
@@ -138,11 +138,13 @@ public class SimulatorTNTGui extends SimulatorScrollGui {
return new SWItem[]{
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tntSetting.setCount(tntSetting.getCount() + (clickType.isShiftClick() ? 5 : 1));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
tnt,
new SWItem(SWItem.getDye(tntSetting.getCount() > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tntSetting.setCount(Math.max(1, tntSetting.getCount() - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTPhaseSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTPhaseSettingsGui.java
index d1850fc9..e66449fb 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTPhaseSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTPhaseSettingsGui.java
@@ -31,6 +31,7 @@ import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.Arrays;
@@ -78,6 +79,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
//Count
int count = tnt.getCount();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setCount(count + (clickType.isShiftClick() ? 5 : 1));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -94,6 +96,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(18, countItem);
inventory.setItem(27, new SWItem(SWItem.getDye(count > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setCount(Math.max(1, count - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -101,6 +104,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
//Tick Offset
int offset = tnt.getTickOffset();
inventory.setItem(10, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setTickOffset(offset + (clickType.isShiftClick() ? 5 : 1));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -117,6 +121,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(19, offsetItem);
inventory.setItem(28, new SWItem(SWItem.getDye(offset > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setTickOffset(Math.max(0, offset - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -124,6 +129,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
//Lifetime
int lifetime = tnt.getLifetime();
inventory.setItem(11, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setLifetime(lifetime + (clickType.isShiftClick() ? 5 : 1));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -140,6 +146,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(20, lifetimeItem);
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setLifetime(Math.max(1, lifetime - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
@@ -147,6 +154,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
//Order
int order = tnt.getOrder();
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -165,30 +173,35 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
inventory.setItem(22, orderItem);
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
//Jump
SWItem jumpX = new SWItem(tnt.isXJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump X§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setXJump(!tnt.isXJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(33, jumpX);
SWItem jumpY = new SWItem(tnt.isYJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Y§8: " + (tnt.isYJump() ? "§aon" : "§coff"), clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setYJump(!tnt.isYJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(16, jumpY);
SWItem jumpZ = new SWItem(tnt.isZJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Z§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setZJump(!tnt.isZJump());
SimulatorWatcher.update(simulator);
});
inventory.setItem(35, jumpZ);
SWItem jumpAll = new SWItem(Material.TNT, "§7TNT §eJump §8: " + (tnt.hasJump() ? "§aon" : "§coff"), clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.setJump(!tnt.hasJump());
SimulatorWatcher.update(simulator);
});
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTSettingsGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTSettingsGui.java
index e835ba43..9640b066 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTSettingsGui.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorTNTSettingsGui.java
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
import de.steamwar.inventory.SWItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
import java.util.ArrayList;
import java.util.Arrays;
@@ -75,6 +76,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
// Base Tick
int baseTicks = tnt.getBaseTick();
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -89,6 +91,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
inventory.setItem(18, baseTick);
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
tnt.changeBaseTicks(-baseTicks);
} else {
@@ -136,6 +139,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
// Pos X
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(clickType.isShiftClick() ? 0.0625 : 1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -147,12 +151,14 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(clickType.isShiftClick() ? -0.0625 : -1, 0, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Y
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(0, clickType.isShiftClick() ? 0.0625 : 1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -164,12 +170,14 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(0, clickType.isShiftClick() ? -0.0625 : -1, 0);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
// Pos Z
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(0, 0, clickType.isShiftClick() ? 0.0625 : 1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
@@ -181,6 +189,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
}, this).open();
}));
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
+ if (clickType == ClickType.DOUBLE_CLICK) return;
tnt.move(0, 0, clickType.isShiftClick() ? -0.0625 : -1);
SimulatorWatcher.update(simulator);
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/BlockBoundingBox.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/BlockBoundingBox.java
index 223cdfe6..ee9d48f4 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/BlockBoundingBox.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/BlockBoundingBox.java
@@ -101,7 +101,7 @@ public class BlockBoundingBox {
addPixel(Material.END_STONE.createBlockData(), 0, 0, 0, 16, 16, 16, null);
addPixel(NMSWrapper.impl.pathMaterial().createBlockData(), 0, 0, 0, 16, 15, 16, createItem("LAUFBAU_BLOCK_GRASS_PATH", NMSWrapper.impl.pathMaterial()));
- addPixel(Material.SOUL_SAND.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
+ addPixel(Material.MUD.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
Cocoa cocoaNorth = (Cocoa) Material.COCOA.createBlockData();
cocoaNorth.setAge(2);
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java
index 9c568a56..42ed812d 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java
@@ -25,12 +25,14 @@ import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.WorldEditUtils;
import de.steamwar.command.SWCommand;
import de.steamwar.linkage.Linked;
+import de.steamwar.linkage.MinVersion;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@Linked
+@MinVersion(19)
public class LaufbauCommand extends SWCommand {
public LaufbauCommand() {
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java
index 3e1dff3e..05fdcda0 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/ViewFlag.java
@@ -135,7 +135,7 @@ public abstract class ViewFlag {
}
Location secoundLocation;
- if (previousVelocity.getX() >= previousVelocity.getZ()) {
+ if (Math.abs(previousVelocity.getX()) >= Math.abs(previousVelocity.getZ())) {
secoundLocation = previous.getLocation().clone().add(delta.getX(), delta.getY(), 0);
} else {
secoundLocation = previous.getLocation().clone().add(0, delta.getY(), delta.getZ());
@@ -198,6 +198,16 @@ public abstract class ViewFlag {
}
};
+ public static ViewFlag HIGHLIGHT = new ViewFlag(true, false, "highlight", "h") {
+ @Override
+ public void modify(REntityServer server, List entities) {
+ for (TraceEntity entity : entities) {
+ entity.setGlowing(true);
+ }
+ }
+
+ };
+
/**
* Name of the flag
*/
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/worldedit/SelectAdjacent.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/worldedit/SelectAdjacent.java
deleted file mode 100644
index 3f6ca8f2..00000000
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/worldedit/SelectAdjacent.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.bausystem.features.worldedit;
-
-import de.steamwar.bausystem.BauSystem;
-import de.steamwar.bausystem.region.Point;
-import de.steamwar.bausystem.region.Region;
-import de.steamwar.bausystem.utils.FlatteningWrapper;
-import de.steamwar.core.SWPlayer;
-import de.steamwar.core.WorldEditRenderer;
-import de.steamwar.linkage.Linked;
-import de.steamwar.linkage.MinVersion;
-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.Listener;
-import org.bukkit.event.block.Action;
-import org.bukkit.event.player.PlayerInteractEvent;
-import org.bukkit.scheduler.BukkitTask;
-import org.bukkit.util.Vector;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.function.Predicate;
-
-@Linked
-@MinVersion(20)
-public class SelectAdjacent implements Listener {
-
- private Vector[] FACES = {
- new Vector(1, 0, 0),
- new Vector(-1, 0, 0),
- new Vector(0, 1, 0),
- new Vector(0, -1, 0),
- new Vector(0, 0, 1),
- new Vector(0, 0, -1),
-
- new Vector(1, 1, 0),
- new Vector(1, -1, 0),
- new Vector(1, 0, 1),
- new Vector(1, 0, -1),
- new Vector(-1, 1, 0),
- new Vector(-1, -1, 0),
- new Vector(-1, 0, 1),
- new Vector(-1, 0, -1),
- new Vector(0, 1, 1),
- new Vector(0, 1, -1),
- new Vector(0, -1, 1),
- new Vector(0, -1, -1),
- };
-
- @EventHandler
- public void onPlayerInteract(PlayerInteractEvent event) {
- if (!event.hasItem()) return;
- if (event.getItem().getType() != Material.WOODEN_AXE) return;
- if (!event.getPlayer().isSneaking()) return;
- if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
- Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
- Selector selector;
- if (material.isAir()) {
- selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
- } else {
- selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
- }
- SWPlayer.of(event.getPlayer()).setComponent(selector);
- }
-
- private class Selector implements SWPlayer.Component {
-
- private static final int MAX_BLOCKS = 500_000;
-
- private int minX;
- private int minY;
- private int minZ;
- private int maxX;
- private int maxY;
- private int maxZ;
-
- private BukkitTask bukkitTask;
- private Predicate predicate;
- private Set seen = new HashSet<>();
- private Set toCalc = new HashSet<>();
-
- private Region.Area area;
-
- public Selector(Block block, Player player, Predicate predicate) {
- this.predicate = predicate;
- toCalc.add(block.getLocation());
- minX = block.getX();
- minY = block.getY();
- minZ = block.getZ();
- maxX = block.getX();
- maxY = block.getY();
- maxZ = block.getZ();
-
- Region region = Region.getRegion(block.getLocation());
- area = Region.Area.EMPTY;
- if (region.getBuildArea().inRegion(block.getLocation(), true)) {
- area = region.getBuildArea();
- } else if (region.getTestblockArea().inRegion(block.getLocation(), true)) {
- area = region.getTestblockArea();
- } else if (region.getArea().inRegion(block.getLocation(), true)) {
- area = region.getArea();
- }
-
- bukkitTask = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
- run();
-
- long volume = (long)(maxX - minX + 1) * (long)(maxY - minY + 1) * (long)(maxZ - minZ + 1);
- player.sendTitle("", "§e" + volume + " §7Blocks", 0, 5, 0);
-
- Point minPoint = new Point(minX, minY, minZ);
- Point maxPoint = new Point(maxX, maxY, maxZ);
-
- FlatteningWrapper.impl.setSelection(player, minPoint, maxPoint);
- WorldEditRenderer.renderPlayer(player);
-
- // boolean finished = toCalc.stream().allMatch(location -> {
- // return location.getBlockX() >= minX && location.getBlockY() >= minY && location.getBlockZ() >= minZ &&
- // location.getBlockX() <= maxX && location.getBlockY() <= maxY && location.getBlockZ() <= maxZ;
- // });
-
- if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
- bukkitTask.cancel();
- player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
- SWPlayer.of(player).removeComponent(Selector.class);
- }
- }, 1, 1);
- }
-
- private void cancel() {
- bukkitTask.cancel();
- }
-
- private void run() {
- Set current = toCalc;
- toCalc = new HashSet<>();
-
- for (Location location : current) {
- Block block = location.getBlock();
- if (block.isEmpty() || block.isLiquid()) continue;
- if (!predicate.test(block.getType())) continue;
- seen.add(location);
- if (!area.inRegion(block.getLocation(), true)) continue;
-
- minX = Math.min(minX, location.getBlockX());
- maxX = Math.max(maxX, location.getBlockX());
- minY = Math.min(minY, location.getBlockY());
- maxY = Math.max(maxY, location.getBlockY());
- minZ = Math.min(minZ, location.getBlockZ());
- maxZ = Math.max(maxZ, location.getBlockZ());
-
- for (Vector face : FACES) {
- Block next = block.getRelative(face.getBlockX(), face.getBlockY(), face.getBlockZ());
- if (next.isEmpty() || next.isLiquid()) continue;
- if (!predicate.test(next.getType())) continue;
- Location loc = next.getLocation();
- if (seen.contains(loc)) continue;
- toCalc.add(loc);
- }
- }
- }
-
- @Override
- public void onUnmount(SWPlayer player) {
- cancel();
- }
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt
index 5db01dbf..5fb01f30 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt
@@ -90,7 +90,7 @@ class EventGroup(id: EntityID) : IntEntity(id) {
set(value) {
groupPointsPerDraw = value
}
- val dependents by lazy { EventRelation.getGroupRelations(this).toList() }
+ val dependents by lazy { EventRelation.getGroupRelations(this) }
val lastFight by lazy { Optional.ofNullable(fights.maxByOrNull { it.startTime }) }
fun getId() = id.value
diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt
index 0ca7be22..82c1d03f 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt
@@ -51,11 +51,11 @@ class EventRelation(id: EntityID) : IntEntity(id) {
@JvmStatic
fun getFightRelations(fight: EventFight) =
- useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) } }
+ useDb { find { (EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT) }.toList() }
@JvmStatic
fun getGroupRelations(group: EventGroup) =
- useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) } }
+ useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) }.toList() }
@JvmStatic
fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb {
diff --git a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java
index 48989139..906a9c87 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java
+++ b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java
@@ -52,6 +52,10 @@ public final class GameModeConfig {
private static final Map> byGameName;
private static final Map> bySchematicType;
+ public static Collection> getAll() {
+ return (Collection) byFileName.values();
+ }
+
public static GameModeConfig getByFileName(File file) {
return (GameModeConfig) byFileName.get(file.getName());
}
@@ -87,8 +91,24 @@ public final class GameModeConfig {
byFileName = new HashMap<>();
byGameName = new HashMap<>();
bySchematicType = new HashMap<>();
- SchematicType.values();
DEFAULTS = SQLWrapper.impl.loadGameModeConfig(null);
+ init();
+ }
+
+ public static void init() {
+ byFileName.clear();
+ byGameName.clear();
+ bySchematicType.clear();
+
+ File folder = SQLWrapper.impl.getSchemTypesFolder();
+ if (!folder.exists()) return;
+ if (!folder.isDirectory()) return;
+
+ for (File file : Objects.requireNonNull(folder.listFiles())) {
+ if (!file.getName().endsWith(".yml")) continue;
+ if (file.getName().endsWith(".kits.yml")) continue;
+ SQLWrapper.impl.loadGameModeConfig(file);
+ }
byFileName.values().forEach(gameModeConfig -> {
List subTypes = Collections.unmodifiableList(gameModeConfig.Schematic.SubTypesStrings.stream()
@@ -440,6 +460,13 @@ public final class GameModeConfig {
*/
public final boolean DisableSnowMelt;
+ /**
+ * Disable ice forming
+ *
+ * @implSpec {@code false} by default
+ */
+ public final boolean DisableIceForm;
+
/**
* Allow leaving the arena area as spectator
*
@@ -470,6 +497,7 @@ public final class GameModeConfig {
BorderFromSchematic = loader.getInt("BorderFromSchematic", 21);
GroundWalkable = loader.getBoolean("GroundWalkable", true);
DisableSnowMelt = loader.getBoolean("DisableSnowMelt", false);
+ DisableIceForm = loader.getBoolean("DisableIceForm", false);
Leaveable = loader.getBoolean("Leaveable", false);
AllowMissiles = loader.getBoolean("AllowMissiles", !EnterStages.isEmpty());
NoFloor = loader.getBoolean("NoFloor", false);
@@ -663,9 +691,9 @@ public final class GameModeConfig {
loaded = loader.canLoad();
Size = new SizeConfig(loader.with("Size"));
Inset = new InsetConfig(loader.with("Inset"));
- Type = loader.getSchematicType("Type", "Normal");
+ Type = null;
SubTypesStrings = loader.getStringList("SubTypes");
- SubTypes = loader.getSchematicTypeList("SubTypes");
+ SubTypes = new ArrayList<>();
Shortcut = loader.getString("Shortcut", "");
Material = loader.getMaterial("Material", "STONE_BUTTON");
ManualCheck = loader.getBoolean("ManualCheck", true);
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
index 69552ac0..386966a8 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
@@ -88,8 +88,6 @@ class NodeData(id: EntityID): CompositeEntity(id) {
schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it }
}
- fun schemData() = schemData(true)
-
override fun delete() = useDb { super.delete() }
enum class SchematicFormat(val fileEnding: String) {
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt
index cf6d951e..febe5808 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt
@@ -94,7 +94,7 @@ class NodeMember(id: EntityID) : CompositeEntity(id) {
{ Optional.ofNullable(it?.value) })
private set
- fun setParentId(id: Int?) {
+ fun setParentId(id: Int?) = useDb {
parent = Optional.ofNullable(id)
}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/SQLWrapper.java b/CommonCore/SQL/src/de/steamwar/sql/SQLWrapper.java
index 47331406..f049f680 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/SQLWrapper.java
+++ b/CommonCore/SQL/src/de/steamwar/sql/SQLWrapper.java
@@ -36,8 +36,5 @@ public interface SQLWrapper {
return Collections.emptyList();
}
- default void processSchematicType(GameModeConfig, String> gameModeConfig) {
- }
-
void additionalExceptionMetadata(StringBuilder builder);
}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
index d27c2890..12dce565 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
@@ -146,7 +146,91 @@ class SchematicNode(id: EntityID) : IntEntity(id) {
@JvmStatic
fun parentsOfNode(user: SteamwarUser, id: Int) = fromSql(
- "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.Config FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId",
+ """
+ WITH RECURSIVE
+ ESN_R AS (
+ SELECT SchematicNode.NodeId AS NodeId,
+ NM.UserId AS EffectiveOwner,
+ NM.ParentId AS ParentNode
+ FROM SchematicNode
+ INNER JOIN NodeMember NM ON NM.NodeId = SchematicNode.NodeId
+ UNION ALL
+ SELECT S.NodeId AS NodeId,
+ ESN_R.EffectiveOwner AS EffectiveOwner,
+ S.ParentNode AS ParentNode
+ FROM SchematicNode S
+ INNER JOIN ESN_R ON S.ParentNode = ESN_R.NodeId
+ ),
+ ESN_R2 AS (
+ SELECT SchematicNode.NodeId AS NodeId,
+ NM.UserId AS UserId,
+ SchematicNode.NodeOwner AS EffectiveOwner,
+ SchematicNode.ParentNode AS ParentNode
+ FROM SchematicNode
+ INNER JOIN NodeMember NM ON NM.NodeId = SchematicNode.NodeId
+ UNION ALL
+ SELECT S.NodeId AS NodeId,
+ ESN_R2.EffectiveOwner AS EffectiveOwner,
+ ESN_R2.UserId AS UserId,
+ S.ParentNode AS ParentNode
+ FROM SchematicNode S
+ INNER JOIN ESN_R2 ON S.ParentNode = ESN_R2.NodeId
+ WHERE S.NodeOwner <> ESN_R2.EffectiveOwner
+ ),
+ ESN_R3 AS (
+ SELECT SchematicNode.NodeId AS NodeId,
+ SchematicNode.NodeOwner AS NodeOwner,
+ SchematicNode.NodeOwner AS EffectiveOwner,
+ SchematicNode.ParentNode AS ParentNode
+ FROM SchematicNode
+ UNION ALL
+ SELECT S.NodeId AS NodeId,
+ S.NodeOwner AS NodeOwner,
+ ESN_R3.EffectiveOwner AS EffectiveOwner,
+ S.ParentNode AS ParentNode
+ FROM SchematicNode S
+ INNER JOIN ESN_R3 ON S.ParentNode = ESN_R3.NodeId
+ WHERE ESN_R3.NodeOwner <> S.NodeOwner
+ ),
+ ResolvedNodes AS (
+ SELECT ESN_R.NodeId AS NodeId,
+ ESN_R.EffectiveOwner AS EffectiveOwner,
+ ESN_R.ParentNode AS ParentNode
+ FROM ESN_R
+ UNION
+ SELECT ESN_R2.NodeId AS NodeId,
+ ESN_R2.UserId AS EffectiveOwner,
+ ESN_R2.ParentNode AS ParentNode
+ FROM ESN_R2
+ INNER JOIN SchematicNode SN2 ON ESN_R2.NodeId = SN2.NodeId
+ WHERE ESN_R2.ParentNode IS NOT NULL
+ AND SN2.NodeOwner <> ESN_R2.EffectiveOwner
+ UNION
+ SELECT ESN_R3.NodeId AS NodeId,
+ ESN_R3.EffectiveOwner AS EffectiveOwner,
+ ESN_R3.ParentNode AS ParentNode
+ FROM ESN_R3
+ WHERE ESN_R3.NodeOwner <> ESN_R3.EffectiveOwner
+ UNION
+ SELECT SchematicNode.NodeId AS NodeId,
+ SchematicNode.NodeOwner AS EffectiveOwner,
+ SchematicNode.ParentNode AS ParentNode
+ FROM SchematicNode
+ ),
+ R AS (
+ SELECT NodeId, ParentNode
+ FROM ResolvedNodes
+ WHERE NodeId = ?
+ UNION
+ SELECT E.NodeId, E.ParentNode
+ FROM R
+ INNER JOIN ResolvedNodes E ON R.ParentNode = E.NodeId
+ WHERE E.EffectiveOwner = ?
+ )
+ SELECT SN.NodeId, SN.NodeOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.Config
+ FROM R
+ INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId
+ """.trimIndent(),
listOf(
IntegerColumnType() to id,
IntegerColumnType() to user.getId()
@@ -284,7 +368,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) {
val list = mutableListOf()
if (s.contains("/")) {
val preTab = s.take(s.lastIndexOf("/") + 1)
- val pa = getNodeFromPath(user, preTab) ?: return emptyList()
+ val pa = getNodeFromPath(user, preTab) ?: return mutableListOf()
val nodes: List = list(user, pa.getId())
val br = pa.generateBreadcrumbs(user)
nodes.forEach(Consumer { node: SchematicNode? -> list.add((if (sws) "/" else "") + br + node!!.name + (if (node.isDir()) "/" else "")) })
diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt
index b7f7d5be..d4abc36c 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicType.kt
@@ -19,11 +19,7 @@
package de.steamwar.sql
-import java.io.File
import java.util.*
-import java.util.Locale
-import java.util.Locale.getDefault
-import java.util.stream.Collectors
data class SchematicType(
val name: String,
@@ -47,58 +43,65 @@ data class SchematicType(
@JvmField
val Normal = SchematicType("Normal", "", Type.NORMAL, null, "STONE_BUTTON", false)
- private val types: List
- private val fromDB: Map?
+ private val types: MutableList = mutableListOf()
+ private val fromDB: MutableMap = mutableMapOf()
init {
- val tmpTypes = mutableListOf()
- val tmpFromDB = mutableMapOf()
-
- tmpTypes.add(Normal)
- tmpFromDB[Normal.toDB()] = Normal
-
- val folder = SQLWrapper.impl.schemTypesFolder
- if (folder.exists()) {
- for (configFile in Arrays.stream(folder.listFiles { _, name ->
- name.endsWith(
- ".yml"
- ) && !name.endsWith(".kits.yml")
- }).sorted().collect(Collectors.toList())) {
- val gameModeConfig = SQLWrapper.impl.loadGameModeConfig(configFile)
- if (gameModeConfig.Schematic.Type == null) continue
- if (tmpFromDB.containsKey(gameModeConfig.Schematic.Type.toDB())) continue
- val current = gameModeConfig.Schematic.Type
- if (gameModeConfig.CheckQuestions.isNotEmpty()) {
- val checkType = current.checkType
- tmpTypes.add(checkType!!)
- tmpFromDB[checkType.toDB()] = checkType
- }
- tmpTypes.add(current)
- tmpFromDB[current.toDB()] = current
- SQLWrapper.impl.processSchematicType(gameModeConfig)
- }
- }
-
- types = tmpTypes.toList()
- fromDB = tmpFromDB.toMap()
+ GameModeConfig.init()
+ init()
}
@JvmStatic
- fun values() = types
+ fun init() {
+ types.clear()
+ fromDB.clear()
+
+ types.add(Normal)
+ fromDB[Normal.toDB()] = Normal
+
+ for (gameModeConfig in GameModeConfig.getAll()) {
+ val type = gameModeConfig.Schematic.Type
+ ?: continue
+ if (fromDB.containsKey(type.toDB())) continue
+
+ types.add(type)
+ fromDB[type.toDB()] = type
+ if (gameModeConfig.CheckQuestions.isNotEmpty() && type.checkType != null) {
+ types.add(type.checkType)
+ fromDB[type.checkType.toDB()] = type.checkType
+ }
+ }
+ }
@JvmStatic
- fun fromDB(value: String) = fromDB?.let { it[value.lowercase()] }
+ fun values() =
+ types
+
+ @JvmStatic
+ fun fromDB(value: String) =
+ fromDB[value.lowercase()]
}
- fun name() = name
- fun toDB() = name.lowercase()
+ fun name() =
+ name
- fun check() = type == Type.CHECK_TYPE
- fun fightType() = type == Type.FIGHT_TYPE
- fun writeable() = type == Type.NORMAL
+ fun toDB() =
+ name.lowercase()
- fun checkType() = if (manualCheck) checkType else this
- fun isAssignable() = type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck
+ fun check() =
+ type == Type.CHECK_TYPE
+
+ fun fightType() =
+ type == Type.FIGHT_TYPE
+
+ fun writeable() =
+ type == Type.NORMAL
+
+ fun checkType() =
+ if (manualCheck) checkType else this
+
+ fun isAssignable() =
+ type == Type.NORMAL || (type == Type.FIGHT_TYPE && checkType != null) || !manualCheck
enum class Type {
NORMAL,
diff --git a/CommonCore/SQL/src/de/steamwar/sql/Team.kt b/CommonCore/SQL/src/de/steamwar/sql/Team.kt
index 8000fbb0..66614ad2 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/Team.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/Team.kt
@@ -32,8 +32,6 @@ object TeamTable : IntIdTable("Team", "TeamID") {
val color = char("TeamColor", 1).default("8")
val name = varchar("TeamName", 16)
val deleted = bool("TeamDeleted").default(false)
- val address = text("Address").nullable()
- val port = ushort("Port").default(25565u)
}
class Team(id: EntityID) : IntEntity(id) {
diff --git a/FightSystem/FightSystem_21/build.gradle.kts b/FightSystem/FightSystem_21/build.gradle.kts
index a8c67f6f..6de2b25a 100644
--- a/FightSystem/FightSystem_21/build.gradle.kts
+++ b/FightSystem/FightSystem_21/build.gradle.kts
@@ -42,4 +42,5 @@ dependencies {
compileOnly(libs.fastutil)
compileOnly(libs.authlib)
+ compileOnly(project(":FightSystem:FightSystem_14"))
}
diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/listener/WindchargeStopper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/listener/WindchargeStopper21.java
new file mode 100644
index 00000000..892312f6
--- /dev/null
+++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/listener/WindchargeStopper21.java
@@ -0,0 +1,51 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.listener;
+
+import de.steamwar.fightsystem.Config;
+import de.steamwar.fightsystem.states.FightState;
+import de.steamwar.fightsystem.states.StateDependentTask;
+import net.minecraft.world.entity.projectile.windcharge.WindCharge;
+import org.bukkit.Location;
+
+public class WindchargeStopper21 implements WindchargeStopper.IWindchargeStopper {
+
+ public WindchargeStopper21() {
+ new StateDependentTask(true, FightState.Running, this::run, 1, 1);
+ }
+
+ private static final int middleLine = Config.SpecSpawn.getBlockZ();
+
+ private static final Class> windChargeClass = WindCharge.class;
+
+ private void run() {
+ Recording.iterateOverEntities(windChargeClass::isInstance, entity -> {
+ Location location = entity.getLocation();
+ Location prevLocation = location.clone().subtract(entity.getVelocity());
+
+ boolean passedMiddle = location.getBlockZ() > middleLine && prevLocation.getBlockZ() > middleLine ||
+ location.getBlockZ() < middleLine && prevLocation.getBlockZ() < middleLine;
+
+ if(!passedMiddle) {
+ entity.remove();
+ }
+ });
+ }
+}
diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/FlatteningWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/FlatteningWrapper21.java
new file mode 100644
index 00000000..ad535a6c
--- /dev/null
+++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/FlatteningWrapper21.java
@@ -0,0 +1,29 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.utils;
+
+import org.bukkit.inventory.ItemStack;
+
+public class FlatteningWrapper21 extends FlatteningWrapper14 {
+ @Override
+ public boolean hasAttributeModifier(ItemStack stack) {
+ return stack.hasItemMeta() && stack.getItemMeta() != null && stack.getItemMeta().hasAttributeModifiers();
+ }
+}
diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java
index ea8b2d7f..8e38938e 100644
--- a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java
+++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java
@@ -38,6 +38,27 @@ public class ReflectionWrapper21 implements ReflectionWrapper {
FORBIDDEN_TYPES.add(DataComponentTypes.BLOCKS_ATTACKS);
FORBIDDEN_TYPES.add(DataComponentTypes.BUNDLE_CONTENTS);
FORBIDDEN_TYPES.add(DataComponentTypes.CUSTOM_MODEL_DATA);
+
+ FORBIDDEN_TYPES.add(DataComponentTypes.ATTRIBUTE_MODIFIERS);
+ FORBIDDEN_TYPES.add(DataComponentTypes.TOOL);
+ FORBIDDEN_TYPES.add(DataComponentTypes.WEAPON);
+ FORBIDDEN_TYPES.add(DataComponentTypes.FOOD);
+ FORBIDDEN_TYPES.add(DataComponentTypes.CONSUMABLE);
+ FORBIDDEN_TYPES.add(DataComponentTypes.POTION_CONTENTS);
+ FORBIDDEN_TYPES.add(DataComponentTypes.STORED_ENCHANTMENTS);
+ FORBIDDEN_TYPES.add(DataComponentTypes.CAN_BREAK);
+ FORBIDDEN_TYPES.add(DataComponentTypes.CAN_PLACE_ON);
+ FORBIDDEN_TYPES.add(DataComponentTypes.MAX_DAMAGE);
+ FORBIDDEN_TYPES.add(DataComponentTypes.USE_REMAINDER);
+ FORBIDDEN_TYPES.add(DataComponentTypes.USE_COOLDOWN);
+ FORBIDDEN_TYPES.add(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS);
+ FORBIDDEN_TYPES.add(DataComponentTypes.CHARGED_PROJECTILES);
+ FORBIDDEN_TYPES.add(DataComponentTypes.INTANGIBLE_PROJECTILE);
+ FORBIDDEN_TYPES.add(DataComponentTypes.FIREWORKS);
+ FORBIDDEN_TYPES.add(DataComponentTypes.FIREWORK_EXPLOSION);
+ FORBIDDEN_TYPES.add(DataComponentTypes.EQUIPPABLE);
+ FORBIDDEN_TYPES.add(DataComponentTypes.REPAIR_COST);
+ FORBIDDEN_TYPES.add(DataComponentTypes.ENCHANTABLE);
}
@Override
diff --git a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/listener/WindchargeStopper8.java b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/listener/WindchargeStopper8.java
new file mode 100644
index 00000000..74f769c5
--- /dev/null
+++ b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/listener/WindchargeStopper8.java
@@ -0,0 +1,23 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.listener;
+
+public class WindchargeStopper8 implements WindchargeStopper.IWindchargeStopper {
+}
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
index 15e2aeea..011d36f6 100644
--- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java
@@ -33,9 +33,6 @@ import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.fightsystem.utils.*;
-import de.steamwar.fightsystem.winconditions.Wincondition;
-import de.steamwar.fightsystem.winconditions.WinconditionComparisonTimeout;
-import de.steamwar.fightsystem.winconditions.Winconditions;
import de.steamwar.linkage.AbstractLinker;
import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message;
@@ -43,6 +40,7 @@ import de.steamwar.sql.NodeData;
import de.steamwar.sql.SchematicNode;
import lombok.Getter;
import org.bukkit.Bukkit;
+import org.bukkit.GameRule;
import org.bukkit.plugin.java.JavaPlugin;
public class FightSystem extends JavaPlugin {
@@ -100,6 +98,13 @@ public class FightSystem extends JavaPlugin {
new StateDependentListener(ArenaMode.All, FightState.All, BountifulWrapper.impl.newDenyArrowPickupListener());
new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f));
new OneShotStateDependent(ArenaMode.Test, FightState.All, WorldEditRendererCUIEditor::new);
+ if (Core.getVersion() >= 19) {
+ try {
+ Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode));
+ } catch (Exception e) {
+ // Ignore if failed!
+ }
+ }
techHider = new TechHiderWrapper();
hullHider = new HullHider();
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/BlockFormListener.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/BlockFormListener.java
new file mode 100644
index 00000000..29c6be82
--- /dev/null
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/BlockFormListener.java
@@ -0,0 +1,44 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2026 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.listener;
+
+import de.steamwar.fightsystem.Config;
+import de.steamwar.fightsystem.states.FightState;
+import de.steamwar.fightsystem.states.StateDependentListener;
+import de.steamwar.linkage.Linked;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockFormEvent;
+
+@Linked
+public class BlockFormListener implements Listener {
+
+ public BlockFormListener() {
+ new StateDependentListener(Config.GameModeConfig.Arena.DisableIceForm, FightState.All, this);
+ }
+
+ @EventHandler
+ public void onBlockForm(BlockFormEvent event) {
+ if (Config.ArenaRegion.inRegion(event.getBlock()) && event.getNewState().getType() == Material.ICE) {
+ event.setCancelled(true);
+ }
+ }
+}
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java
index 422e2a94..e0b446d5 100644
--- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/PersonalKitCreator.java
@@ -35,10 +35,7 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryAction;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.event.inventory.InventoryCloseEvent;
-import org.bukkit.event.inventory.InventoryOpenEvent;
+import org.bukkit.event.inventory.*;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
@@ -81,25 +78,8 @@ public class PersonalKitCreator implements Listener {
if(!openKitCreators.containsKey(e.getWhoClicked()))
return;
- Player player = (Player) e.getWhoClicked();
- //Deny bad items
if(Kit.isBadItem(e.getCursor()))
e.setCancelled(true);
-
- /* Should the inventory reset? */
- if(e.getAction() != InventoryAction.PLACE_ALL)
- return;
-
- ItemStack[] items = e.getWhoClicked().getInventory().getContents();
- for(int i = 0; i < items.length; i++){
- ItemStack stack = items[i];
- if(stack != null && i != e.getSlot())
- return;
- }
-
- FightPlayer fightPlayer = Fight.getFightPlayer(player);
- assert fightPlayer != null;
- Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> fightPlayer.getKit().loadToPlayer(player), 1);
}
@EventHandler
@@ -117,7 +97,10 @@ public class PersonalKitCreator implements Listener {
if(backup == null)
return;
- backup.close();
+ InventoryType type = e.getInventory().getType();
+ if(type != InventoryType.PLAYER && type != InventoryType.CREATIVE) {
+ backup.close();
+ }
}
@EventHandler
@@ -126,7 +109,7 @@ public class PersonalKitCreator implements Listener {
if(backup == null)
return;
- backup.close();
+ Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), backup::close, 1);
}
@EventHandler
@@ -151,9 +134,11 @@ public class PersonalKitCreator implements Listener {
}
private void close(){
- openKitCreators.remove(player);
Kit kit1 = new Kit(kit.getName(), player);
kit1.removeBadItems();
+
+
+ openKitCreators.remove(player);
kit1.toPersonalKit(kit);
backup.loadToPlayer(player);
player.setGameMode(GameMode.SURVIVAL);
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java
new file mode 100644
index 00000000..0218f58d
--- /dev/null
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java
@@ -0,0 +1,35 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.fightsystem.listener;
+
+import de.steamwar.core.VersionDependent;
+import de.steamwar.fightsystem.FightSystem;
+import de.steamwar.linkage.Linked;
+
+@Linked
+public class WindchargeStopper {
+
+ static {
+ VersionDependent.getVersionImpl(FightSystem.getPlugin());
+ }
+
+ public interface IWindchargeStopper {
+ }
+}
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java
index cbb79a5e..2e2aa21c 100644
--- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/PacketProcessor.java
@@ -36,7 +36,6 @@ import de.steamwar.fightsystem.fight.FreezeWorld;
import de.steamwar.fightsystem.listener.FightScoreboard;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.utils.*;
-import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.Team;
@@ -520,12 +519,12 @@ public class PacketProcessor implements Listener {
private void pasteEmbeddedSchem(FightTeam team) throws IOException {
int schemId = source.readInt();
- Clipboard clipboard = SchematicData.clipboardFromStream(new FilterInputStream(source) {
+ Clipboard clipboard = WorldEditWrapper.impl.getClipboard(new FilterInputStream(source) {
@Override
public void close() {
// FAWE 1.12 calls close...
}
- }, WorldEditWrapper.impl.getNativeFormat());
+ });
execSync(() -> team.pasteSchem(schemId, clipboard));
}
diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java
index f4267b49..25f67457 100644
--- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java
+++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/record/Recorder.java
@@ -283,7 +283,7 @@ public interface Recorder {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
try{
- copy(NodeData.getLatest(SchematicNode.getSchematicNode(schemId)).schemData(), buffer);
+ copy(NodeData.getLatest(SchematicNode.getSchematicNode(schemId)).schemData(true), buffer);
}catch (EOFException e) {
Bukkit.getLogger().log(Level.INFO, "EOFException ignored");
} catch (IOException e) {
diff --git a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java
index d6189931..8ed1bd4c 100644
--- a/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java
+++ b/SchematicSystem/SchematicSystem_15/src/de/steamwar/schematicsystem/autocheck/AutoChecker15.java
@@ -53,7 +53,7 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker {
checkInventory(result, block, material, new BlockPos(x, y, z));
}
- if(x == 0 || x == max.getBlockX() - 1 || y == max.getBlockY() - 1 || z == 0 || z == max.getBlockZ() - 1) {
+ if(x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) {
result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z));
}
}
diff --git a/SchematicSystem/SchematicSystem_21/build.gradle.kts b/SchematicSystem/SchematicSystem_21/build.gradle.kts
new file mode 100644
index 00000000..2654c5b7
--- /dev/null
+++ b/SchematicSystem/SchematicSystem_21/build.gradle.kts
@@ -0,0 +1,37 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 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 .
+ */
+
+plugins {
+ steamwar.java
+}
+
+dependencies {
+ compileOnly(project(":SpigotCore", "default"))
+ compileOnly(project(":SchematicSystem:SchematicSystem_Core", "default"))
+
+ compileOnly(libs.paperapi21) {
+ attributes {
+ // Very Hacky, but it works
+ attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
+ }
+ }
+
+ compileOnly(libs.nms21)
+ compileOnly(libs.fawe21)
+}
diff --git a/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java
new file mode 100644
index 00000000..ad8acd39
--- /dev/null
+++ b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoChecker21.java
@@ -0,0 +1,137 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2026 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.schematicsystem.autocheck;
+
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.extent.clipboard.Clipboard;
+import com.sk89q.worldedit.math.BlockVector3;
+import com.sk89q.worldedit.world.block.BaseBlock;
+import de.steamwar.core.Core;
+import de.steamwar.sql.GameModeConfig;
+import org.bukkit.Material;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class AutoChecker21 implements AutoChecker.IAutoChecker {
+
+ public AutoChecker.BlockScanResult scan(Clipboard clipboard, GameModeConfig type) {
+ AutoChecker.BlockScanResult result = new AutoChecker.BlockScanResult();
+ BlockVector3 min = clipboard.getMinimumPoint();
+ BlockVector3 max = clipboard.getMaximumPoint();
+ for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
+ for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
+ for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
+ final BaseBlock block = clipboard.getFullBlock(BlockVector3.at(x, y, z));
+ final Material material = Material.matchMaterial(block.getBlockType().getId());
+ if (material == null) {
+ continue;
+ }
+
+ result.getBlockCounts().merge(material, 1, Integer::sum);
+
+ if (AutoCheckerItems.impl.getInventoryMaterials().contains(material)) {
+ checkInventory(result, block, material, new BlockPos(x, y, z), type);
+ }
+
+ if (x == min.getBlockX() || x == max.getBlockX() || y == max.getBlockY() || z == min.getBlockZ() || z == max.getBlockZ()) {
+ result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z));
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private static final Map> itemsInInv = new EnumMap<>(Material.class);
+
+ static {
+ itemsInInv.put(Material.BUCKET, EnumSet.of(Material.DISPENSER));
+ itemsInInv.put(Material.TNT, EnumSet.of(Material.CHEST, Material.BARREL, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX,
+ Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX,
+ Material.LIGHT_GRAY_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX,
+ Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX));
+ itemsInInv.put(Material.FIRE_CHARGE, EnumSet.of(Material.DISPENSER));
+ itemsInInv.put(Material.ARROW, EnumSet.of(Material.DISPENSER));
+ AutoCheckerItems.impl.getAllowedMaterialsInInventory().forEach(material -> itemsInInv.put(material, AutoCheckerItems.impl.getInventoryMaterials()));
+ }
+
+ private void checkInventory(AutoChecker.BlockScanResult result, BaseBlock block, Material material, BlockPos pos, GameModeConfig type) {
+ CompoundTag nbt = block.getNbtData();
+ if (nbt == null) {
+ result.getDefunctNbt().add(pos);
+ return;
+ }
+
+
+ if (material == Material.JUKEBOX && nbt.getValue().containsKey("RecordItem")) {
+ result.getRecords().add(pos);
+ return;
+ }
+
+ List items = nbt.getList("Items", CompoundTag.class);
+ if (items.isEmpty())
+ return; // Leeres Inventar
+
+ int counter = 0;
+ int windChargeCount = 0;
+ for (CompoundTag item : items) {
+ if (!item.containsKey("id")) {
+ result.getDefunctNbt().add(pos);
+ continue;
+ }
+
+ Material itemType = Material.matchMaterial(item.getString("id"));
+ if (itemType == null) // Leere Slots
+ continue;
+
+ if(type.Schematic.Type.getName().equals("wargearseason26") && material == Material.DISPENSER && itemType == Material.WIND_CHARGE) {
+ windChargeCount += item.getInt("count");
+ }
+ else if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) {
+ result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
+ } else if (material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) {
+ counter += Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
+ }
+ if (item.containsKey("tag")) {
+ result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
+ }
+ }
+ result.getDispenserItems().put(pos, counter);
+ result.getWindChargeCount().put(pos, windChargeCount);
+ }
+
+ @Override
+ public AutoCheckerResult check(Clipboard clipboard, GameModeConfig type) {
+ return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
+ .depth(clipboard.getDimensions().getBlockZ()).blockScanResult(scan(clipboard, type))
+ .entities(clipboard.getEntities().stream().map(Entity::getLocation)
+ .map(blockVector3 -> new BlockPos(blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ()))
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ @Override
+ public AutoCheckerResult sizeCheck(Clipboard clipboard, GameModeConfig type) {
+ return AutoCheckerResult.builder().type(type).height(clipboard.getDimensions().getBlockY()).width(clipboard.getDimensions().getBlockX())
+ .depth(clipboard.getDimensions().getBlockZ()).build();
+ }
+}
diff --git a/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java
new file mode 100644
index 00000000..af50a3fa
--- /dev/null
+++ b/SchematicSystem/SchematicSystem_21/src/de/steamwar/schematicsystem/autocheck/AutoCheckerItems21.java
@@ -0,0 +1,49 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify it under the terms of the
+ * GNU Affero General Public License as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License along with this program.
+ * If not, see .
+ */
+
+package de.steamwar.schematicsystem.autocheck;
+
+import org.bukkit.Material;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public class AutoCheckerItems21 implements AutoCheckerItems {
+
+ private static final Set INVENTORY = EnumSet.of(Material.BARREL, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CAMPFIRE,
+ Material.CHEST, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.JUKEBOX, Material.SHULKER_BOX,
+ Material.WHITE_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX,
+ Material.LIME_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX, Material.CYAN_SHULKER_BOX,
+ Material.PURPLE_SHULKER_BOX, Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.RED_SHULKER_BOX,
+ Material.BLACK_SHULKER_BOX, Material.SMOKER, Material.TRAPPED_CHEST);
+
+ private static final Set FLOWERS = EnumSet.of(Material.CORNFLOWER, Material.POPPY, Material.FERN, Material.DANDELION, Material.BLUE_ORCHID,
+ Material.ALLIUM, Material.AZURE_BLUET, Material.RED_TULIP, Material.ORANGE_TULIP, Material.WHITE_TULIP, Material.PINK_TULIP, Material.OXEYE_DAISY,
+ Material.LILY_OF_THE_VALLEY, Material.WITHER_ROSE, Material.SUNFLOWER, Material.DIAMOND_HORSE_ARMOR, Material.IRON_HORSE_ARMOR,
+ Material.GOLDEN_HORSE_ARMOR, Material.LEATHER_HORSE_ARMOR, Material.HONEY_BOTTLE, Material.LILAC, Material.ROSE_BUSH, Material.PEONY,
+ Material.TALL_GRASS, Material.LARGE_FERN);
+
+ @Override
+ public Set getInventoryMaterials() {
+ return INVENTORY;
+ }
+
+ @Override
+ public Set getAllowedMaterialsInInventory() {
+ return FLOWERS;
+ }
+}
diff --git a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
index 0ff05daa..da86e45c 100644
--- a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
+++ b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem.properties
@@ -262,6 +262,8 @@ AUTO_CHECKER_RESULT_BLOCKS=§7Blocks: §c{0}§7, Max: §e{1}
AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unknown block: §c{0}
AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2}
AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Forbidden block: §c{0}
+AUTO_CHECKER_RESULT_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048
+AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Dispenser: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Forbidden Item: [{0}, {1}, {2}] -> §c{3}
AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Defunct NBT: §7[{0}, {1}, {2}]
AUTO_CHECKER_RESULT_DESIGN_BLOCK=§7{0} in Design: [{1}, {2}, {3}]
diff --git a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties
index 12030a2f..aa72936e 100644
--- a/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties
+++ b/SchematicSystem/SchematicSystem_Core/src/SchematicSystem_de.properties
@@ -242,6 +242,8 @@ AUTO_CHECKER_RESULT_BLOCKS=§7Blöcke: §c{0}§7, Max: §e{1}
AUTO_CHECKER_RESULT_UNKNOWN_MATERIAL=§7Unbekannter Block: §c{0}
AUTO_CHECKER_RESULT_TOO_MANY_BLOCK=§7{0}: §c{1}§7, Max: §e{2}
AUTO_CHECKER_RESULT_FORBIDDEN_BLOCK=§7Verbotener Block: §c{0}
+AUTO_CHECKER_RESULT_WIND_CHARGES=§7Windcharges: §c{0}§7, Max: §e2048
+AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER=§7Werfer: §c[{0}, {1}, {2}]§7, Windcharges: §c{3}§7
AUTO_CHECKER_RESULT_FORBIDDEN_ITEM=§7Verbotener gegenstand: [{0}, {1}, {2}] -> §c{3}
AUTO_CHECKER_RESULT_DEFUNCT_NBT=§7Keine NBT-Daten: §c[{0}, {1}, {2}]
AUTO_CHECKER_RESULT_DESIGN_BLOCK=§7{0} im Design: [{1}, {2}, {3}]
diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java
index eb464553..7d17e8f9 100644
--- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java
+++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java
@@ -55,6 +55,7 @@ public class AutoChecker {
private final List records = new ArrayList<>();
private final Map> designBlocks = new EnumMap<>(Material.class);
private final Map dispenserItems = new HashMap<>();
+ private final Map windChargeCount = new HashMap<>();
private final Map> forbiddenItems = new HashMap<>();
private final Map> forbiddenNbt = new HashMap<>();
}
diff --git a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java
index 60ab9070..0cb6e386 100644
--- a/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java
+++ b/SchematicSystem/SchematicSystem_Core/src/de/steamwar/schematicsystem/autocheck/AutoCheckerResult.java
@@ -20,9 +20,8 @@
package de.steamwar.schematicsystem.autocheck;
import de.steamwar.core.Core;
-import de.steamwar.sql.GameModeConfig;
import de.steamwar.schematicsystem.SchematicSystem;
-import de.steamwar.sql.SchematicType;
+import de.steamwar.sql.GameModeConfig;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
@@ -53,6 +52,7 @@ public class AutoCheckerResult {
isBlockCountOk() &&
isLimitedBlocksOK() &&
isDispenserItemsOK() &&
+ isWindchargeCountOK() &&
!type.isAfterDeadline() &&
entities.isEmpty() &&
isDesignBlastResistanceOK();
@@ -63,8 +63,18 @@ public class AutoCheckerResult {
!type.isAfterDeadline();
}
+ public boolean isWindchargeCountOK() {
+ if( type.Schematic.Type.getName().equals("wargearseason26")) {
+ int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0);
+ return windChargesCount <= 2048;
+ }
+ else {
+ return true;
+ }
+ }
+
public boolean isDispenserItemsOK() {
- return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems);
+ return blockScanResult.getDispenserItems().values().stream().allMatch(i -> i <= type.Schematic.MaxDispenserItems);
}
public boolean hasWarnings() {
@@ -102,7 +112,9 @@ public class AutoCheckerResult {
}
public boolean isDesignBlastResistanceOK() {
- return blockScanResult.getDesignBlocks().keySet().stream().map(Material::getBlastResistance).noneMatch(i -> i > type.Schematic.MaxDesignBlastResistance);
+ return blockScanResult.getDesignBlocks().keySet().stream()
+ .filter(material -> material != Material.WATER && material != Material.LAVA)
+ .map(Material::getBlastResistance).noneMatch(i -> i > type.Schematic.MaxDesignBlastResistance);
}
public void sendErrorMessage(Player p, String schemName) {
@@ -126,6 +138,19 @@ public class AutoCheckerResult {
}
});
}
+
+ if(!isWindchargeCountOK()) {
+ int windChargesCount = blockScanResult.getWindChargeCount().values().stream().reduce(Integer::sum).orElse(0);
+ SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES", p, windChargesCount, 2048);
+ blockScanResult.getWindChargeCount().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > 0).forEach(blockVector3IntegerEntry -> {
+ SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_WIND_CHARGES_DISPENSER", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()),
+ blockVector3IntegerEntry.getKey().getBlockX(),
+ blockVector3IntegerEntry.getKey().getBlockY(),
+ blockVector3IntegerEntry.getKey().getBlockZ(),
+ blockVector3IntegerEntry.getValue());
+ });
+ }
+
blockScanResult.getDispenserItems().entrySet().stream().filter(blockVector3IntegerEntry -> blockVector3IntegerEntry.getValue() > type.Schematic.MaxDispenserItems).forEach(blockVector3IntegerEntry -> {
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_TOO_MANY_DISPENSER_ITEMS", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3IntegerEntry.getKey()),
blockVector3IntegerEntry.getKey().getBlockX(),
@@ -134,6 +159,7 @@ public class AutoCheckerResult {
blockVector3IntegerEntry.getValue(),
type.Schematic.MaxDispenserItems);
});
+
blockScanResult.getRecords().forEach(blockVector3 -> {
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_RECORD", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(blockVector3), blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ());
});
@@ -148,6 +174,7 @@ public class AutoCheckerResult {
});
if(Core.getVersion() > 12) {
blockScanResult.getDesignBlocks().forEach((material, poss) -> {
+ if (material == Material.WATER || material == Material.LAVA) return;
if(material.getBlastResistance() > type.Schematic.MaxDesignBlastResistance) {
poss.forEach(pos -> {
SchematicSystem.MESSAGE.sendPrefixless("AUTO_CHECKER_RESULT_DESIGN_BLOCK", p, SchematicSystem.MESSAGE.parse("AUTO_CHECKER_RESULT_TELEPORT_HERE", p), tpCommandTo(pos), material.name(), pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
diff --git a/SchematicSystem/build.gradle.kts b/SchematicSystem/build.gradle.kts
index 65613802..947812e3 100644
--- a/SchematicSystem/build.gradle.kts
+++ b/SchematicSystem/build.gradle.kts
@@ -32,4 +32,5 @@ dependencies {
implementation(project(":SchematicSystem:SchematicSystem_15"))
implementation(project(":SchematicSystem:SchematicSystem_19"))
implementation(project(":SchematicSystem:SchematicSystem_20"))
+ implementation(project(":SchematicSystem:SchematicSystem_21"))
}
diff --git a/SpigotCore/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java b/SpigotCore/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java
index 60e4758d..b0f0238e 100644
--- a/SpigotCore/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java
+++ b/SpigotCore/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java
@@ -67,36 +67,31 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
}
@Override
- public void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat) {
- Clipboard clipboard = null;
- try {
- clipboard = getClipboard(is, schemFormat);
- } catch (IOException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
-
- if (clipboard == null)
- throw new NoClipboardException();
-
+ public void setPlayerClipboard(Player player, Clipboard clipboard) {
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard));
}
@Override
- public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
- try {
+ public Clipboard getClipboard(NodeData data) throws IOException {
+ InputStream is = data.schemData(true);
+ return readClipboard(is, data.getNodeFormat());
+ }
- switch (schemFormat) {
- case SPONGE_V2:
- case SPONGE_V3:
- return new SpongeSchematicReader(new NBTInputStream(is), this).read();
- case MCEDIT:
- return new MCEditSchematicReader(new NBTInputStream(is)).read();
- default:
- throw new IOException("This schematic format is currently not supported");
- }
- } catch (NullPointerException e) {
- throw new NoClipboardException();
+ @Override
+ public Clipboard getClipboard(InputStream inputStream) throws IOException {
+ return readClipboard(inputStream, getNativeFormat());
+ }
+
+ private Clipboard readClipboard(InputStream is, NodeData.SchematicFormat format) throws IOException {
+ switch (format) {
+ case SPONGE_V2:
+ case SPONGE_V3:
+ return new SpongeSchematicReader(new NBTInputStream(is), this).read();
+ case MCEDIT:
+ return new MCEditSchematicReader(new NBTInputStream(is)).read();
+ default:
+ throw new IOException("This schematic format is currently not supported");
}
}
diff --git a/SpigotCore/SpigotCore_21/src/de/steamwar/core/WorldEditWrapper21.java b/SpigotCore/SpigotCore_21/src/de/steamwar/core/WorldEditWrapper21.java
index 15256d90..b1e97156 100644
--- a/SpigotCore/SpigotCore_21/src/de/steamwar/core/WorldEditWrapper21.java
+++ b/SpigotCore/SpigotCore_21/src/de/steamwar/core/WorldEditWrapper21.java
@@ -19,12 +19,13 @@
package de.steamwar.core;
+import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
+import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
-import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
-import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
-import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader;
+import com.sk89q.worldedit.extent.clipboard.io.*;
+import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV1Reader;
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV2Reader;
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader;
import com.sk89q.worldedit.math.Vector3;
@@ -37,10 +38,12 @@ import org.bukkit.util.Vector;
import org.enginehub.linbus.stream.LinBinaryIO;
import java.io.DataInputStream;
+import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Function;
public class WorldEditWrapper21 implements WorldEditWrapper {
@@ -54,43 +57,68 @@ public class WorldEditWrapper21 implements WorldEditWrapper {
}
@Override
- public void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat) {
- Clipboard clipboard = null;
- try {
- clipboard = getClipboard(is, schemFormat);
- } catch (IOException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
-
- if (clipboard == null)
- throw new SecurityException("Clipboard is null");
-
+ public void setPlayerClipboard(Player player, Clipboard clipboard) {
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard));
}
@Override
- @SuppressWarnings("removal")
- public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat ignored) throws IOException {
- ResetableInputStream ris = new ResetableInputStream(is);
- for (NodeData.SchematicFormat schemFormat : NodeData.SchematicFormat.values()) {
- try {
- Clipboard clipboard = switch (schemFormat) {
- case MCEDIT -> new MCEditSchematicReader(new NBTInputStream(ris)).read();
- case SPONGE_V2 -> new SpongeSchematicV2Reader(LinBinaryIO.read(new DataInputStream(ris))).read();
- case SPONGE_V3 -> new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(ris))).read();
- };
- ris.close();
- return clipboard;
- } catch (Exception e) {
- // Ignore
- }
- ris.reset();
+ public Clipboard getClipboard(NodeData data) throws IOException {
+ ResetableInputStream is = new ResetableInputStream(data.schemData(false));
+ for (ClipboardFormat clipboardFormat : ClipboardFormats.getAll()) {
+ FilterInputStream fis = new FilterInputStream(is) {
+ @Override
+ public void close() throws IOException {
+ // Ignore close call!
+ }
+ };
+ boolean canBeRead = clipboardFormat.isFormat(fis);
+ is.reset();
+ if (!canBeRead) continue;
+ return clipboardFormat.load(is);
}
throw new IOException("No clipboard found");
}
- private class ResetableInputStream extends InputStream {
+ private static final Function FastV3 = FastSchematicReaderV3::new;
+ @SuppressWarnings("removal")
+ private static final Function FastV2 = inputStream -> new FastSchematicReaderV2(new NBTInputStream(inputStream));
+ @SuppressWarnings("removal")
+ private static final Function McEdit = inputStream -> new MCEditSchematicReader(new NBTInputStream(inputStream));
+ private static final Function SpongeV3 = inputStream -> new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
+ private static final Function SpongeV2 = inputStream -> new SpongeSchematicV2Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
+ private static final Function SpongeV1 = inputStream -> new SpongeSchematicV1Reader(LinBinaryIO.read(new DataInputStream(inputStream)));
+
+ private static final Function[] READERS = new Function[]{
+ FastV3,
+ FastV2,
+ SpongeV3,
+ SpongeV2,
+ SpongeV1,
+ McEdit
+ };
+
+ @Override
+ public Clipboard getClipboard(InputStream inputStream) throws IOException {
+ ResetableInputStream is = new ResetableInputStream(inputStream);
+ for (Function reader : READERS) {
+ FilterInputStream fis = new FilterInputStream(is) {
+ @Override
+ public void close() throws IOException {
+ // Ignore close call!
+ }
+ };
+ try {
+ return reader.apply(fis).read();
+ } catch (Exception e) {
+ is.reset();
+ }
+ }
+ is.close();
+ throw new IOException("No clipboard found");
+ }
+
+ private static class ResetableInputStream extends InputStream {
private InputStream inputStream;
private int pointer = 0;
diff --git a/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java
index cc021f19..4f45729d 100644
--- a/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java
+++ b/SpigotCore/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java
@@ -22,7 +22,10 @@ package de.steamwar.core;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.*;
-import com.sk89q.worldedit.*;
+import com.sk89q.worldedit.BlockVector;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extension.input.ParserContext;
@@ -57,22 +60,25 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
}
@Override
- public void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat) {
+ public void setPlayerClipboard(Player player, Clipboard clipboard) {
WorldData world = new BukkitWorld(player.getWorld()).getWorldData();
- Clipboard clipboard;
- try {
- clipboard = getClipboard(is, schemFormat);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
-
Actor actor = WorldEditWrapper.getWorldEditPlugin().wrapCommandSender(player);
WorldEditWrapper.getWorldEditPlugin().getWorldEdit().getSessionManager().get(actor).setClipboard(new ClipboardHolder(clipboard, world));
}
@Override
- public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
- switch (schemFormat) {
+ public Clipboard getClipboard(NodeData data) throws IOException {
+ InputStream is = data.schemData(true);
+ return readClipboard(is, data.getNodeFormat());
+ }
+
+ @Override
+ public Clipboard getClipboard(InputStream inputStream) throws IOException {
+ return readClipboard(inputStream, getNativeFormat());
+ }
+
+ private Clipboard readClipboard(InputStream is, NodeData.SchematicFormat format) throws IOException {
+ switch (format) {
case MCEDIT:
return new SchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
case SPONGE_V2:
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java
index f3b0accc..724f8184 100644
--- a/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java
@@ -22,10 +22,10 @@ package de.steamwar.core;
import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
-import com.sk89q.worldedit.session.ClipboardHolder;
-import de.steamwar.sql.NoClipboardException;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.session.ClipboardHolder;
+import de.steamwar.sql.NoClipboardException;
import de.steamwar.sql.NodeData;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@@ -38,8 +38,10 @@ public interface WorldEditWrapper {
WorldEditWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
InputStream getPlayerClipboard(Player player);
- void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat);
- Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException;
+
+ void setPlayerClipboard(Player player, Clipboard clipboard);
+ Clipboard getClipboard(NodeData data) throws IOException;
+ Clipboard getClipboard(InputStream inputStream) throws IOException;
Vector getOrigin(Clipboard clipboard);
Vector getMinimum(Region region);
diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java
index 72fd070f..f83e5a78 100644
--- a/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java
+++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/sql/SchematicData.java
@@ -29,14 +29,6 @@ import java.io.InputStream;
public class SchematicData {
- public static Clipboard clipboardFromStream(InputStream is, NodeData.SchematicFormat schemFormat) {
- try {
- return WorldEditWrapper.impl.getClipboard(is, schemFormat);
- } catch (IOException e) {
- throw new SecurityException("Could not read schem", e);
- }
- }
-
private final NodeData data;
public SchematicData(SchematicNode node) {
@@ -60,11 +52,11 @@ public class SchematicData {
}
public Clipboard load() throws IOException, NoClipboardException {
- return WorldEditWrapper.impl.getClipboard(data.schemData(), data.getNodeFormat());
+ return WorldEditWrapper.impl.getClipboard(data);
}
public void loadToPlayer(Player player) throws IOException, NoClipboardException {
- WorldEditWrapper.impl.setPlayerClipboard(player, data.schemData(), data.getNodeFormat());
+ WorldEditWrapper.impl.setPlayerClipboard(player, WorldEditWrapper.impl.getClipboard(data));
}
public static void saveFromPlayer(Player player, SchematicNode node) throws IOException, NoClipboardException {
diff --git a/Teamserver/src/de/steamwar/teamserver/listener/SelectAdjacent.java b/Teamserver/src/de/steamwar/teamserver/listener/SelectAdjacent.java
deleted file mode 100644
index 4a9f4d0d..00000000
--- a/Teamserver/src/de/steamwar/teamserver/listener/SelectAdjacent.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.teamserver.listener;
-
-import com.sk89q.worldedit.bukkit.BukkitWorld;
-import com.sk89q.worldedit.bukkit.WorldEditPlugin;
-import com.sk89q.worldedit.math.BlockVector3;
-import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
-import com.sk89q.worldedit.world.World;
-import de.steamwar.core.WorldEditRenderer;
-import de.steamwar.linkage.Linked;
-import de.steamwar.linkage.MinVersion;
-import de.steamwar.teamserver.Builder;
-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.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.Action;
-import org.bukkit.event.player.PlayerInteractEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.scheduler.BukkitTask;
-import org.bukkit.util.Vector;
-
-import java.util.*;
-import java.util.function.Predicate;
-
-@Linked
-@MinVersion(20)
-public class SelectAdjacent implements Listener {
-
- private Vector[] FACES = {
- new Vector(1, 0, 0),
- new Vector(-1, 0, 0),
- new Vector(0, 1, 0),
- new Vector(0, -1, 0),
- new Vector(0, 0, 1),
- new Vector(0, 0, -1),
-
- new Vector(1, 1, 0),
- new Vector(1, -1, 0),
- new Vector(1, 0, 1),
- new Vector(1, 0, -1),
- new Vector(-1, 1, 0),
- new Vector(-1, -1, 0),
- new Vector(-1, 0, 1),
- new Vector(-1, 0, -1),
- new Vector(0, 1, 1),
- new Vector(0, 1, -1),
- new Vector(0, -1, 1),
- new Vector(0, -1, -1),
- };
-
- private Map selectors = new HashMap<>();
-
- @EventHandler
- public void onPlayerInteract(PlayerInteractEvent event) {
- if (!event.hasItem()) return;
- if (event.getItem().getType() != Material.WOODEN_AXE) return;
- if (!event.getPlayer().isSneaking()) return;
- if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
- Selector selector = selectors.get(event.getPlayer());
- if (selector != null) selector.cancel();
- Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
- if (material.isAir()) {
- selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
- } else {
- selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
- }
- selectors.put(event.getPlayer(), selector);
- }
-
- @EventHandler
- public void onPlayerQuit(PlayerQuitEvent event) {
- Selector selector = selectors.remove(event.getPlayer());
- if (selector != null) selector.cancel();
- }
-
- private static final WorldEditPlugin WORLDEDIT_PLUGIN = Objects.requireNonNull((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"));
- private static final World BUKKITWORLD = new BukkitWorld(Bukkit.getWorlds().get(0));
-
- private class Selector {
-
- private static final int MAX_BLOCKS = 1_000_000;
-
- private int minX;
- private int minY;
- private int minZ;
- private int maxX;
- private int maxY;
- private int maxZ;
-
- private BukkitTask bukkitTask;
- private Predicate predicate;
- private Set seen = new HashSet<>();
- private Set toCalc = new HashSet<>();
-
- public Selector(Block block, Player player, Predicate predicate) {
- this.predicate = predicate;
- toCalc.add(block.getLocation());
- minX = block.getX();
- minY = block.getY();
- minZ = block.getZ();
- maxX = block.getX();
- maxY = block.getY();
- maxZ = block.getZ();
-
- bukkitTask = Bukkit.getScheduler().runTaskTimer(Builder.getInstance(), () -> {
- run();
-
- long volume = (long)(maxX - minX + 1) * (long)(maxY - minY + 1) * (long)(maxZ - minZ + 1);
- player.sendTitle("", "§e" + volume + " §7Blocks", 0, 5, 0);
-
- WORLDEDIT_PLUGIN.getSession(player).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ)));
- WorldEditRenderer.renderPlayer(player);
-
- // boolean finished = toCalc.stream().allMatch(location -> {
- // return location.getBlockX() >= minX && location.getBlockY() >= minY && location.getBlockZ() >= minZ &&
- // location.getBlockX() <= maxX && location.getBlockY() <= maxY && location.getBlockZ() <= maxZ;
- // });
-
- if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
- bukkitTask.cancel();
- player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
- }
- }, 1, 1);
- }
-
- private void cancel() {
- bukkitTask.cancel();
- }
-
- private void run() {
- Set current = toCalc;
- toCalc = new HashSet<>();
-
- for (Location location : current) {
- Block block = location.getBlock();
- if (block.isEmpty() || block.isLiquid()) continue;
- if (!predicate.test(block.getType())) continue;
- seen.add(location);
-
- minX = Math.min(minX, location.getBlockX());
- maxX = Math.max(maxX, location.getBlockX());
- minY = Math.min(minY, location.getBlockY());
- maxY = Math.max(maxY, location.getBlockY());
- minZ = Math.min(minZ, location.getBlockZ());
- maxZ = Math.max(maxZ, location.getBlockZ());
-
- for (Vector face : FACES) {
- Block next = block.getRelative(face.getBlockX(), face.getBlockY(), face.getBlockZ());
- if (next.isEmpty() || next.isLiquid()) continue;
- if (!predicate.test(next.getType())) continue;
- Location loc = next.getLocation();
- if (seen.contains(loc)) continue;
- toCalc.add(loc);
- }
- }
- }
- }
-}
diff --git a/TowerRun/src/de/steamwar/towerrun/commands/StartCommand.java b/TowerRun/src/de/steamwar/towerrun/commands/StartCommand.java
index 77884b37..44d285d5 100644
--- a/TowerRun/src/de/steamwar/towerrun/commands/StartCommand.java
+++ b/TowerRun/src/de/steamwar/towerrun/commands/StartCommand.java
@@ -22,6 +22,7 @@ package de.steamwar.towerrun.commands;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.linkage.Linked;
+import de.steamwar.linkage.LinkedInstance;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import de.steamwar.towerrun.TowerRun;
@@ -30,6 +31,8 @@ import org.bukkit.entity.Player;
@Linked
public class StartCommand extends SWCommand {
+
+ @LinkedInstance
private LobbyCountdown countdown;
public StartCommand() {
diff --git a/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java b/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java
index ce0a33b7..0e1c8781 100644
--- a/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java
+++ b/TowerRun/src/de/steamwar/towerrun/generator/TowerGenerator.java
@@ -159,8 +159,8 @@ public class TowerGenerator {
noKeyFloors--;
if (!chestBlocks.isEmpty() && noKeyFloors < 0 && random.nextDouble() < config.keyChance) {
noKeyFloors = random.nextInt(config.maxNoKeyFloors - config.minNoKeyFloors) + config.minNoKeyFloors;
- for (int i = 0; i < 2; i++) {
- Container container = chestBlocks.get(random.nextInt(chestBlocks.size()));
+ for (int i = 0; i < 2 && !chestBlocks.isEmpty(); i++) {
+ Container container = chestBlocks.remove(random.nextInt(chestBlocks.size()));
keys.add(container.getLocation());
}
diff --git a/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java b/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java
index d85eafdf..e928e66e 100644
--- a/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java
+++ b/TowerRun/src/de/steamwar/towerrun/listener/IngameListener.java
@@ -42,6 +42,7 @@ import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
@@ -158,10 +159,16 @@ public class IngameListener extends GameStateBukkitListener {
public void onKeyUse(PlayerInteractEvent event) {
if (!event.hasItem()) return;
if (event.getItem().getType() != Material.LEVER) return;
- event.setCancelled(true);
if (!event.hasBlock()) return;
if (event.getClickedBlock().getType() != Material.IRON_DOOR) return;
- event.getPlayer().getInventory().setItemInMainHand(null);
+ if (event.getHand() == null) return;
+ event.setCancelled(true);
+ ItemStack itemStack = event.getItem();
+ itemStack.setAmount(event.getItem().getAmount() - 1);
+ switch (event.getHand()) {
+ case OFF_HAND -> event.getPlayer().getInventory().setItemInOffHand(itemStack);
+ case HAND -> event.getPlayer().getInventory().setItemInMainHand(itemStack);
+ }
event.getClickedBlock().breakNaturally();
}
@@ -223,6 +230,8 @@ public class IngameListener extends GameStateBukkitListener {
shouldMelt(block.getRelative(0, 0, -1));
}
+ private static final Random RANDOM = new Random();
+
private void shouldMelt(Block block) {
if (block.getType().isBurnable()) return;
if (block.getType().isAir()) return;
@@ -269,7 +278,9 @@ public class IngameListener extends GameStateBukkitListener {
break;
}
Pos pos = new Pos(block.getLocation().getBlockX(), block.getLocation().getBlockY(), block.getLocation().getBlockZ());
- blocksToMelt.putIfAbsent(pos, time + meltingTime + 1);
+ int delay = meltingTime + 1 + RANDOM.nextInt(30*20)-30*10;
+ if (delay < 0) delay = meltingTime + 1;
+ blocksToMelt.putIfAbsent(pos, time + delay);
}
@EventHandler
diff --git a/TowerRun/src/de/steamwar/towerrun/winconditions/OutsideWincondition.java b/TowerRun/src/de/steamwar/towerrun/winconditions/OutsideWincondition.java
index 8b241da5..3ea07fe7 100644
--- a/TowerRun/src/de/steamwar/towerrun/winconditions/OutsideWincondition.java
+++ b/TowerRun/src/de/steamwar/towerrun/winconditions/OutsideWincondition.java
@@ -42,6 +42,10 @@ public abstract class OutsideWincondition extends WinCondition {
@EventHandler
public void onPlayerMove(PlayerMoveEvent event) {
if (event.getTo().getY() > WorldConfig.ESCAPE_HEIGHT) {
+ if (event.getTo().getY() > WorldConfig.ESCAPE_HEIGHT + 10 && Arrays.stream(WorldConfig.REGIONS).noneMatch(region -> region.contains(event.getTo().toVector()))) {
+ TowerRunPlayer tPlayer = TowerRunPlayer.get(event.getPlayer());
+ tPlayer.player().damage(Integer.MAX_VALUE);
+ }
return;
}
diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties
index 66d439df..5e619e84 100644
--- a/VelocityCore/src/de/steamwar/messages/BungeeCore.properties
+++ b/VelocityCore/src/de/steamwar/messages/BungeeCore.properties
@@ -419,7 +419,6 @@ TEAM_NOT_IN_EVENT=§cThis is not possible during an event.
TEAM_HELP_HEADER=§7Manage your team with §e/team.
TEAM_HELP_LIST=§8/§7team list §8- §7List all teams.
TEAM_HELP_INFO=§8/§7team info §8- §7Get information on a team.
-TEAM_HELP_TP=§8/§7team tp §8(§7Team§8) §8- §7Teleport to a team server.
TEAM_HELP_CREATE=§8/§7team create §8- §7Create your own team.
TEAM_HELP_JOIN=§8/§7team join §8- §7Join a team.
TEAM_HELP_CHAT=§8/§7teamchat §8- §7Send messages to your team.
diff --git a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties
index 71e55412..ed0edfc4 100644
--- a/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties
+++ b/VelocityCore/src/de/steamwar/messages/BungeeCore_de.properties
@@ -391,7 +391,6 @@ TEAM_NOT_IN_EVENT=§cDies ist während eines Events nicht möglich.
TEAM_HELP_HEADER=§7Mit §e/team §7verwaltest du dein Team.
TEAM_HELP_LIST=§8/§7team list §8- §7Liste alle Teams auf.
TEAM_HELP_INFO=§8/§7team info §8- §7Informiere dich über ein Team.
-TEAM_HELP_TP=§8/§7team tp §8(§7Team§8) §8- §7Teleportiert zum Teamserver.
TEAM_HELP_CREATE=§8/§7team create §8- §7Erstelle dein eigenes Team.
TEAM_HELP_JOIN=§8/§7team join §8- §7Trete einem Team bei.
TEAM_HELP_CHAT=§8/§7teamchat §8- §7Sende Nachrichten an dein Team.
diff --git a/VelocityCore/src/de/steamwar/sql/SQLWrapperImpl.java b/VelocityCore/src/de/steamwar/sql/SQLWrapperImpl.java
index 8e469d20..ce6e06d7 100644
--- a/VelocityCore/src/de/steamwar/sql/SQLWrapperImpl.java
+++ b/VelocityCore/src/de/steamwar/sql/SQLWrapperImpl.java
@@ -22,7 +22,6 @@ package de.steamwar.sql;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.steamwar.velocitycore.VelocityCore;
-import de.steamwar.velocitycore.commands.CheckCommand;
import java.io.File;
@@ -38,15 +37,6 @@ public class SQLWrapperImpl implements SQLWrapper {
return new GameModeConfig<>(file, GameModeConfig.ToString, GameModeConfig.ToString, GameModeConfig.ToInternalName, true);
}
- @Override
- public void processSchematicType(GameModeConfig, String> gameModeConfig) {
- SchematicType type = gameModeConfig.Schematic.Type;
- if (type.checkType() != null) {
- CheckCommand.setCheckQuestions(type.checkType(), gameModeConfig.CheckQuestions);
- CheckCommand.addFightType(type.checkType(), type);
- }
- }
-
@Override
public void additionalExceptionMetadata(StringBuilder builder) {
builder.append("\nServers: ");
diff --git a/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java b/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java
index 9657e30c..1d66ec3a 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/ArenaMode.java
@@ -25,7 +25,10 @@ import lombok.Getter;
import lombok.experimental.UtilityClass;
import java.io.File;
-import java.util.*;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
@UtilityClass
public class ArenaMode {
@@ -50,12 +53,12 @@ public class ArenaMode {
if(!folder.exists())
return;
- for(File file : Arrays.stream(folder.listFiles((file, name) -> name.endsWith(".yml") && !name.endsWith(".kits.yml") && !name.equals("config.yml"))).sorted().toList()) {
- GameModeConfig gameModeConfig = new GameModeConfig<>(file, GameModeConfig.ToString, GameModeConfig.ToString, GameModeConfig.ToInternalName, false);
+ GameModeConfig.init();
+ SchematicType.init();
+ for (GameModeConfig gameModeConfig : GameModeConfig.getAll()) {
if (!gameModeConfig.Server.loaded) continue;
-
allModes.add(gameModeConfig);
- byInternal.put(file.getName().replace(".yml", ""), gameModeConfig);
+ byInternal.put(gameModeConfig.configFile.getName().replace(".yml", ""), gameModeConfig);
for (String name : gameModeConfig.Server.ChatNames) {
byChat.put(name.toLowerCase(), gameModeConfig);
}
diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java
index fe78a018..3b95a338 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/commands/CheckCommand.java
@@ -40,6 +40,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
import java.awt.*;
import java.sql.Timestamp;
import java.time.Instant;
+import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -48,20 +49,9 @@ import java.util.logging.Level;
@Linked
public class CheckCommand extends SWCommand {
- private static final Map fightTypes = new HashMap<>();
- private static final Map> checkQuestions = new HashMap<>();
-
private static final Map currentCheckers = new HashMap<>();
private static final Map currentSchems = new HashMap<>();
- public static void setCheckQuestions(SchematicType checkType, List checkQuestions) {
- CheckCommand.checkQuestions.put(checkType, checkQuestions);
- }
-
- public static void addFightType(SchematicType checkType, SchematicType fightType) {
- fightTypes.put(checkType, fightType);
- }
-
public static boolean isChecking(Player player){
return currentCheckers.containsKey(player.getUniqueId());
}
@@ -147,7 +137,7 @@ public class CheckCommand extends SWCommand {
if(!schem.getSchemtype().check()){
VelocityCore.getLogger().log(Level.SEVERE, () -> sender.user().getUserName() + " tried to check an uncheckable schematic!");
return;
- }else if(schem.getOwner() == sender.user().getId()) {
+ }else if(schem.getOwner() == sender.user().getId() && !sender.user().hasPerm(UserPerm.ADMINISTRATION)) {
sender.system("CHECK_SCHEMATIC_OWN");
return;
}
@@ -248,9 +238,9 @@ public class CheckCommand extends SWCommand {
this.checker = checker;
this.schematic = schematic;
this.startTime = Timestamp.from(Instant.now());
- this.checkList = checkQuestions.get(schematic.getSchemtype()).listIterator();
+ this.checkList = GameModeConfig.getBySchematicType(schematic.getSchemtype()).CheckQuestions.listIterator();
- GameModeConfig mode = ArenaMode.getBySchemType(fightTypes.get(schematic.getSchemtype()));
+ GameModeConfig mode = GameModeConfig.getBySchematicType(schematic.getSchemtype());
new ServerStarter().test(mode, mode.getRandomMap(), checker.getPlayer()).check(schematic.getId()).callback(subserver -> {
currentCheckers.put(checker.user().getUUID(), this);
currentSchems.put(schematic.getId(), this);
@@ -304,7 +294,50 @@ public class CheckCommand extends SWCommand {
}
private void accept(){
- concludeCheckSession("freigegeben", fightTypes.get(schematic.getSchemtype()), () -> {
+ // TODO: This Code is only for the WGS and because YoyoNow is not available this can be removed or changed after the WGS!
+ if (schematic.getSchemtype().toDB().equals("cwargearseason26")) {
+ int userId = schematic.getOwner();
+ SteamwarUser user = SteamwarUser.byId(userId);
+ int teamId = user.getTeam();
+
+ SchematicNode teamFolder = SchematicNode.getSchematicNodeInNode(172325)
+ .stream()
+ .filter(schematicNode -> schematicNode.getName().startsWith(teamId + "_"))
+ .findFirst()
+ .orElse(null);
+ if (teamFolder == null) {
+ internalAccept();
+ return;
+ }
+
+ // Copy Schem into team folder of -1 user
+ String name = DateTimeFormatter.ofPattern("yyyy.MM.dd_HH:mm:ss").format(schematic.getLastUpdate().toLocalDateTime());
+ NodeData data = NodeData.getLatest(schematic);
+ SchematicNode node = SchematicNode.createSchematic(-1, name, teamFolder.getNodeId());
+ NodeData.saveFromStream(node, data.schemData(false), data.getNodeFormat());
+
+ // Accept the team folder schematic and set other to Normal
+ node.setSchemtype(GameModeConfig.getBySchematicType(schematic.getSchemtype()).Schematic.Type);
+
+ // Conclude by setting send in schematic to normal and broadcast
+ concludeCheckSession("freigegeben", SchematicType.Normal, () -> {
+ Chatter owner = Chatter.of(SteamwarUser.byId(schematic.getOwner()).getUUID());
+ owner.withPlayerOrOffline(
+ player -> owner.system("CHECK_ACCEPTED", schematic.getSchemtype().name(), schematic.getName()),
+ () -> DiscordAlert.send(owner, Color.GREEN, new Message("DC_TITLE_SCHEMINFO"), new Message("DC_SCHEM_ACCEPT", schematic.getName()), true)
+ );
+ notifyTeam(new Message("CHECK_ACCEPTED_TEAM", schematic.getName(), owner.user().getUserName()));
+
+ return owner.getPlayer() != null;
+ });
+ return;
+ }
+
+ internalAccept();
+ }
+
+ private void internalAccept() {
+ concludeCheckSession("freigegeben", GameModeConfig.getBySchematicType(schematic.getSchemtype()).Schematic.Type, () -> {
Chatter owner = Chatter.of(SteamwarUser.byId(schematic.getOwner()).getUUID());
owner.withPlayerOrOffline(
player -> owner.system("CHECK_ACCEPTED", schematic.getSchemtype().name(), schematic.getName()),
diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/GDPRQuery.java b/VelocityCore/src/de/steamwar/velocitycore/commands/GDPRQuery.java
index d5756890..4cdbfc69 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/commands/GDPRQuery.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/commands/GDPRQuery.java
@@ -19,14 +19,14 @@
package de.steamwar.velocitycore.commands;
-import de.steamwar.linkage.Linked;
-import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.command.SWCommand;
+import de.steamwar.linkage.Linked;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.PlayerChatter;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import de.steamwar.sql.internal.Statement;
+import de.steamwar.velocitycore.VelocityCore;
import java.io.*;
import java.util.zip.ZipEntry;
@@ -76,13 +76,11 @@ public class GDPRQuery extends SWCommand {
sqlCSV(user, out, bauweltMember, "BuildMember.csv");
sqlCSV(user, out, bauweltMembers, "BuildMembers.csv");
sqlCSV(user, out, checkedSchems, "SchematicChecksessions.csv");
- sqlCSV(user, out, userElo, "UserElo.csv");
sqlCSV(user, out, fights, "Fights.csv");
sqlCSV(user, out, ignoredPlayers, "IgnoredPlayers.csv");
sqlCSV(user, out, ignoringPlayers, "IgnoringPlayers.csv");
sqlCSV(user, out, schematicMember, "SchematicMember.csv");
sqlCSV(user, out, schematicMembers, "SchematicMembers.csv");
- sqlCSV(user, out, pollAnswers, "PollAnswers.csv");
sqlCSV(user, out, punishments, "Punishments.csv");
sqlCSV(user, out, sessions, "Sessions.csv");
sqlCSV(user, out, userData, "UserData.csv");
@@ -104,13 +102,11 @@ public class GDPRQuery extends SWCommand {
private static final Statement bauweltMember = new Statement("SELECT BauweltID AS Bauwelt, WorldEdit, World FROM BauweltMember WHERE MemberID = ?");
private static final Statement bauweltMembers = new Statement("SELECT u.UserName AS 'User', m.WorldEdit AS WorldEdit, m.World AS World FROM BauweltMember m INNER JOIN UserData u ON m.MemberID = u.id WHERE m.BauweltID = ?");
private static final Statement checkedSchems = new Statement("SELECT NodeName AS Schematic, StartTime, EndTime, DeclineReason AS Result FROM CheckedSchematic WHERE NodeOwner = ? ORDER BY StartTime ASC");
- private static final Statement userElo = new Statement("SELECT GameMode, Elo, Season FROM Elo WHERE UserID = ?");
private static final Statement fights = new Statement("SELECT p.Team AS Team, p.Kit AS Kit, p.Kills AS Kills, p.IsOut AS Died, f.GameMode AS GameMode, f.Server AS Server, f.StartTime AS StartTime, f.Duration AS Duration, (f.BlueLeader = p.UserID) AS IsBlueLeader, (f.RedLeader = p.UserID) AS IsRedLeader, f.Win AS Winner, f.WinCondition AS WinCondition FROM Fight f INNER JOIN FightPlayer p ON f.FightID = p.FightID WHERE p.UserID = ? ORDER BY StartTime ASC");
private static final Statement ignoredPlayers = new Statement("SELECT u.UserName AS IgnoredPlayer FROM IgnoredPlayers i INNER JOIN UserData u ON i.Ignored = u.id WHERE Ignorer = ?");
private static final Statement ignoringPlayers = new Statement("SELECT Ignorer AS IgnoringPlayers FROM IgnoredPlayers WHERE Ignored = ?");
private static final Statement schematicMember = new Statement("SELECT s.NodeName AS SchematicName, u.UserName AS SchematicOwner FROM NodeMember m INNER JOIN SchematicNode s ON m.NodeId = s.NodeId INNER JOIN UserData u ON s.NodeOwner = u.id WHERE m.UserId = ?");
private static final Statement schematicMembers = new Statement("SELECT s.NodeName AS SchematicName, u.UserName AS Member FROM NodeMember m INNER JOIN SchematicNode s ON m.NodeId = s.NodeId INNER JOIN UserData u ON m.UserId = u.id WHERE s.NodeOwner = ?");
- private static final Statement pollAnswers = new Statement("SELECT Question, Answer FROM PollAnswer WHERE UserID = ?");
private static final Statement punishments = new Statement("SELECT Type, StartTime, EndTime, Perma, Reason FROM Punishments WHERE UserId = ?");
private static final Statement sessions = new Statement("SELECT StartTime, EndTime FROM Session WHERE UserID = ?");
private static final Statement userData = new Statement("SELECT * FROM UserData WHERE id = ?");
diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java
index 3d861398..16270087 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/commands/TeamCommand.java
@@ -19,12 +19,6 @@
package de.steamwar.velocitycore.commands;
-import com.velocitypowered.api.proxy.ConnectionRequestBuilder;
-import com.velocitypowered.api.proxy.server.RegisteredServer;
-import com.velocitypowered.api.proxy.server.ServerInfo;
-import com.velocitypowered.api.proxy.server.ServerPing;
-import com.viaversion.viaversion.api.Via;
-import com.viaversion.viaversion.velocity.platform.VelocityViaConfig;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
@@ -33,19 +27,19 @@ import de.steamwar.linkage.Linked;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
import de.steamwar.messages.PlayerChatter;
-import de.steamwar.persistent.Storage;
-import de.steamwar.sql.*;
+import de.steamwar.sql.Event;
+import de.steamwar.sql.SteamwarUser;
+import de.steamwar.sql.Team;
+import de.steamwar.sql.TeamTeilnahme;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.discord.DiscordBot;
import de.steamwar.velocitycore.inventory.SWItem;
import de.steamwar.velocitycore.inventory.SWListInv;
-import lombok.val;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
-import java.net.*;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -63,7 +57,7 @@ public class TeamCommand extends SWCommand {
@Register(noTabComplete = true)
public void help(Chatter sender, String... args){
- helpMessages(sender, "TEAM_HELP_HEADER", "TEAM_HELP_LIST", "TEAM_HELP_INFO", "TEAM_HELP_TP");
+ helpMessages(sender, "TEAM_HELP_HEADER", "TEAM_HELP_LIST", "TEAM_HELP_INFO");
SteamwarUser user = sender.user();
if(user.getTeam() == 0) {
@@ -469,10 +463,14 @@ public class TeamCommand extends SWCommand {
@ClassMapper(Event.class)
public TypeMapper eventTypeMapper() {
- return new TypeMapper() {
+ return new TypeMapper<>() {
@Override
public Event map(Chatter sender, PreviousArguments previousArguments, String s) {
- return Event.get(s);
+ return Event.getComing()
+ .stream()
+ .filter(event -> event.getEventName().replace(" ", "").equalsIgnoreCase(s))
+ .findFirst()
+ .orElse(null);
}
@Override
@@ -487,7 +485,7 @@ public class TeamCommand extends SWCommand {
@Override
public Collection tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
- return Event.getComing().stream().map(Event::getEventName).toList();
+ return Event.getComing().stream().map(Event::getEventName).map(e -> e.replace(" ", "")).toList();
}
};
}
diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java
index 53e4639e..08e3ef57 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/BanListener.java
@@ -46,7 +46,9 @@ public class BanListener extends BasicListener {
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
String ip = IPSanitizer.getTrueAddress(player).getHostAddress();
if (user.isPunished(Punishment.PunishmentType.Ban)) {
- BannedUserIPs.banIP(user.getId(), ip);
+ if (!player.getUsername().startsWith(".")) {
+ BannedUserIPs.banIP(user.getId(), ip);
+ }
Chatter.of(event).system(PunishmentCommand.punishmentMessage(user, Punishment.PunishmentType.Ban));
return;
}
diff --git a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java
index 125e0388..f80b57cf 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/tablist/Tablist.java
@@ -158,7 +158,6 @@ public class Tablist extends ChannelInboundHandlerAdapter {
public void disable() {
sendTabPacket(new ArrayList<>(directTabItems.values()), null);
- directTabItems.clear();
sendTabPacket(current, null);
current.clear();
diff --git a/VelocityCore/src/de/steamwar/velocitycore/util/BauLock.java b/VelocityCore/src/de/steamwar/velocitycore/util/BauLock.java
index ee8d7e71..e36fc904 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/util/BauLock.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/util/BauLock.java
@@ -55,7 +55,7 @@ public class BauLock {
break;
case SUPERVISOR:
BauweltMember member = BauweltMember.getBauMember(owner.getId(), target.getId());
- locked = !member.isSupervisor();
+ locked = member == null || !member.isSupervisor();
break;
case SERVERTEAM:
locked = !target.hasPerm(UserPerm.TEAM);
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b29b83d2..26c3bd0b 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -101,6 +101,7 @@ dependencyResolutionManagement {
library("hamcrest", "org.hamcrest:hamcrest:2.2")
library("classindex", "org.atteo.classindex:classindex:3.13")
+
library("spigotapi", "org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT")
library("spigotannotations", "org.spigotmc:plugin-annotations:1.2.3-SNAPSHOT")
library("paperapi", "io.papermc.paper:paper-api:1.19.2-R0.1-SNAPSHOT")
@@ -222,6 +223,7 @@ include(
"SchematicSystem:SchematicSystem_15",
"SchematicSystem:SchematicSystem_19",
"SchematicSystem:SchematicSystem_20",
+ "SchematicSystem:SchematicSystem_21",
"SchematicSystem:SchematicSystem_Core"
)