From ec10b0fe710d878c13d9374b29a93885cce69159 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 22 Dec 2023 09:01:54 +0100 Subject: [PATCH] Add Observer to Simulator --- .../features/simulator/SimulatorCursor.java | 14 +- .../data/SimulatorBlockAlignedElement.java | 35 ++++ .../data/observer/ObserverElement.java | 103 ++++++++++ .../data/observer/ObserverPhase.java | 81 ++++++++ .../data/redstone/RedstoneElement.java | 9 +- .../simulator/gui/SimulatorObserverGui.java | 188 ++++++++++++++++++ .../SimulatorObserverPhaseSettingsGui.java | 172 ++++++++++++++++ .../gui/SimulatorObserverSettingsGui.java | 142 +++++++++++++ .../storage/SimFormatSimulatorLoader.java | 6 + 9 files changed, 739 insertions(+), 11 deletions(-) create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/SimulatorBlockAlignedElement.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverElement.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverPhase.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java index 911872ba..83b373ce 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java @@ -26,6 +26,8 @@ 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; @@ -230,7 +232,7 @@ public class SimulatorCursor implements Listener { } } - public static Vector getPosTNT(Player player, RayTraceUtils.RRayTraceResult result) { + public static Vector getPosFree(Player player, RayTraceUtils.RRayTraceResult result) { Vector pos = result.getHitPosition(); BlockFace face = result.getHitBlockFace(); @@ -270,7 +272,7 @@ public class SimulatorCursor implements Listener { return pos; } - private static Vector getPosRedstoneBlock(Player player, RayTraceUtils.RRayTraceResult result) { + private static Vector getPosBlockAligned(Player player, RayTraceUtils.RRayTraceResult result) { Vector pos = result.getHitPosition(); BlockFace face = result.getHitBlockFace(); @@ -309,8 +311,9 @@ public class SimulatorCursor implements Listener { @Getter @AllArgsConstructor public enum CursorType { - TNT(Material.TNT, SimulatorCursor::getPosTNT, "TNT", vector -> new TNTElement(vector).add(new TNTPhase())), - REDSTONE_BLOCK(Material.REDSTONE_BLOCK, SimulatorCursor::getPosRedstoneBlock, "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())), + TNT(Material.TNT, SimulatorCursor::getPosFree, "TNT", vector -> new TNTElement(vector).add(new TNTPhase())), + REDSTONE_BLOCK(Material.REDSTONE_BLOCK, SimulatorCursor::getPosBlockAligned, "Redstone Block", vector -> new RedstoneElement(vector).add(new RedstonePhase())), + OBSERVER(Material.OBSERVER, SimulatorCursor::getPosBlockAligned, "Observer", vector -> new ObserverElement(vector).add(new ObserverPhase())), ; private Material material; @@ -322,6 +325,9 @@ public class SimulatorCursor implements Listener { if (this == TNT) { return REDSTONE_BLOCK; } + if (this == REDSTONE_BLOCK) { + return OBSERVER; + } return TNT; } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/SimulatorBlockAlignedElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/SimulatorBlockAlignedElement.java new file mode 100644 index 00000000..de0d2b69 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/SimulatorBlockAlignedElement.java @@ -0,0 +1,35 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.data; + +import org.bukkit.Material; +import org.bukkit.util.Vector; + +public abstract class SimulatorBlockAlignedElement extends SimulatorElement { + + protected SimulatorBlockAlignedElement(Material material, Vector position) { + super(material, position); + } + + @Override + public final boolean canBeInGroup(SimulatorGroup simulatorGroup) { + return simulatorGroup.getElements().stream().allMatch(SimulatorBlockAlignedElement.class::isInstance); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverElement.java new file mode 100644 index 00000000..9c7f36d5 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverElement.java @@ -0,0 +1,103 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.data.observer; + +import de.steamwar.bausystem.features.simulator.data.Simulator; +import de.steamwar.bausystem.features.simulator.data.SimulatorBlockAlignedElement; +import de.steamwar.bausystem.features.simulator.data.SimulatorGroup; +import de.steamwar.bausystem.features.simulator.data.SimulatorPhase; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.features.simulator.execute.SimulatorAction; +import de.steamwar.bausystem.features.simulator.gui.SimulatorObserverGui; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; +import de.steamwar.inventory.InvCallback; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.Vector; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; + +public final class ObserverElement extends SimulatorBlockAlignedElement { + + public ObserverElement(Vector position) { + super(Material.OBSERVER, position); + } + + @Override + public String getName(Player player) { + return "Observer"; + } + + @Override + public Material getWorldMaterial() { + return Material.OBSERVER; + } + + @Override + public Material getWorldDisabledMaterial() { + return Material.GRAY_STAINED_GLASS; + } + + public void toSimulatorActions(BiConsumer tickStart, BiConsumer tickEnd) { + if (disabled) return; + phases.forEach(phase -> { + phase.toSimulatorActions(position.clone(), tickStart, tickEnd); + }); + + int end = phases.stream().mapToInt(SimulatorPhase::getTickOffset).max().orElse(0) + 4; + AtomicReference blockState = new AtomicReference<>(); + tickStart.accept(0, new SimulatorAction(-100, 1) { + @Override + public void accept(World world) { + Block block = world.getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + blockState.set(block.getState()); + block.setType(Material.OBSERVER, false); + } + }); + tickEnd.accept(end, new SimulatorAction(0, 1) { + @Override + public void accept(World world) { + BlockState oldState = blockState.get(); + if (oldState != null) { + oldState.update(true, true); + } else { + Block block = world.getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + block.setType(Material.AIR); + } + } + }); + } + + @Override + public void open(Player player, Simulator simulator, SimulatorGroup group, SimulatorBaseGui back) { + new SimulatorObserverGui(player, simulator, group, this, back).open(); + } + + @Override + public String getType() { + return "Observer"; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverPhase.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverPhase.java new file mode 100644 index 00000000..e3707c3e --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/observer/ObserverPhase.java @@ -0,0 +1,81 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.data.observer; + +import de.steamwar.bausystem.features.simulator.data.SimulatorPhase; +import de.steamwar.bausystem.features.simulator.execute.SimulatorAction; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.type.Observer; +import org.bukkit.util.Vector; +import yapion.hierarchy.types.YAPIONObject; + +import java.util.function.BiConsumer; + +@NoArgsConstructor +public final class ObserverPhase extends SimulatorPhase { + + @Getter + @Setter + private BlockFace orientation = BlockFace.UP; + + public ObserverPhase(int tickOffset) { + this.tickOffset = tickOffset; + } + + { + this.lifetime = 0; + } + + @Override + public void toSimulatorActions(Vector position, BiConsumer tickStart, BiConsumer tickEnd) { + Observer observer = (Observer) Material.OBSERVER.createBlockData(); + observer.setFacing(orientation.getOppositeFace()); + observer.setPowered(true); + + tickStart.accept(tickOffset, new SimulatorAction(order, 1) { + @Override + public void accept(World world) { + Block block = world.getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + Block updateBlock = block.getRelative(orientation); + BlockState state = updateBlock.getState(); + updateBlock.setType(Material.SPONGE, true); + block.setBlockData(observer, true); + state.update(true, true); + } + }); + } + + @Override + public void saveExtra(YAPIONObject phaseObject) { + phaseObject.add("orientation", orientation.name()); + } + + @Override + public void loadExtra(YAPIONObject phaseObject) { + orientation = BlockFace.valueOf(phaseObject.getPlainValue("orientation")); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/redstone/RedstoneElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/redstone/RedstoneElement.java index 2eb7aca2..9a970526 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/redstone/RedstoneElement.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/redstone/RedstoneElement.java @@ -19,8 +19,8 @@ package de.steamwar.bausystem.features.simulator.data.redstone; +import de.steamwar.bausystem.features.simulator.data.SimulatorBlockAlignedElement; 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.gui.SimulatorRedstoneGui; import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; @@ -28,7 +28,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -public final class RedstoneElement extends SimulatorElement { +public final class RedstoneElement extends SimulatorBlockAlignedElement { public RedstoneElement(Vector position) { super(Material.REDSTONE_BLOCK, position); @@ -49,11 +49,6 @@ public final class RedstoneElement extends SimulatorElement { return Material.WHITE_STAINED_GLASS; } - @Override - public boolean canBeInGroup(SimulatorGroup simulatorGroup) { - return simulatorGroup.getElements().stream().allMatch(RedstoneElement.class::isInstance); - } - @Override public Vector getWorldPos() { return position.clone().add(new Vector(0.5, 0, 0.5)); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java new file mode 100644 index 00000000..42669387 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverGui.java @@ -0,0 +1,188 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.gui; + +import de.steamwar.bausystem.features.simulator.SimulatorWatcher; +import de.steamwar.bausystem.features.simulator.data.Simulator; +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.gui.base.SimulatorBaseGui; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorScrollGui; +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; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class SimulatorObserverGui extends SimulatorScrollGui { + + private final SimulatorGroup parent; + private final ObserverElement observer; + private final SimulatorBaseGui back; + + public SimulatorObserverGui(Player player, Simulator simulator, SimulatorGroup parent, ObserverElement observer, SimulatorBaseGui back) { + super(player, simulator, 6 * 9, observer.getPhases()); + this.parent = parent; + this.observer = observer; + this.back = back; + } + + @Override + public String baseTitle() { + return "Observer"; + } + + @Override + public void headerAndFooter() { + if (observer.getPhases().isEmpty()) { + back.open(); + SimulatorWatcher.update(simulator); + return; + } + + observer.sort(); + + // Back Arrow + inventory.setItem(0, new SWItem(Material.ARROW, "§eBack", clickType -> { + if (parent.getElements().contains(observer)) { + back.open(); + } else { + SimulatorGroup newParent = observer.getGroup(simulator); + if (newParent == null) { + player.closeInventory(); + return; + } + SimulatorGui simulatorGui = new SimulatorGui(player, simulator); + if (newParent.getElements().size() == 1) { + simulatorGui.open(); + } else { + new SimulatorGroupGui(player, simulator, newParent, simulatorGui).open(); + } + } + })); + + inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> { + observer.getPhases().clear(); + SimulatorWatcher.update(simulator); + })); + + // Material Chooser + inventory.setItem(4, observer.toItem(player, clickType -> { + new SimulatorMaterialGui(player, simulator, observer::getMaterial, observer::setMaterial, this).open(); + })); + + // Settings + inventory.setItem(47, new SWItem(Material.REPEATER, "§eSettings", clickType -> { + new SimulatorObserverSettingsGui(player, simulator, observer, this).open(); + })); + + // Enable/Disable + inventory.setItem(48, new SWItem(observer.isDisabled() ? Material.ENDER_PEARL : Material.ENDER_EYE, observer.isDisabled() ? "§cDisabled" : "§aEnabled", clickType -> { + observer.setDisabled(!observer.isDisabled()); + SimulatorWatcher.update(simulator); + })); + + // Group chooser + inventory.setItem(51, new SWItem(Material.LEAD, "§eJoin Group", clickType -> { + new SimulatorGroupChooserGui(player, simulator, observer, observer.getGroup(simulator), this).open(); + })); + } + + @Override + public SWItem[] column(ObserverPhase observerPhase, int index) { + int min; + if (index > 0) { + min = data.get(index - 1).getTickOffset() + 4; + } else { + min = 0; + } + + int max; + if (index < data.size() - 1) { + max = data.get(index + 1).getTickOffset() - 4; + } else { + max = Integer.MAX_VALUE - 4; + } + + List lore = new ArrayList<>(); + lore.add("§7Time§8:§e " + observerPhase.getTickOffset()); + lore.add("§7Order§8:§e " + observerPhase.getOrder()); + lore.add(""); + lore.add("§7Orientation§8:§e " + observerPhase.getOrientation().name()); + lore.add(""); + lore.add("§7Click§8:§e Edit"); + lore.add("§7Middle-Click§8:§e Remove"); + SWItem observer = new SWItem(Material.OBSERVER, "§eObserver", lore, false, clickType -> { + if (clickType == ClickType.MIDDLE) { + this.observer.getPhases().remove(observerPhase); + SimulatorWatcher.update(simulator); + } else { + new SimulatorObserverPhaseSettingsGui(player, simulator, this.observer, observerPhase, this).open(); + } + }); + observer.getItemStack().setAmount(Math.min(Math.max(observerPhase.getTickOffset(), 1), 64)); + + Supplier getter = observerPhase::getTickOffset; + 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 -> { + setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }), + observer, + new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> { + setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }), + new SWItem(Material.ANVIL, "§eEdit Activation", clickType -> { + new SimulatorObserverPhaseSettingsGui(player, simulator, this.observer, observerPhase, this).open(); + }), + }; + } + + @Override + public SWItem[] lastColumn() { + return new SWItem[]{ + new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> { + addNewPhase(clickType.isShiftClick()); + }), + new SWItem(Material.QUARTZ, "§eObserver§8:§a New Phase", clickType -> { + addNewPhase(false); + }), + new SWItem(SWItem.getDye(8), "§7", clickType -> { + }), + }; + } + + private void addNewPhase(boolean shift) { + ObserverPhase lastElement = observer.getPhases().get(observer.getPhases().size() - 1); + ObserverPhase newPhase = new ObserverPhase(lastElement.getTickOffset() + 4); + if (shift) newPhase.setTickOffset(newPhase.getTickOffset() + 5); + scroll += 2; + observer.add(newPhase); + SimulatorWatcher.update(simulator); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java new file mode 100644 index 00000000..f7925c34 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverPhaseSettingsGui.java @@ -0,0 +1,172 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.gui; + +import de.steamwar.bausystem.features.simulator.SimulatorWatcher; +import de.steamwar.bausystem.features.simulator.data.Simulator; +import de.steamwar.bausystem.features.simulator.data.SimulatorPhase; +import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement; +import de.steamwar.bausystem.features.simulator.data.observer.ObserverPhase; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; +import de.steamwar.core.Core; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui { + + private final ObserverElement observerElement; + private final ObserverPhase observer; + private final SimulatorBaseGui back; + + public SimulatorObserverPhaseSettingsGui(Player player, Simulator simulator, ObserverElement observerElement, ObserverPhase observer, SimulatorBaseGui back) { + super(player, simulator, 5 * 9); + this.observerElement = observerElement; + this.observer = observer; + this.back = back; + } + + @Override + public String title() { + return "Observer"; + } + + @Override + public void populate() { + if (!observerElement.getPhases().contains(observer)) { + back.open(); + return; + } + + // Back Arrow + inventory.setItem(0, new SWItem(Material.ARROW, "§eBack", clickType -> { + back.open(); + })); + + // Material Chooser + inventory.setItem(4, observerElement.toItem(player, clickType -> { + new SimulatorMaterialGui(player, simulator, observerElement::getMaterial, observerElement::setMaterial, this).open(); + })); + + // Delete + inventory.setItem(8, new SWItem(Material.BARRIER, "§eDelete", clickType -> { + observerElement.getPhases().remove(observer); + back.open(); + SimulatorWatcher.update(simulator); + })); + + int index = observerElement.getPhases().indexOf(observer); + int min; + if (index > 0) { + ObserverPhase previous = observerElement.getPhases().get(index - 1); + min = previous.getTickOffset() + 4; + } else { + min = 0; + } + + int max; + if (index < observerElement.getPhases().size() - 1) { + ObserverPhase next = observerElement.getPhases().get(index + 1); + max = next.getTickOffset() - 4; + } else { + max = Integer.MAX_VALUE - 4; + } + + //Tick Offset + int offset = observer.getTickOffset(); + inventory.setItem(10, SWItem.getDye(offset < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.setTickOffset(Math.min(max, offset + (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }); + + SWItem offsetItem = new SWItem(Material.REPEATER, "§eStart at§8:§7 " + offset, clickType -> { + new SimulatorAnvilGui<>(player, "Start at", offset + "", Integer::parseInt, integer -> { + if (integer < 0) return false; + observer.setTickOffset(Math.min(Math.max(integer, min), max)); + SimulatorWatcher.update(simulator); + return true; + }, this).setItem(Material.REPEATER).open(); + }); + offsetItem.getItemStack().setAmount(Math.max(1, Math.min(offset, 64))); + inventory.setItem(19, offsetItem); + + inventory.setItem(28, SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + observer.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }); + + //Order + int order = observer.getOrder(); + inventory.setItem(13, SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }); + + Material negativeNumbers = Material.getMaterial(Core.getVersion() >= 19 ? "RECOVERY_COMPASS" : "FIREWORK_STAR"); + SWItem orderItem = new SWItem(order >= 0 ? Material.COMPASS : negativeNumbers, "§eActivation Order§8:§7 " + order, clickType -> { + new SimulatorAnvilGui<>(player, "Activation Order", order + "", Integer::parseInt, integer -> { + if (integer < -SimulatorPhase.ORDER_LIMIT) return false; + if (integer > SimulatorPhase.ORDER_LIMIT) return false; + observer.setOrder(integer); + SimulatorWatcher.update(simulator); + return true; + }, this).setItem(order >= 0 ? Material.COMPASS : negativeNumbers).open(); + }); + orderItem.getItemStack().setAmount(Math.max(1, Math.min(Math.abs(order), 30))); + inventory.setItem(22, orderItem); + + inventory.setItem(31, SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + observer.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1))); + SimulatorWatcher.update(simulator); + }); + + // Update orientation + inventory.setItem(25, new SWItem(Material.SUNFLOWER, "§7", clickType -> { + })); + inventory.setItem(15, new SWItem(observer.getOrientation() == BlockFace.UP ? Material.LIME_CONCRETE : Material.GRAY_CONCRETE, "§eUp", clickType -> { + observer.setOrientation(BlockFace.UP); + SimulatorWatcher.update(simulator); + })); + inventory.setItem(33, new SWItem(observer.getOrientation() == BlockFace.DOWN ? Material.RED_CONCRETE : Material.GRAY_CONCRETE, "§eDown", clickType -> { + observer.setOrientation(BlockFace.DOWN); + SimulatorWatcher.update(simulator); + })); + inventory.setItem(16, new SWItem(observer.getOrientation() == BlockFace.NORTH ? Material.LIME_WOOL : Material.GRAY_WOOL, "§eNorth", clickType -> { + observer.setOrientation(BlockFace.NORTH); + SimulatorWatcher.update(simulator); + })); + inventory.setItem(34, new SWItem(observer.getOrientation() == BlockFace.SOUTH ? Material.RED_WOOL : Material.GRAY_WOOL, "§eSouth", clickType -> { + observer.setOrientation(BlockFace.SOUTH); + SimulatorWatcher.update(simulator); + })); + inventory.setItem(24, new SWItem(observer.getOrientation() == BlockFace.EAST ? Material.LIME_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eEast", clickType -> { + observer.setOrientation(BlockFace.EAST); + SimulatorWatcher.update(simulator); + })); + inventory.setItem(26, new SWItem(observer.getOrientation() == BlockFace.WEST ? Material.RED_STAINED_GLASS : Material.GRAY_STAINED_GLASS, "§eWest", clickType -> { + observer.setOrientation(BlockFace.WEST); + SimulatorWatcher.update(simulator); + })); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java new file mode 100644 index 00000000..8084c7b1 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/SimulatorObserverSettingsGui.java @@ -0,0 +1,142 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.bausystem.features.simulator.gui; + +import de.steamwar.bausystem.features.simulator.SimulatorWatcher; +import de.steamwar.bausystem.features.simulator.data.Simulator; +import de.steamwar.bausystem.features.simulator.data.observer.ObserverElement; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; +import de.steamwar.inventory.SWItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +public class SimulatorObserverSettingsGui extends SimulatorBaseGui { + + private final ObserverElement observer; + private final SimulatorBaseGui back; + + public SimulatorObserverSettingsGui(Player player, Simulator simulator, ObserverElement observer, SimulatorBaseGui back) { + super(player, simulator, 5 * 9); + this.observer = observer; + this.back = back; + } + + @Override + public String title() { + return "Observer"; + } + + @Override + public void populate() { + if (observer.getPhases().isEmpty()) { + back.open(); + return; + } + + // Back Arrow + inventory.setItem(0, new SWItem(Material.ARROW, "§eBack", clickType -> { + back.open(); + })); + + // Material Chooser + inventory.setItem(4, observer.toItem(player, clickType -> { + new SimulatorMaterialGui(player, simulator, observer::getMaterial, observer::setMaterial, this).open(); + })); + + // Base Tick + int baseTicks = observer.getBaseTick(); + inventory.setItem(9, SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.changeBaseTicks(clickType.isShiftClick() ? 5 : 1); + SimulatorWatcher.update(simulator); + }); + SWItem baseTick = new SWItem(Material.REPEATER, "§eTicks§8:§7 " + baseTicks, clickType -> { + new SimulatorAnvilGui<>(player, "Ticks", baseTicks + "", Integer::parseInt, integer -> { + if (integer < 0) return false; + observer.changeBaseTicks(integer - baseTicks); + SimulatorWatcher.update(simulator); + return true; + }, this).setItem(Material.REPEATER).open(); + }); + baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64))); + inventory.setItem(18, baseTick); + inventory.setItem(27, SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) { + observer.changeBaseTicks(-baseTicks); + } else { + observer.changeBaseTicks(clickType.isShiftClick() ? -5 : -1); + } + SimulatorWatcher.update(simulator); + }); + + //Pos X + inventory.setItem(15, SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.move(clickType.isShiftClick() ? 5 : 1, 0, 0); + SimulatorWatcher.update(simulator); + }); + inventory.setItem(24, new SWItem(Material.PAPER, "§eX§8:§7 " + observer.getPosition().getBlockX(), clickType -> { + new SimulatorAnvilGui<>(player, "X", observer.getPosition().getBlockX() + "", Integer::parseInt, i -> { + observer.getPosition().setX(i); + SimulatorWatcher.update(simulator); + return true; + }, this).open(); + })); + inventory.setItem(33, SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + observer.move(clickType.isShiftClick() ? -5 : -1, 0, 0); + SimulatorWatcher.update(simulator); + }); + + //Pos Y + inventory.setItem(16, SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.move(0, clickType.isShiftClick() ? 5 : 1, 0); + SimulatorWatcher.update(simulator); + }); + inventory.setItem(25, new SWItem(Material.PAPER, "§eY§8:§7 " + observer.getPosition().getBlockY(), clickType -> { + new SimulatorAnvilGui<>(player, "Y", observer.getPosition().getBlockY() + "", Integer::parseInt, i -> { + observer.getPosition().setY(i); + SimulatorWatcher.update(simulator); + return true; + }, this).open(); + })); + inventory.setItem(34, SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + observer.move(0, clickType.isShiftClick() ? -5 : -1, 0); + SimulatorWatcher.update(simulator); + }); + + //Pos Z + inventory.setItem(17, SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> { + observer.move(0, 0, clickType.isShiftClick() ? 5 : 1); + SimulatorWatcher.update(simulator); + }); + inventory.setItem(26, new SWItem(Material.PAPER, "§eZ§8:§7 " + observer.getPosition().getBlockZ(), clickType -> { + new SimulatorAnvilGui<>(player, "Z", observer.getPosition().getBlockZ() + "", Integer::parseInt, i -> { + observer.getPosition().setZ(i); + SimulatorWatcher.update(simulator); + return true; + }, this).open(); + })); + inventory.setItem(35, SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> { + observer.move(0, 0, clickType.isShiftClick() ? -5 : -1); + SimulatorWatcher.update(simulator); + }); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/SimFormatSimulatorLoader.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/SimFormatSimulatorLoader.java index 15af2e4a..218c89a4 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/SimFormatSimulatorLoader.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/storage/SimFormatSimulatorLoader.java @@ -23,6 +23,8 @@ 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.SimulatorPhase; +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; @@ -94,6 +96,10 @@ public class SimFormatSimulatorLoader implements SimulatorLoader { element = new RedstoneElement(position); phaseConstructor = RedstonePhase::new; break; + case "Observer": + element = new ObserverElement(position); + phaseConstructor = ObserverPhase::new; + break; default: element = null; phaseConstructor = null;