diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java
deleted file mode 100644
index 1c44e35d..00000000
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java
+++ /dev/null
@@ -1,362 +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.simulator;
-
-import de.steamwar.bausystem.BauSystem;
-import de.steamwar.bausystem.Permission;
-import de.steamwar.bausystem.SWUtils;
-import de.steamwar.bausystem.features.simulator.data.Simulator;
-import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
-import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
-import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement;
-import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase;
-import de.steamwar.bausystem.features.simulator.data.redstone.RedstoneElement;
-import de.steamwar.bausystem.features.simulator.data.redstone.RedstonePhase;
-import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement;
-import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase;
-import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
-import de.steamwar.bausystem.features.simulator.gui.SimulatorGroupGui;
-import de.steamwar.bausystem.features.simulator.gui.SimulatorGui;
-import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui;
-import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
-import de.steamwar.bausystem.utils.ItemUtils;
-import de.steamwar.core.SWPlayer;
-import de.steamwar.cursor.Cursor;
-import de.steamwar.entity.REntity;
-import de.steamwar.entity.REntityServer;
-import de.steamwar.inventory.SWAnvilInv;
-import de.steamwar.linkage.Linked;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.block.Action;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.event.inventory.InventoryDragEvent;
-import org.bukkit.event.player.PlayerDropItemEvent;
-import org.bukkit.event.player.PlayerItemHeldEvent;
-import org.bukkit.event.player.PlayerJoinEvent;
-import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.event.player.PlayerToggleSneakEvent;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.util.Vector;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-@Linked
-public class SimulatorCursor implements Listener {
-
- private static final Map cursorType = Collections.synchronizedMap(new HashMap<>());
- private static final Map emptyTargetServers = Collections.synchronizedMap(new HashMap<>());
-
- public static boolean isSimulatorItem(ItemStack itemStack) {
- return ItemUtils.isItem(itemStack, "simulator");
- }
-
- private static boolean hasSimulatorItem(Player player) {
- return isSimulatorItem(player.getInventory().getItemInMainHand()) || isSimulatorItem(player.getInventory().getItemInOffHand());
- }
-
- private static void scheduleCursorUpdate(Player player) {
- BauSystem.runTaskLater(BauSystem.getInstance(), () -> calcCursor(player), 1);
- }
-
- @EventHandler
- public void onPlayerJoin(PlayerJoinEvent event) {
- if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
- scheduleCursorUpdate(event.getPlayer());
- }
-
- @EventHandler
- public void onPlayerDropItem(PlayerDropItemEvent event) {
- if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
- scheduleCursorUpdate(event.getPlayer());
- }
-
- @EventHandler
- public void onPlayerItemHeld(PlayerItemHeldEvent event) {
- if (!Permission.BUILD.hasPermission(event.getPlayer())) return;
- scheduleCursorUpdate(event.getPlayer());
- }
-
- @EventHandler
- public void onInventoryClick(InventoryClickEvent event) {
- if (!(event.getWhoClicked() instanceof Player player)) return;
- if (!Permission.BUILD.hasPermission(player)) return;
- scheduleCursorUpdate(player);
- }
-
- @EventHandler
- public void onInventoryDrag(InventoryDragEvent event) {
- if (!(event.getWhoClicked() instanceof Player player)) return;
- if (!Permission.BUILD.hasPermission(player)) return;
- scheduleCursorUpdate(player);
- }
-
- @EventHandler
- public void onBauMemberUpdate(BauMemberUpdateEvent event) {
- event.getChanged().forEach(SimulatorCursor::calcCursor);
- }
-
- @EventHandler
- public void onPlayerQuit(PlayerQuitEvent event) {
- cursorType.remove(event.getPlayer());
- removeCursor(event.getPlayer());
- }
-
- private static final Map LAST_SNEAKS = new HashMap<>();
-
- static {
- Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
- long millis = System.currentTimeMillis();
- LAST_SNEAKS.entrySet().removeIf(entry -> millis - entry.getValue() > 200);
- }, 1, 1);
- }
-
- @EventHandler(priority = EventPriority.HIGH)
- public void onPlayerToggleSneak(PlayerToggleSneakEvent event) {
- if (!event.isSneaking()) return;
- Player player = event.getPlayer();
- if (!hasSimulatorItem(player)) {
- return;
- }
- if (LAST_SNEAKS.containsKey(player)) {
- CursorType currentType = cursorType.getOrDefault(player, CursorType.TNT);
- if (currentType == CursorType.TNT) {
- cursorType.put(player, CursorType.REDSTONE_BLOCK);
- } else {
- cursorType.put(player, CursorType.TNT);
- }
- calcCursor(player);
- } else {
- LAST_SNEAKS.put(player, System.currentTimeMillis());
- }
- }
-
- public static CursorType getCursorType(Player player) {
- return cursorType.getOrDefault(player, CursorType.TNT);
- }
-
- public static void setCursorType(Player player, CursorType cursorType) {
- SimulatorCursor.cursorType.put(player, cursorType);
- calcCursor(player);
- }
-
- public static void calcCursor(Player player) {
- if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) {
- if (removeCursor(player) || SimulatorWatcher.show(null, player)) {
- SWUtils.sendToActionbar(player, "");
- }
- return;
- }
-
- Simulator simulator = SimulatorStorage.getSimulator(player);
- if (simulator != null && simulator.getStabGenerator() != null) {
- removeCursor(player);
- SimulatorWatcher.show(null, player);
- SWUtils.sendToActionbar(player, "§cGenerating Stab");
- return;
- }
-
- SimulatorWatcher.show(simulator, player);
- Cursor cursor = getOrCreateCursor(player, simulator, cursorType.getOrDefault(player, CursorType.TNT));
- cursor.renderDeduplicated();
- }
-
- private static Cursor getOrCreateCursor(Player player, Simulator simulator, CursorType type) {
- REntityServer targetServer = simulator == null ? emptyTargetServers.computeIfAbsent(player, __ -> new REntityServer()) : SimulatorWatcher.getEntityServerOfSimulator(simulator);
- SWPlayer swPlayer = SWPlayer.of(player);
- Optional activeCursor = swPlayer.getComponent(Cursor.class);
-
- Cursor cursor = activeCursor.orElse(null);
- if (cursor == null || cursor.getTargetServer() != targetServer) {
- swPlayer.removeComponent(Cursor.class);
- cursor = new Cursor(
- targetServer,
- player,
- Material.GLASS,
- type.material,
- type.cursorModes,
- (location, hitEntity, action) -> handlePlayerClick(player, location, hitEntity, action),
- (location, hitEntity) -> sendCursorActionbar(player, SimulatorStorage.getSimulator(player), location != null, hitEntity.isPresent())
- );
- } else {
- cursor.setCursorMaterial(type.material);
- cursor.setAllowedCursorModes(type.cursorModes);
- }
-
- return cursor;
- }
-
- private static synchronized boolean removeCursor(Player player) {
- Optional cursor = SWPlayer.of(player).getComponent(Cursor.class);
- cursor.ifPresent(__ -> SWPlayer.of(player).removeComponent(Cursor.class));
- REntityServer emptyTargetServer = emptyTargetServers.remove(player);
- if (emptyTargetServer != null) {
- emptyTargetServer.close();
- }
- return cursor.isPresent();
- }
-
- private static void sendCursorActionbar(Player player, Simulator simulator, boolean hasCursorLocation, boolean hasHitEntity) {
- if (!hasCursorLocation) {
- SWUtils.sendToActionbar(player, simulator == null ? "§eSelect Simulator" : "§eOpen Simulator");
- } else if (simulator == null) {
- SWUtils.sendToActionbar(player, "§eCreate new Simulator");
- } else if (hasHitEntity) {
- SWUtils.sendToActionbar(player, "§eEdit Position");
- } else {
- SWUtils.sendToActionbar(player, "§eAdd new " + cursorType.getOrDefault(player, CursorType.TNT).name);
- }
- }
-
- @Getter
- @AllArgsConstructor
- public enum CursorType {
- TNT(Material.TNT, Material.GUNPOWDER, List.of(Cursor.CursorMode.FREE, Cursor.CursorMode.SURFACE_ALIGNED), "TNT", vector -> new TNTElement(vector).add(new TNTPhase())),
- REDSTONE_BLOCK(Material.REDSTONE_BLOCK, Material.REDSTONE, List.of(Cursor.CursorMode.BLOCK_ALIGNED), "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())),
- OBSERVER(Material.OBSERVER, Material.QUARTZ, List.of(Cursor.CursorMode.BLOCK_ALIGNED), "Observer", vector -> new ObserverElement(vector).add(new ObserverPhase())),
- ;
-
- public final Material material;
- public final Material nonSelectedMaterial;
- public final List cursorModes;
- public final String name;
- public final Function> elementFunction;
- }
-
- private static void handlePlayerClick(Player player, Location cursorLocation, Optional hitEntity, Action action) {
- if (!Permission.BUILD.hasPermission(player)) return;
- if (!hasSimulatorItem(player)) {
- return;
- }
-
- Simulator simulator = SimulatorStorage.getSimulator(player);
-
- if (action == Action.LEFT_CLICK_BLOCK || action == Action.LEFT_CLICK_AIR) {
- if (simulator == null) {
- return;
- }
- SimulatorExecutor.run(player, simulator, null);
- return;
- }
-
- if (action != Action.RIGHT_CLICK_BLOCK && action != Action.RIGHT_CLICK_AIR) {
- return;
- }
-
- if (simulator == null) {
- if (cursorLocation == null) {
- SimulatorStorage.openSimulatorSelector(player);
- } else {
- SWAnvilInv anvilInv = new SWAnvilInv(player, "Name");
- anvilInv.setCallback(s -> {
- Simulator sim = SimulatorStorage.getSimulator(s);
- if (sim != null) {
- BauSystem.MESSAGE.send("SIMULATOR_NAME_ALREADY_EXISTS", player);
- return;
- }
- if (!s.matches("[a-zA-Z_0-9-]+")) {
- BauSystem.MESSAGE.send("SIMULATOR_NAME_INVALID", player);
- return;
- }
- sim = new Simulator(s);
- SimulatorStorage.addSimulator(s, sim);
- createElement(player, cursorLocation, sim);
- SimulatorStorage.setSimulator(player, sim);
- });
- anvilInv.open();
- }
- return;
- }
-
- if (cursorLocation == null) {
- new SimulatorGui(player, simulator).open();
- return;
- }
-
- if (hitEntity.isPresent()) {
- openElement(player, simulator, hitEntity.get());
- return;
- }
-
- createElement(player, cursorLocation, simulator);
- }
-
- private static void openElement(Player player, Simulator simulator, REntity hitEntity) {
- Vector vector = new Vector(hitEntity.getX(), hitEntity.getY(), hitEntity.getZ());
- List> elements = simulator.getGroups().stream().map(SimulatorGroup::getElements).flatMap(List::stream).filter(element -> {
- return element.getWorldPos().distanceSquared(vector) < (1 / 16.0) * (1 / 16.0);
- }).collect(Collectors.toList());
-
- switch (elements.size()) {
- case 0:
- return;
- case 1:
- SimulatorElement> element = elements.get(0);
- SimulatorGroup group1 = element.getGroup(simulator);
- SimulatorBaseGui back = new SimulatorGui(player, simulator);
- if (group1.getElements().size() > 1) {
- back = new SimulatorGroupGui(player, simulator, group1, back);
- }
- element.open(player, simulator, group1, back);
- break;
- default:
- List parents = elements.stream().map(e -> e.getGroup(simulator)).distinct().collect(Collectors.toList());
- if (parents.size() == 1) {
- SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
- new SimulatorGroupGui(player, simulator, parents.get(0), simulatorGui).open();
- } else {
- SimulatorGroup group2 = new SimulatorGroup();
- group2.setMaterial(null);
- group2.getElements().addAll(elements);
- SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
- new SimulatorGroupGui(player, simulator, group2, simulatorGui).open();
- }
- break;
- }
- }
-
- private static void createElement(Player player, Location cursorLocation, Simulator simulator) {
- CursorType type = cursorType.getOrDefault(player, CursorType.TNT);
- Vector vector = cursorLocation.toVector();
- if (type == CursorType.REDSTONE_BLOCK) {
- vector.subtract(new Vector(0.5, 0, 0.5));
- }
- SimulatorElement> element = type.elementFunction.apply(vector);
- SimulatorGroup group = new SimulatorGroup().add(element);
- simulator.getGroups().add(group);
- SimulatorGui simulatorGui = new SimulatorGui(player, simulator);
- element.open(player, simulator, group, simulatorGui);
- SimulatorWatcher.update(simulator);
- calcCursor(player);
- }
-}