diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursorManager.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursorManager.java index 8a469160..432f5acc 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursorManager.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursorManager.java @@ -70,10 +70,20 @@ import java.util.stream.Collectors; public class SimulatorCursorManager implements Listener { private static class SimulatorCursorComponent implements SWPlayer.Component { + private Player player; + private Cursor cursor; private CursorType cursorType = CursorType.TNT; private REntityServer emptyTargetServer; + private REntityServer currentTargetServer; private long lastSneakMillis; + private SimulatorCursorComponent() { + } + + private SimulatorCursorComponent(CursorType cursorType) { + this.cursorType = cursorType; + } + private REntityServer getOrCreateEmptyTargetServer() { if (emptyTargetServer == null) { emptyTargetServer = new REntityServer(); @@ -81,18 +91,168 @@ public class SimulatorCursorManager implements Listener { return emptyTargetServer; } - private boolean isDoubleSneak() { - long now = System.currentTimeMillis(); + private boolean handleSneak(long now) { boolean doubleSneak = now - lastSneakMillis <= 200; lastSneakMillis = doubleSneak ? 0 : now; return doubleSneak; } + private CursorType getCursorType() { + return cursorType; + } + + private void setCursorType(CursorType cursorType) { + this.cursorType = cursorType; + refresh(); + } + + private void switchCursorMode() { + cursorType = cursorType == CursorType.TNT ? CursorType.REDSTONE_BLOCK : CursorType.TNT; + refresh(); + } + + private void refresh() { + if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) { + deactivateCursor(player); + return; + } + + Simulator simulator = SimulatorStorage.getSimulator(player); + if (simulator != null && simulator.getStabGenerator() != null) { + removeGenericCursor(); + boolean watcherRemoved = SimulatorWatcher.show(null, player); + if (watcherRemoved) { + SWUtils.sendToActionbar(player, ""); + } + SWUtils.sendToActionbar(player, "§cGenerating Stab"); + return; + } + + SimulatorWatcher.show(simulator, player); + REntityServer targetServer = simulator == null ? getOrCreateEmptyTargetServer() : SimulatorWatcher.getEntityServerOfSimulator(simulator); + if (cursor == null || currentTargetServer != targetServer) { + removeGenericCursor(); + currentTargetServer = targetServer; + cursor = new Cursor( + targetServer, + player, + Material.GLASS, + cursorType.material, + cursorType.cursorModes, + this::handlePlayerClick, + (location, hitEntity) -> sendCursorActionbar(simulator, location != null, hitEntity.isPresent()) + ); + } else { + cursor.setCursorMaterial(cursorType.material); + cursor.setAllowedCursorModes(cursorType.cursorModes); + } + cursor.renderDeduplicated(); + } + + private void removeGenericCursor() { + if (cursor == null && !SWPlayer.of(player).hasComponent(Cursor.class)) { + currentTargetServer = null; + return; + } + + SWPlayer.of(player).removeComponent(Cursor.class); + cursor = null; + currentTargetServer = null; + } + + private void closeEmptyTargetServer() { + if (emptyTargetServer == null) { + return; + } + + emptyTargetServer.close(); + emptyTargetServer = null; + } + + private void sendCursorActionbar(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.name); + } + } + + private void handlePlayerClick(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); + } + + @Override + public void onMount(SWPlayer player) { + this.player = player.getPlayer(); + refresh(); + } + @Override public void onUnmount(SWPlayer player) { - player.removeComponent(Cursor.class); - if (emptyTargetServer != null) { - emptyTargetServer.close(); + boolean hadCursor = cursor != null || player.hasComponent(Cursor.class); + removeGenericCursor(); + closeEmptyTargetServer(); + boolean watcherRemoved = SimulatorWatcher.show(null, this.player); + if (hadCursor || watcherRemoved) { + SWUtils.sendToActionbar(this.player, ""); } } } @@ -105,12 +265,6 @@ public class SimulatorCursorManager implements Listener { return isSimulatorItem(player.getInventory().getItemInMainHand()) || isSimulatorItem(player.getInventory().getItemInOffHand()); } - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - if (!Permission.BUILD.hasPermission(event.getPlayer())) return; - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> calcCursor(event.getPlayer()), 0); - } - @EventHandler public void onPlayerDropItem(PlayerDropItemEvent event) { if (!Permission.BUILD.hasPermission(event.getPlayer())) return; @@ -125,7 +279,9 @@ public class SimulatorCursorManager implements Listener { boolean hasSimulatorInNewMainHand = isSimulatorItem(player.getInventory().getItem(event.getNewSlot())); boolean hasSimulatorInOffHand = isSimulatorItem(player.getInventory().getItemInOffHand()); if (!hasSimulatorInNewMainHand && !hasSimulatorInOffHand) { - if (deactivateCursor(player) || SimulatorWatcher.show(null, player)) { + boolean cursorRemoved = deactivateCursor(player); + boolean watcherRemoved = SimulatorWatcher.show(null, player); + if (cursorRemoved || watcherRemoved) { SWUtils.sendToActionbar(player, ""); } return; @@ -151,74 +307,60 @@ public class SimulatorCursorManager implements Listener { if (!hasSimulatorItem(player)) { return; } - SimulatorCursorComponent component = getOrCreateComponent(player); - if (component.isDoubleSneak()) { - component.cursorType = component.cursorType == CursorType.TNT ? CursorType.REDSTONE_BLOCK : CursorType.TNT; - calcCursor(player); + SimulatorCursorComponent component = activateOrRefresh(player); + if (component == null) { + return; + } + boolean shouldSwitch = component.handleSneak(System.currentTimeMillis()); + if (shouldSwitch) { + component.switchCursorMode(); } } public static CursorType getCursorType(Player player) { return SWPlayer.of(player).getComponent(SimulatorCursorComponent.class) - .map(component -> component.cursorType) + .map(SimulatorCursorComponent::getCursorType) .orElse(CursorType.TNT); } public static void setCursorType(Player player, CursorType cursorType) { - getOrCreateComponent(player).cursorType = cursorType; - calcCursor(player); + Optional component = SWPlayer.of(player).getComponent(SimulatorCursorComponent.class); + if (component.isPresent()) { + component.get().setCursorType(cursorType); + return; + } + + if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) { + return; + } + SWPlayer.of(player).setComponent(new SimulatorCursorComponent(cursorType)); } public static void calcCursor(Player player) { + activateOrRefresh(player); + } + + private static SimulatorCursorComponent activateOrRefresh(Player player) { if (!Permission.BUILD.hasPermission(player) || !hasSimulatorItem(player)) { - if (deactivateCursor(player) || SimulatorWatcher.show(null, player)) { + boolean cursorRemoved = deactivateCursor(player); + boolean watcherRemoved = SimulatorWatcher.show(null, player); + if (cursorRemoved || watcherRemoved) { SWUtils.sendToActionbar(player, ""); } - return; + return null; } - Simulator simulator = SimulatorStorage.getSimulator(player); - if (simulator != null && simulator.getStabGenerator() != null) { - deactivateCursor(player); - SimulatorWatcher.show(null, player); - SWUtils.sendToActionbar(player, "§cGenerating Stab"); - return; - } - - SimulatorCursorComponent component = getOrCreateComponent(player); - SimulatorWatcher.show(simulator, player); - Cursor cursor = getOrCreateCursor(player, simulator, component); - cursor.renderDeduplicated(); - } - - private static SimulatorCursorComponent getOrCreateComponent(Player player) { - return SWPlayer.of(player).getComponentOrDefault(SimulatorCursorComponent.class, SimulatorCursorComponent::new); - } - - private static Cursor getOrCreateCursor(Player player, Simulator simulator, SimulatorCursorComponent component) { - REntityServer targetServer = simulator == null ? component.getOrCreateEmptyTargetServer() : SimulatorWatcher.getEntityServerOfSimulator(simulator); SWPlayer swPlayer = SWPlayer.of(player); - Optional activeCursor = swPlayer.getComponent(Cursor.class); - CursorType type = component.cursorType; - - 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, component, SimulatorStorage.getSimulator(player), location != null, hitEntity.isPresent()) - ); - } else { - cursor.setCursorMaterial(type.material); - cursor.setAllowedCursorModes(type.cursorModes); + Optional existingComponent = swPlayer.getComponent(SimulatorCursorComponent.class); + if (existingComponent.isPresent()) { + SimulatorCursorComponent component = existingComponent.get(); + component.refresh(); + return component; } - return cursor; + SimulatorCursorComponent component = new SimulatorCursorComponent(); + swPlayer.setComponent(component); + return component; } private static synchronized boolean deactivateCursor(Player player) { @@ -232,22 +374,10 @@ public class SimulatorCursorManager implements Listener { return hadSimulatorCursor || hadCursor; } - private static void sendCursorActionbar(Player player, SimulatorCursorComponent component, 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 " + component.cursorType.name); - } - } - @Getter @AllArgsConstructor public enum CursorType { - TNT(Material.TNT, Material.GUNPOWDER, List.of(Cursor.CursorMode.FREE), "TNT", vector -> new TNTElement(vector).add(new TNTPhase())), + TNT(Material.TNT, Material.GUNPOWDER, List.of(Cursor.CursorMode.SURFACE_ALIGNED, Cursor.CursorMode.FREE), "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())), ; @@ -259,64 +389,6 @@ public class SimulatorCursorManager implements Listener { 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 -> {