diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java index de0c4b74..bf329b3b 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCommand.java @@ -76,7 +76,7 @@ public class SimulatorCommand extends SWCommand { @Register(value = "start", description = "SIMULATOR_START_HELP") public void start(@Validator Player p, @ErrorMessage("SIMULATOR_NOT_EXISTS") Simulator simulator) { - SimulatorExecutor.run(simulator); + SimulatorExecutor.run(simulator, () -> {}); } @Register(value = "rename", description = "SIMULATOR_RENAME_HELP") 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 index de9dae3f..f9629c3d 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorCursor.java @@ -168,9 +168,19 @@ public class SimulatorCursor implements Listener { } return; } - Simulator simulator = SimulatorStorage.getSimulator(player); - SimulatorWatcher.show(simulator, player); + Simulator simulator = SimulatorStorage.getSimulator(player); + if (simulator != null && simulator.getStabGenerator() != null) { + removeCursor(player); + SimulatorWatcher.show(null, player); + SWUtils.sendToActionbar(player, "§cGenerating Stab"); + synchronized (calculating) { + calculating.remove(player); + } + return; + } + + SimulatorWatcher.show(simulator, player); List entities = SimulatorWatcher.getEntitiesOfSimulator(simulator); RayTraceUtils.RRayTraceResult rayTraceResult = RayTraceUtils.traceREntity(player, player.getLocation(), entities); if (rayTraceResult == null) { @@ -357,7 +367,7 @@ public class SimulatorCursor implements Listener { if (simulator == null) { return; } - SimulatorExecutor.run(simulator); + SimulatorExecutor.run(simulator, () -> {}); return; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java index 91b7a8e1..8dcb8321 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/data/Simulator.java @@ -20,6 +20,7 @@ package de.steamwar.bausystem.features.simulator.data; import de.steamwar.bausystem.features.simulator.execute.SimulatorAction; +import de.steamwar.bausystem.features.simulator.execute.SimulatorStabGenerator; import de.steamwar.inventory.InvCallback; import de.steamwar.inventory.SWItem; import lombok.Getter; @@ -30,13 +31,13 @@ import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.function.BiConsumer; @Getter @Setter @RequiredArgsConstructor public final class Simulator { + private SimulatorStabGenerator stabGenerator = null; private Material material = Material.BARREL; private final String name; private boolean autoTrace = false; diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java index 5c3d30e0..b052e4c8 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorExecutor.java @@ -46,7 +46,7 @@ public class SimulatorExecutor implements Listener { private static Map>> tickStartActions = new HashMap<>(); private static Map> tickEndActions = new HashMap<>(); - public static boolean run(Simulator simulator) { + public static boolean run(Simulator simulator, Runnable onEnd) { if (currentlyRunning.contains(simulator)) return false; currentlyRunning.add(simulator); @@ -69,7 +69,7 @@ public class SimulatorExecutor implements Listener { public void accept(World world) { currentlyRunning.remove(simulator); - if (simulator.isAutoTrace()) { + if (simulator.isAutoTrace() && onEnd == null) { simulator.getGroups() .stream() .map(SimulatorGroup::getElements) @@ -82,10 +82,12 @@ public class SimulatorExecutor implements Listener { TraceRecorder.instance.stopRecording(region); }); } + + onEnd.run(); } }); - if (simulator.isAutoTrace()) { + if (simulator.isAutoTrace() && onEnd == null) { simulator.getGroups() .stream() .map(SimulatorGroup::getElements) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java new file mode 100644 index 00000000..b874280f --- /dev/null +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/execute/SimulatorStabGenerator.java @@ -0,0 +1,386 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 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.execute; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.world.block.BlockTypes; +import de.steamwar.bausystem.BauSystem; +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.SimulatorPhase; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTElement; +import de.steamwar.bausystem.features.simulator.data.tnt.TNTPhase; +import de.steamwar.bausystem.features.tracer.TNTPoint; +import de.steamwar.bausystem.features.tracer.Trace; +import de.steamwar.bausystem.features.tracer.TraceManager; +import de.steamwar.bausystem.features.tracer.TraceRecorder; +import de.steamwar.bausystem.region.Point; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.region.flags.Flag; +import de.steamwar.bausystem.region.flags.flagvalues.ColorMode; +import de.steamwar.bausystem.region.utils.RegionExtensionType; +import de.steamwar.bausystem.region.utils.RegionType; +import de.steamwar.bausystem.utils.FlatteningWrapper; +import de.steamwar.bausystem.utils.PasteBuilder; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; +import de.steamwar.bausystem.utils.bossbar.BossBarService; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.util.Vector; + +import java.util.*; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.stream.Collectors; + +public class SimulatorStabGenerator implements Listener { + + // Lupfstichs sind noch nicht perfekt + // Schwenkstichs sidn noch nicht perfekt + + private static final int MAX_RECORDINGS = 5; + private static final Level LEVEL = Level.INFO; + private static final int TNT_INCREASE = 10; + private static final int MIN_BLOCK_TO_COUNT_AS_DEPTH = 20; + + private final Map> destroyedBlocksPerSlice = new HashMap<>(); + + @EventHandler + public void onEntityExplode(EntityExplodeEvent event) { + if (direction == null) return; + if (Region.getRegion(event.getEntity().getLocation()) == region) { + event.blockList().forEach(block -> { + if (!region.inRegion(block.getLocation(), RegionType.TESTBLOCK, RegionExtensionType.EXTENSION)) return; + int component = direction.component.apply(block.getLocation().toVector()); + destroyedBlocksPerSlice.computeIfAbsent(component, __ -> new HashSet<>()) + .add(block.getLocation()); + }); + } + } + + private final Region region; + private final Simulator simulator; + private final TNTElement tntElement; + private final List phases; + private final int depthLimit; + + private Clipboard clipboard; + private boolean cancel = false; + + private Direction direction = null; + + public SimulatorStabGenerator(Region region, Simulator simulator, TNTElement tntElement, int depthLimit) { + this.region = region; + this.simulator = simulator; + this.tntElement = tntElement; + this.phases = tntElement.getPhases(); + this.depthLimit = depthLimit; + + setup(); + } + + private void setup() { + TNTPhase tntPhase = simulator.getGroups().stream() + .map(SimulatorGroup::getElements) + .flatMap(List::stream) + .filter(TNTElement.class::isInstance) + .map(TNTElement.class::cast) + .filter(tntElement -> this.tntElement != tntElement) + .map(tntElement -> tntElement.getPhases().stream().max(Comparator.comparingInt(TNTPhase::getTickOffset))) + .filter(Optional::isPresent) + .map(Optional::get) + .filter(phase -> phase != phases.get(0)) + .max(Comparator.comparingInt(TNTPhase::getTickOffset)) + .orElse(null); + if (tntPhase == null) { + throw new SecurityException(""); + } + + TNTPhase phase = phases.get(0); + phases.clear(); + phases.add(phase); + phase.setCount(1); + phase.setTickOffset(tntPhase.getTickOffset()); + phase.setOrder(100); + + TraceRecorder.instance.stopRecording(region); + if (TraceRecorder.instance.isAutoTraceEnabledInRegion(region)) { + TraceRecorder.instance.removeAutoTraceRegion(region); + } + clipboard = FlatteningWrapper.impl.copy(region.getMinPointTestblockExtension(), region.getMaxPointTestblockExtension(), region.getTestBlockPoint()); + + getDirection(); + } + + private BlockVector3 toBlockVector3(Point point) { + return BlockVector3.at(point.getX(), point.getY(), point.getZ()); + } + + private void getDirection() { + try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) { + e.setBlocks((com.sk89q.worldedit.regions.Region) new CuboidRegion(toBlockVector3(region.getMinPointTestblockExtension()), toBlockVector3(region.getMaxPointTestblockExtension())), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock()); + } + + showBossbar(false); + + Trace trace = TraceRecorder.instance.startRecording(region); + SimulatorExecutor.run(simulator, () -> { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + TraceRecorder.instance.stopRecording(region); + calculateDirection(trace); + }, 20); + }); + } + + private void calculateDirection(Trace trace) { + long tickSinceStart = -1; + List points = null; + for (List current : trace.getHistories()) { + long ticks = current.get(0).getTicksSinceStart(); + if (points == null || ticks > tickSinceStart) { + tickSinceStart = ticks; + points = current; + } else if (ticks == tickSinceStart && points.get(0).getTntId() < current.get(0).getTntId()) { + points = current; + } + } + TraceManager.instance.remove(trace); + if (points == null) { + stop(); + return; + } + + TNTPoint current = points.getLast(); + Vector velocity = current.getVelocity(); + if (velocity.getX() < 0) velocity.setX(-velocity.getX()); + if (velocity.getY() < 0) velocity.setY(-velocity.getY()); + if (velocity.getZ() < 0) velocity.setZ(-velocity.getZ()); + if (velocity.getX() > velocity.getY() && velocity.getX() > velocity.getZ()) { + direction = Direction.X; + } else if (velocity.getY() > velocity.getX() && velocity.getY() > velocity.getZ()) { + direction = Direction.Y; + } else if (velocity.getZ() > velocity.getX() && velocity.getZ() > velocity.getY()) { + direction = Direction.Z; + } else { + stop(); + return; + } + + Bukkit.getLogger().log(LEVEL, "Direction: {0}", direction); + phases.getFirst().setOrder(SimulatorPhase.ORDER_LIMIT); + phases.getFirst().setCount(TNT_INCREASE); + destroyedBlocksPerSlice.clear(); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance()); + getStab(); + }, 20); + } + + private void getStab() { + try { + PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(clipboard); + PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider) + .color(region.getPlain(Flag.COLOR, ColorMode.class).getColor()); + region.reset(pasteBuilder, RegionType.TESTBLOCK, RegionExtensionType.EXTENSION); + } catch (SecurityException e) { + stop(); + throw e; + } + if (cancel) return; + + showBossbar(false); + + SimulatorExecutor.run(simulator, () -> { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::calculateStep, 20); + }); + } + + private int recordings = 0; + private List currentDepths = new ArrayList<>(); + private int lastDepth = 0; + private int currentDepth = 0; + + private void calculateStep() { + List>> locations = destroyedBlocksPerSlice.entrySet() + .stream() + .sorted(Comparator.comparingInt(Map.Entry::getKey)) + .collect(Collectors.toList()); + int depth = 0; + for (int i = 0; i < locations.size(); i++) { + if (i == 0 || i == locations.size() - 1) { + if (locations.get(i).getValue().size() > MIN_BLOCK_TO_COUNT_AS_DEPTH) { + depth++; + } + } else { + depth++; + } + } + + if (depth > 0) { + Bukkit.getLogger().log(LEVEL, "{0} {1} {2}", new Object[]{depth, destroyedBlocksPerSlice.size(), destroyedBlocksPerSlice.values().stream().map(Set::size).collect(Collectors.toList())}); + currentDepths.add(depth); + } + destroyedBlocksPerSlice.clear(); + + int maxDepth = currentDepths.stream().max(Integer::compareTo).orElse(0); + currentDepth = maxDepth; + + int countWithoutLast = 0; + for (int i = 0; i < phases.size() - 1; i++) { + countWithoutLast += phases.get(i).getCount(); + } + + TNTPhase lastPhase = phases.getLast(); + boolean moreTNTNeeded = maxDepth - countWithoutLast >= lastPhase.getCount() - 5; + if (!currentDepths.isEmpty() && moreTNTNeeded) { + Bukkit.getLogger().log(LEVEL, "Increasing tnt count by {0}", TNT_INCREASE); + lastPhase.setCount(lastPhase.getCount() + TNT_INCREASE); + recordings = 0; + currentDepths.clear(); + + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::getStab, 20); + return; + } + + if (recordings++ < MAX_RECORDINGS) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::getStab, 20); + return; + } + + recordings = 0; + if (currentDepths.isEmpty()) { + Bukkit.getLogger().log(LEVEL, "No dimension - Increasing tickOffset to: {0}", phases.getFirst().getTickOffset() + 1); + phases.getFirst().setTickOffset(phases.getFirst().getTickOffset() + 1); + phases.getFirst().setOrder(0); + if (phases.getFirst().getTickOffset() > 80) { + stop(); + } else { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::getStab, 20); + } + return; + } + + currentDepths.clear(); + + Bukkit.getLogger().log(LEVEL, "No more TNT needed on phase adjusting - {0} new depth; {1} current count", new Object[]{maxDepth - countWithoutLast, lastPhase.getCount()}); + lastPhase.setCount(maxDepth - countWithoutLast); + if (lastPhase.getCount() <= 0) { + Bukkit.getLogger().log(LEVEL, "Count was 0 or negative - removing last phase"); + phases.removeLast(); + } + + if (maxDepth > depthLimit) { + Bukkit.getLogger().log(LEVEL, "Depth is greater than {0} - finished", depthLimit); + stop(); + return; + } + if (maxDepth <= lastDepth) { + Bukkit.getLogger().log(LEVEL, "Depth is equal to last depth recorded {0} - finished", maxDepth); + stop(); + return; + } + lastDepth = maxDepth; + + Bukkit.getLogger().log(LEVEL, "Adding new phase in next tick"); + TNTPhase nextPhase = new TNTPhase(); + nextPhase.setCount(TNT_INCREASE); + nextPhase.setTickOffset(lastPhase.getTickOffset() + 1); + nextPhase.setXJump(lastPhase.isXJump()); + nextPhase.setYJump(lastPhase.isYJump()); + nextPhase.setZJump(lastPhase.isZJump()); + phases.add(nextPhase); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::getStab, 20); + } + + @AllArgsConstructor + private enum Direction { + X(Vector::getBlockX), + Y(Vector::getBlockY), + Z(Vector::getBlockZ); + + private final Function component; + } + + private void showBossbar(boolean finished) { + for (Player player : Bukkit.getOnlinePlayers()) { + BauSystemBossbar bossbar = BossBarService.instance.get(player, region, "simulator_stab_generator"); + bossbar.setColor(BarColor.GREEN); + bossbar.setStyle(BarStyle.SEGMENTED_10); + bossbar.setProgress(Math.min(currentDepth / (double) depthLimit, 1.0)); + StringBuilder st = new StringBuilder(); + + if (finished) { + st.append("§eFinished ").append(currentDepth).append("§8/§7").append(depthLimit); + } else if (direction == null) { + st.append("§eCalculating Stab Direction"); + } else { + st.append("§7Direction§7 §e" + direction); + st.append(" §e").append(currentDepth).append("§8/§7").append(depthLimit); + if (recordings > 0) { + st.append(" §7Retries§8:§e ").append(recordings).append("§8/§7").append(MAX_RECORDINGS); + } + } + + bossbar.setTitle(st.toString()); + } + } + + private void stop() { + simulator.setStabGenerator(null); + SimulatorWatcher.update(simulator); + HandlerList.unregisterAll(this); + + showBossbar(true); + new Thread(() -> { + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + for (Player player : Bukkit.getOnlinePlayers()) { + BossBarService.instance.remove(player, region, "simulator_stab_generator"); + } + } + }).start(); + } + + public void cancel() { + cancel = true; + simulator.setStabGenerator(null); + for (Player player : Bukkit.getOnlinePlayers()) { + BossBarService.instance.remove(player, region, "simulator_stab_generator"); + } + HandlerList.unregisterAll(this); + } +} 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 a9c178ce..3520720e 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 @@ -24,8 +24,11 @@ import de.steamwar.bausystem.features.simulator.data.Simulator; import de.steamwar.bausystem.features.simulator.data.SimulatorGroup; 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.SimulatorStabGenerator; +import de.steamwar.bausystem.features.simulator.gui.base.SimulatorAnvilGui; import de.steamwar.bausystem.features.simulator.gui.base.SimulatorBaseGui; import de.steamwar.bausystem.features.simulator.gui.base.SimulatorScrollGui; +import de.steamwar.bausystem.region.Region; import de.steamwar.inventory.SWItem; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -97,6 +100,14 @@ public class SimulatorTNTGui extends SimulatorScrollGui { tnt.setDisabled(!tnt.isDisabled()); SimulatorWatcher.update(simulator); })); + inventory.setItem(49, new SWItem(Material.CALIBRATED_SCULK_SENSOR, "§eCreate Stab", click -> { + new SimulatorAnvilGui<>(player, "Depth Limit", "", Integer::parseInt, depthLimit -> { + if (depthLimit <= 0) return false; + simulator.setStabGenerator(new SimulatorStabGenerator(Region.getRegion(player.getLocation()), simulator, tnt, depthLimit)); + SimulatorWatcher.update(simulator); + return true; + }, null).open(); + })); inventory.setItem(50, new SWItem(Material.CHEST, parent.getElements().size() == 1 ? "§eMake Group" : "§eAdd another TNT to Group", clickType -> { TNTElement tntElement = new TNTElement(tnt.getPosition().clone()); tntElement.add(new TNTPhase()); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java index 380dc618..e22c807a 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorAnvilGui.java @@ -44,7 +44,7 @@ public class SimulatorAnvilGui { if (error.get()) { anvilInv.open(); } else { - back.open(); + if (back != null) back.open(); } error.set(false); }, 0); diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java index 6fa35d4c..aeb4da13 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/base/SimulatorBaseGui.java @@ -22,7 +22,6 @@ package de.steamwar.bausystem.features.simulator.gui.base; import de.steamwar.bausystem.features.simulator.SimulatorWatcher; import de.steamwar.bausystem.features.simulator.data.Simulator; import de.steamwar.core.Core; -import de.steamwar.core.TrickyTrialsWrapper; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import org.bukkit.Bukkit; @@ -64,7 +63,11 @@ public abstract class SimulatorBaseGui { if (Core.getVersion() > 19) { player.getOpenInventory().setTitle(title()); } - populate(); + if (simulator != null && simulator.getStabGenerator() != null) { + populateStabGenerator(); + } else { + populate(); + } if (player.getOpenInventory().getTopInventory() == inv) { inventory.open(); SimulatorWatcher.watch(player, simulator, this::open); @@ -84,10 +87,21 @@ public abstract class SimulatorBaseGui { }); SimulatorWatcher.watch(player, simulator, this::open); - populate(); + if (simulator != null && simulator.getStabGenerator() != null) { + populateStabGenerator(); + } else { + populate(); + } inventory.open(); } + private void populateStabGenerator() { + inventory.setItem(22, new SWItem(Material.BARRIER, "§cCancel Stab Generator", click -> { + simulator.getStabGenerator().cancel(); + SimulatorWatcher.update(simulator); + })); + } + public boolean shouldOpen() { return true; } diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java index 6a0a2314..208b49e8 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java @@ -102,11 +102,14 @@ public class TraceRecorder implements Listener { * * @param region region to be recorded */ - public void startRecording(Region region) { - if (activeTraces.containsKey(region)) return; + public Trace startRecording(Region region) { + if (activeTraces.containsKey(region)) { + return activeTraces.get(region).getTrace(); + } TraceRecordingWrapper wrappedTrace = new TraceRecordingWrapper(region); activeTraces.put(region, wrappedTrace); + return wrappedTrace.getTrace(); } /**