diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeExplosion19.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeExplosion19.java
new file mode 100644
index 00000000..f6bfbcbe
--- /dev/null
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeExplosion19.java
@@ -0,0 +1,165 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 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 com.google.common.collect.Maps;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+import net.minecraft.core.BlockPosition;
+import net.minecraft.util.RandomSource;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.level.Explosion;
+import net.minecraft.world.level.ExplosionDamageCalculator;
+import net.minecraft.world.level.World;
+import net.minecraft.world.level.gameevent.GameEvent;
+import net.minecraft.world.phys.Vec3D;
+import org.bukkit.craftbukkit.v1_19_R1.event.CraftEventFactory;
+
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+
+public class FakeExplosion19 extends Explosion {
+
+ private List fakeTNT19s;
+ private boolean c;
+ private Explosion.Effect d;
+ private RandomSource e;
+ private World f;
+ private double g;
+ private double h;
+ private double i;
+ @Nullable
+ public Entity j;
+ private float k;
+ private DamageSource l;
+ private ExplosionDamageCalculator m;
+ private ObjectArrayList n;
+ private Map o;
+ public boolean wasCanceled;
+
+ public FakeExplosion19(List fakeTNT19s, World world, @Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, double x, double y, double z, float power, boolean createFire, Explosion.Effect destructionType) {
+ super(world, entity, damageSource, behavior, x, y, z, power, createFire, destructionType);
+ this.fakeTNT19s = fakeTNT19s;
+ this.wasCanceled = false;
+ this.e = RandomSource.a();
+ this.n = new ObjectArrayList();
+ this.o = Maps.newHashMap();
+ this.f = world;
+ this.j = entity;
+ this.k = (float) Math.max((double) power, 0.0D);
+ this.g = x;
+ this.h = y;
+ this.i = z;
+ this.c = createFire;
+ this.d = destructionType;
+ this.l = damageSource == null ? DamageSource.a(this) : damageSource;
+ this.m = new ExplosionDamageCalculator();
+
+ }
+
+ private float getBlockDensity(Vec3D vec3d, Entity entity) {
+ return a(vec3d, entity);
+ }
+
+
+ @Override
+ public void a() {
+ if ((this.k) >= 0.1F) {
+ this.f.a(this.j, GameEvent.w, new Vec3D(this.g, this.h, this.i));
+ /*
+ Set set = Sets.newHashSet();
+
+ int i;
+ int j;
+ for (int k = 0; k < 16; ++k) {
+ for (i = 0; i < 16; ++i) {
+ for (j = 0; j < 16; ++j) {
+ if (k == 0 || k == 15 || i == 0 || i == 15 || j == 0 || j == 15) {
+ double d0 = (double) ((float) k / 15.0F * 2.0F - 1.0F);
+ double d1 = (double) ((float) i / 15.0F * 2.0F - 1.0F);
+ double d2 = (double) ((float) j / 15.0F * 2.0F - 1.0F);
+ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
+ d0 /= d3;
+ d1 /= d3;
+ d2 /= d3;
+ float f = this.k * (0.7F + this.f.w.i() * 0.6F);
+ double d4 = this.g;
+ double d5 = this.h;
+ double d6 = this.i;
+
+ for (float var21 = 0.3F; f > 0.0F; f -= 0.22500001F) {
+ BlockPosition blockposition = new BlockPosition(d4, d5, d6);
+ IBlockData iblockdata = this.f.a_(blockposition);
+ Fluid fluid = iblockdata.p();
+ if (!this.f.j(blockposition)) {
+ break;
+ }
+
+ Optional optional = this.m.a(this, this.f, blockposition, iblockdata, fluid);
+ if (optional.isPresent()) {
+ f -= ((Float) optional.get() + 0.3F) * 0.3F;
+ }
+
+ if (f > 0.0F && this.m.a(this, this.f, blockposition, iblockdata, f)) {
+ set.add(blockposition);
+ }
+
+ d4 += d0 * 0.30000001192092896D;
+ d5 += d1 * 0.30000001192092896D;
+ d6 += d2 * 0.30000001192092896D;
+ }
+ }
+ }
+ }
+ }
+
+ this.n.addAll(set);
+ */
+
+ float f2 = this.k * 2.0F;
+ Vec3D vec3d = new Vec3D(this.g, this.h, this.i);
+ for (int l1 = 0; l1 < fakeTNT19s.size(); ++l1) {
+ Entity entity = (Entity) fakeTNT19s.get(l1);
+ if (!entity.cF()) {
+ double d7 = Math.sqrt(entity.e(vec3d)) / (double) f2;
+ if (d7 <= 1.0D) {
+ double d8 = entity.dg() - this.g;
+ double d9 = entity.di() - this.h;
+ double d10 = entity.dm() - this.i;
+ double d11 = Math.sqrt(d8 * d8 + d9 * d9 + d10 * d10);
+ if (d11 != 0.0D) {
+ d8 /= d11;
+ d9 /= d11;
+ d10 /= d11;
+ double d12 = (double) this.getBlockDensity(vec3d, entity);
+
+ double d13 = (1.0D - d7) * d12;
+ entity.lastDamageCancelled = false;
+ CraftEventFactory.entityDamage = null;
+ entity.f(entity.de().b(d8 * d13, d9 * d13, d10 * d13));
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeTNT19.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeTNT19.java
new file mode 100644
index 00000000..90347f64
--- /dev/null
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeTNT19.java
@@ -0,0 +1,164 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 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 net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity;
+import net.minecraft.network.syncher.DataWatcher;
+import net.minecraft.network.syncher.DataWatcherObject;
+import net.minecraft.network.syncher.DataWatcherRegistry;
+import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.entity.*;
+import net.minecraft.world.entity.item.EntityTNTPrimed;
+import net.minecraft.world.level.Explosion;
+import net.minecraft.world.level.ExplosionDamageCalculator;
+import net.minecraft.world.level.World;
+import org.bukkit.entity.Explosive;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+
+import javax.annotation.Nullable;
+import java.util.List;
+
+public class FakeTNT19 extends EntityTNTPrimed {
+ private static final DataWatcherObject b;
+ private static final int c = 80;
+ private List fakeTNT19s;
+ @Nullable
+ public EntityLiving d;
+ public float yield;
+ public boolean isIncendiary;
+ public int offset = 0;
+
+ public FakeTNT19(List fakeTNT19s, EntityTypes extends EntityTNTPrimed> type, World world) {
+ super(type, world);
+ this.fakeTNT19s = fakeTNT19s;
+ this.yield = 4.0F;
+ this.isIncendiary = false;
+ super.q = true;
+ }
+
+ public FakeTNT19(List fakeTNT19s, World world, double x, double y, double z, int tickoffset) {
+ this(fakeTNT19s, EntityTypes.av, world);
+ this.e(x, y, z);
+ double d3 = world.w.j() * 6.2831854820251465D;
+ this.n(-Math.sin(d3) * 0.02D, 0.20000000298023224D, -Math.cos(d3) * 0.02D);
+ this.a(tickoffset);
+ super.t = x;
+ super.u = y;
+ super.v = z;
+ this.d = null;
+ this.offset = tickoffset;
+ }
+
+ protected void a_() {
+ super.Y.a(b, 80);
+ }
+
+ protected MovementEmission aO() {
+ return MovementEmission.a;
+ }
+
+ public boolean bl() {
+ return !this.du();
+ }
+
+ @Override
+ public void k() {
+ if (!this.aN()) {
+ this.f(this.de().b(0.0D, -0.04D, 0.0D));
+ }
+
+ this.a(EnumMoveType.a, this.de());
+ this.f(this.de().a(0.98D));
+ if (super.y) {
+ this.f(this.de().d(0.7D, -0.5D, 0.7D));
+ }
+
+ int i = this.i() - 1;
+ this.a(i);
+ if (i <= 0) {
+ if (!super.s.y) {
+ this.j1();
+ }
+
+ this.ah();
+ } else {
+ this.aZ();
+ }
+ }
+
+ private void j1() {
+ ExplosionPrimeEvent event = new ExplosionPrimeEvent((Explosive) this.getBukkitEntity());
+ super.s.getCraftServer().getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ this.a(this, this.dg(), this.e(0.0625D), this.dm(), event.getRadius(), event.getFire(), Explosion.Effect.b);
+ }
+ }
+
+ public FakeExplosion19 a(@Nullable Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.Effect destructionType) {
+ return this.a(entity, (DamageSource) null, (ExplosionDamageCalculator) null, x, y, z, power, createFire, destructionType);
+ }
+
+ public FakeExplosion19 a(@Nullable Entity entity, @Nullable DamageSource damageSource, @Nullable ExplosionDamageCalculator behavior, double x, double y, double z, float power, boolean createFire, Explosion.Effect destructionType) {
+ FakeExplosion19 explosion = new FakeExplosion19(fakeTNT19s, SimulatorPreview19.WORLD, entity, damageSource, behavior, x, y, z, power, createFire, destructionType);
+ explosion.a();
+ // explosion.a(true);
+ return explosion;
+ }
+
+
+ protected void b(NBTTagCompound nbt) {
+ nbt.a("Fuse", (short) this.i());
+ }
+
+ protected void a(NBTTagCompound nbt) {
+ this.a(nbt.g("Fuse"));
+ }
+
+ @Nullable
+ public EntityLiving h() {
+ return this.d;
+ }
+
+ protected float a(EntityPose pose, EntitySize dimensions) {
+ return 0.15F;
+ }
+
+ public void a(int fuse) {
+ super.Y.b(b, fuse);
+ }
+
+ public int i() {
+ return (Integer) super.Y.a(b);
+ }
+
+ public Packet> S() {
+ return new PacketPlayOutSpawnEntity(this);
+ }
+
+ public boolean cs() {
+ return super.cs();
+ }
+
+ static {
+ b = DataWatcher.a(EntityTNTPrimed.class, DataWatcherRegistry.b);
+ }
+}
diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/SimulatorPreview19.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/SimulatorPreview19.java
new file mode 100644
index 00000000..b8cdf8a6
--- /dev/null
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/SimulatorPreview19.java
@@ -0,0 +1,111 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 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.features.simulator.tnt.SimulatorElement;
+import de.steamwar.bausystem.features.tracer.show.Record;
+import de.steamwar.bausystem.shared.Pair;
+import net.minecraft.world.level.World;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
+import org.bukkit.entity.TNTPrimed;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+public class SimulatorPreview19 implements SimulatorPreview {
+
+ public static final World WORLD = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle();
+
+ @Override
+ public Record simulate(TNTSimulator tntSimulator) {
+ Map>>> result = new HashMap<>();
+ for (SimulatorElement element : tntSimulator.getTntElementList()) {
+ element.locations(result);
+ }
+
+ AtomicInteger maxTick = new AtomicInteger(0);
+ Map>>> toSpawn = new HashMap<>();
+ result.forEach((integer, integerSetMap) -> {
+ List>>> internal = new ArrayList<>();
+ integerSetMap.forEach((integer1, pairs) -> {
+ internal.add(new Pair<>(integer1, pairs));
+ });
+ internal.sort(Comparator.comparingInt(Pair::getKey));
+
+ toSpawn.put(integer, internal.stream().map(Pair::getValue).map(ArrayList::new).peek(Collections::shuffle).collect(Collectors.toList()));
+
+ if (maxTick.get() < integer) {
+ maxTick.set(integer);
+ }
+ });
+
+ List fakeTNT19s = new ArrayList<>();
+ Record record = new Record(false);
+ Map tntRecords = new HashMap<>();
+
+ int maxTickToCalc = maxTick.get() + 160;
+ for (int tick = 0; tick < maxTickToCalc; tick++) {
+ List>> toSpawnInTick = toSpawn.get(tick);
+ try {
+ if (toSpawnInTick == null) continue;
+ toSpawnInTick.forEach(pairs -> {
+ AtomicBoolean hasSomeLeft = new AtomicBoolean(true);
+ while(hasSomeLeft.get()) {
+ hasSomeLeft.set(false);
+ pairs.forEach(pair -> {
+ if (pair.getValue() > 0) {
+ hasSomeLeft.set(true);
+ SimulatorPreview.SimulatorPreviewTNTData previewTNTData = pair.getKey();
+ FakeTNT19 fakeTNT19 = new FakeTNT19(fakeTNT19s, WORLD, previewTNTData.getX(), previewTNTData.getY(), previewTNTData.getZ(), previewTNTData.getFuseTicks());
+ TNTPrimed tntPrimed = (TNTPrimed) fakeTNT19.getBukkitEntity();
+ if (!previewTNTData.isXVelocity()) tntPrimed.setVelocity(tntPrimed.getVelocity().setX(0));
+ if (!previewTNTData.isYVelocity()) tntPrimed.setVelocity(tntPrimed.getVelocity().setY(0));
+ if (!previewTNTData.isZVelocity()) tntPrimed.setVelocity(tntPrimed.getVelocity().setZ(0));
+ fakeTNT19s.add(fakeTNT19);
+ pair.setValue(pair.getValue() - 1);
+ }
+ });
+ }
+ });
+ } finally {
+ calculateTick(fakeTNT19s, record, tntRecords);
+ }
+ }
+ return record;
+ }
+
+ private void calculateTick(List fakeTNT19s, Record record, Map tntRecords) {
+ Iterator iterator = fakeTNT19s.iterator();
+ while (iterator.hasNext()) {
+ FakeTNT19 fakeTNT19 = iterator.next();
+ fakeTNT19.k();
+ TNTPrimed tntPrimed = ((TNTPrimed) (fakeTNT19.getBukkitEntity()));
+ if (tntPrimed.getFuseTicks() <= 0) {
+ tntRecords.computeIfAbsent(fakeTNT19, ignore -> record.spawn()).explode(tntPrimed);
+ iterator.remove();
+ } else {
+ tntRecords.computeIfAbsent(fakeTNT19, ignore -> record.spawn()).explode(tntPrimed);
+ }
+ }
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreview.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreview.java
new file mode 100644
index 00000000..422bb075
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreview.java
@@ -0,0 +1,44 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 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.features.tracer.show.Record;
+import de.steamwar.core.VersionDependent;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+public interface SimulatorPreview {
+ SimulatorPreview impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
+
+ @Data
+ @AllArgsConstructor
+ class SimulatorPreviewTNTData {
+ private double x;
+ private double y;
+ private double z;
+ private int fuseTicks;
+ private boolean xVelocity;
+ private boolean yVelocity;
+ private boolean zVelocity;
+ }
+
+ Record simulate(TNTSimulator tntSimulator);
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreviewStorage.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreviewStorage.java
new file mode 100644
index 00000000..daf831bc
--- /dev/null
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreviewStorage.java
@@ -0,0 +1,71 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 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.features.tracer.TNTPosition;
+import de.steamwar.bausystem.features.tracer.show.Record;
+import de.steamwar.bausystem.features.tracer.show.ShowModeParameter;
+import de.steamwar.bausystem.features.tracer.show.mode.TraceEntityShowMode;
+import de.steamwar.bausystem.shared.ShowMode;
+import lombok.experimental.UtilityClass;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+@UtilityClass
+public class SimulatorPreviewStorage {
+ private Map previews = new HashMap<>();
+ private Map> showModes = new HashMap<>();
+
+ public void show(Player player, TNTSimulator tntSimulator) {
+ hide(player);
+
+ Record record = previews.computeIfAbsent(tntSimulator, SimulatorPreview.impl::simulate);
+ ShowModeParameter showModeParameter = new ShowModeParameter();
+ showModeParameter.setInterpolate_XZ(true);
+ showModeParameter.setInterpolate_Y(true);
+ TraceEntityShowMode showMode = new TraceEntityShowMode(player, showModeParameter);
+ record.showAll(showMode);
+ showModes.put(player, showMode);
+ }
+
+ public void hide(Player player) {
+ if (showModes.containsKey(player)) {
+ showModes.get(player).hide();
+ showModes.remove(player);
+ }
+ }
+
+ public void recalculate(TNTSimulator tntSimulator) {
+ previews.remove(tntSimulator);
+ new HashSet<>(showModes.keySet()).forEach(player -> {
+ TNTSimulator simulator = SimulatorStorage.getSimulator(player.getInventory().getItemInOffHand());
+ if (simulator == tntSimulator) {
+ show(player, simulator);
+ }
+ });
+ }
+
+ public void recalculateAll() {
+ new HashSet<>(previews.keySet()).forEach(SimulatorPreviewStorage::recalculate);
+ }
+}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java
index f464063b..1c010766 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TNTSimulatorListener.java
@@ -22,9 +22,16 @@ package de.steamwar.bausystem.features.simulator;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.Permission;
import de.steamwar.bausystem.features.simulator.gui.SimulatorSelectionGUI;
+import de.steamwar.bausystem.features.tracer.TNTPosition;
+import de.steamwar.bausystem.features.tracer.show.Record;
+import de.steamwar.bausystem.features.tracer.show.ShowModeParameter;
+import de.steamwar.bausystem.features.tracer.show.mode.TraceEntityShowMode;
import de.steamwar.bausystem.linkage.LinkageType;
import de.steamwar.bausystem.linkage.Linked;
+import de.steamwar.bausystem.shared.Pair;
+import de.steamwar.bausystem.shared.ShowMode;
import de.steamwar.bausystem.utils.ItemUtils;
+import org.bukkit.Bukkit;
import org.bukkit.FluidCollisionMode;
import org.bukkit.GameMode;
import org.bukkit.Location;
@@ -32,10 +39,9 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerDropItemEvent;
-import org.bukkit.event.player.PlayerInteractEvent;
-import org.bukkit.event.player.PlayerItemHeldEvent;
-import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.player.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.util.BoundingBox;
@@ -124,6 +130,35 @@ public class TNTSimulatorListener implements Listener {
SimulatorCursor.show(player, simulator, trace(player, location, simulator));
}
+ @EventHandler
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ SimulatorCursor.hide(event.getPlayer(), null);
+ SimulatorStorage.getSimulatorNames().forEach(s -> {
+ SimulatorStorage.getSimulator(s).remove(event.getPlayer());
+ });
+ SimulatorPreviewStorage.hide(event.getPlayer());
+ }
+
+ @EventHandler
+ public void onPlayerSwapHandItems(PlayerSwapHandItemsEvent event) {
+ TNTSimulator tntSimulator = SimulatorStorage.getSimulator(event.getOffHandItem());
+ if (tntSimulator == null) {
+ SimulatorPreviewStorage.hide(event.getPlayer());
+ return;
+ }
+ SimulatorPreviewStorage.show(event.getPlayer(), tntSimulator);
+ }
+
+ @EventHandler
+ public void onBlockPlace(BlockPlaceEvent event) {
+ SimulatorPreviewStorage.recalculateAll();
+ }
+
+ @EventHandler
+ public void onBlockBreak(BlockBreakEvent event) {
+ Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), SimulatorPreviewStorage::recalculateAll, 1);
+ }
+
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!ItemUtils.isItem(event.getItem(), "simulator")) {
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTElementGUI.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTElementGUI.java
index 3a788410..d1f490c2 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTElementGUI.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTElementGUI.java
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.OrderUtils;
+import de.steamwar.bausystem.features.simulator.SimulatorPreviewStorage;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.TNTSimulator;
import de.steamwar.bausystem.features.simulator.gui.components.ChangeMaterial;
@@ -60,6 +61,7 @@ public class TNTElementGUI {
inv.setItem(36, new SWItem(Material.ARROW, BauSystem.MESSAGE.parse("SIMULATOR_BACK", player), clickType -> back.run()));
}
+ TNTSimulator tntSimulator = SimulatorStorage.getSimulator(player);
Runnable editObserver = () -> {
List locationLore = new ArrayList<>();
locationLore.add("");
@@ -97,7 +99,10 @@ public class TNTElementGUI {
};
editObserver.run();
tntElement.register(editObserver, player::closeInventory);
- inv.addCloseRunnable(() -> tntElement.unregister(editObserver));
+ inv.addCloseRunnable(() -> {
+ tntElement.unregister(editObserver);
+ SimulatorPreviewStorage.recalculate(tntSimulator);
+ });
inv.open();
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTGroupEditGUI.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTGroupEditGUI.java
index 0b061fd1..949bcc61 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTGroupEditGUI.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTGroupEditGUI.java
@@ -20,6 +20,7 @@
package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.features.simulator.SimulatorPreviewStorage;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.TNTSimulator;
import de.steamwar.bausystem.features.simulator.gui.components.ChangeMaterial;
@@ -59,9 +60,8 @@ public class TNTGroupEditGUI {
List minusOneFiveShiftLore = Arrays.asList(BauSystem.MESSAGE.parse("SIMULATOR_MINUS_FIVE_SHIFT", player));
List lore = Arrays.asList(BauSystem.MESSAGE.parse("SIMULATOR_TNT_SPAWN_LORE", player));
+ TNTSimulator tntSimulator = SimulatorStorage.getSimulator(player);
Runnable editObserver = () -> {
- TNTSimulator tntSimulator = SimulatorStorage.getSimulator(player);
-
ChangePosition.show(inv, player, tntSimulator, tntGroup, tntGroup::getPosition, UnaryOperator.identity(), UnaryOperator.identity(), UnaryOperator.identity(), () -> open(player, tntGroup, back));
ChangeMaterial.show(inv, player, 14, tntGroup, Material.BARREL, () -> open(player, tntGroup, back));
Disabled.show(inv, player, 32, tntSimulator, tntGroup);
@@ -85,7 +85,10 @@ public class TNTGroupEditGUI {
};
editObserver.run();
tntGroup.register(editObserver, player::closeInventory);
- inv.addCloseRunnable(() -> tntGroup.unregister(editObserver));
+ inv.addCloseRunnable(() -> {
+ tntGroup.unregister(editObserver);
+ SimulatorPreviewStorage.recalculate(tntSimulator);
+ });
inv.open();
}
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTSimulatorGui.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTSimulatorGui.java
index 7cb5d381..7bb551b8 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTSimulatorGui.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/gui/TNTSimulatorGui.java
@@ -21,6 +21,7 @@ package de.steamwar.bausystem.features.simulator.gui;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.configplayer.Config;
+import de.steamwar.bausystem.features.simulator.SimulatorPreviewStorage;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.TNTSimulator;
import de.steamwar.bausystem.features.simulator.tnt.SimulatorElement;
@@ -110,7 +111,14 @@ public class TNTSimulatorGui {
};
editObserver.run();
currentTntGroup.register(editObserver, player::closeInventory);
- inv.addCloseRunnable(() -> currentTntGroup.unregister(editObserver));
+ inv.addCloseRunnable(() -> {
+ currentTntGroup.unregister(editObserver);
+ SimulatorPreviewStorage.recalculate(currentTntSimulator);
+ });
+ } else {
+ inv.addCloseCallback(clickType -> {
+ SimulatorPreviewStorage.recalculate(currentTntSimulator);
+ });
}
if (currentTntSimulator != null || currentTntGroup != null) {
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/SimulatorElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/SimulatorElement.java
index 10ce5cd2..c4c48e4e 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/SimulatorElement.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/SimulatorElement.java
@@ -19,6 +19,7 @@
package de.steamwar.bausystem.features.simulator.tnt;
+import de.steamwar.bausystem.features.simulator.SimulatorPreview;
import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.Pair;
@@ -50,6 +51,7 @@ public interface SimulatorElement {
SWItem menu(Player p);
boolean locations(Map>>> result, Region region, Location location); // Ticks to subtick order to spawning runnable to count of activations
+ void locations(Map>>> result);
int tntCount();
int tick();
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTElement.java
index 7e122fff..5806b2f0 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTElement.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTElement.java
@@ -22,6 +22,7 @@ package de.steamwar.bausystem.features.simulator.tnt;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.AbstractSimulatorEntity;
import de.steamwar.bausystem.features.simulator.OrderUtils;
+import de.steamwar.bausystem.features.simulator.SimulatorPreview;
import de.steamwar.bausystem.features.simulator.SimulatorStorage;
import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode;
import de.steamwar.bausystem.region.Region;
@@ -198,6 +199,17 @@ public class TNTElement implements SimulatorElement {
return false;
}
+ @Override
+ public void locations(Map>>> result) {
+ if (disabled) return;
+ Location location = getPosition().toLocation(SimulatorStorage.WORLD);
+ result.computeIfAbsent(getTickOffset(), ignore -> new HashMap<>())
+ .computeIfAbsent(OrderUtils.order(order), ignore -> new HashSet<>())
+ .add(new Pair<>(
+ new SimulatorPreview.SimulatorPreviewTNTData(location.getX(), location.getY(), location.getZ(), fuseTicks, xVelocity, yVelocity, zVelocity),
+ count));
+ }
+
@Override
public int tntCount() {
return disabled ? 0 : count;
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTGroup.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTGroup.java
index 47254fee..4b75fef4 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTGroup.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/tnt/TNTGroup.java
@@ -20,6 +20,7 @@
package de.steamwar.bausystem.features.simulator.tnt;
import de.steamwar.bausystem.BauSystem;
+import de.steamwar.bausystem.features.simulator.SimulatorPreview;
import de.steamwar.bausystem.features.simulator.show.SimulatorEntityShowMode;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.shared.Pair;
@@ -151,6 +152,14 @@ public class TNTGroup implements SimulatorElement {
return false;
}
+ @Override
+ public void locations(Map>>> result) {
+ if (disabled) return;
+ for (TNTElement element : elements) {
+ element.locations(result);
+ }
+ }
+
@Override
public int tntCount() {
if (disabled) return 0;
diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java
index d76f4441..8ed2061b 100644
--- a/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java
+++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/show/Record.java
@@ -23,6 +23,7 @@ import de.steamwar.bausystem.features.tpslimit.TPSUtils;
import de.steamwar.bausystem.features.tracer.TNTPosition;
import de.steamwar.bausystem.shared.ShowMode;
import lombok.Getter;
+import lombok.RequiredArgsConstructor;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.util.Vector;
@@ -38,6 +39,8 @@ public class Record {
private final long startTime = TPSUtils.currentTick.get();
private final List tnt = new ArrayList<>();
+ private final boolean trace;
+
public int size() {
return tnt.size();
}
@@ -49,11 +52,18 @@ public class Record {
/* The following methods should only be called by a recorder */
public Record() {
- StoredRecords.add(this);
+ this(true);
+ }
+
+ public Record(boolean trace) {
+ if (trace) {
+ StoredRecords.add(this);
+ }
+ this.trace = trace;
}
public TNTRecord spawn() {
- TNTRecord record = new TNTRecord();
+ TNTRecord record = new TNTRecord(trace);
tnt.add(record);
return record;
}
@@ -74,10 +84,12 @@ public class Record {
}
@Getter
+ @RequiredArgsConstructor
public static class TNTRecord {
private final long id = idNumber++;
private final List positions = new ArrayList<>(41);
+ private final boolean trace;
public void showAll(ShowMode mode) {
for (TNTPosition position : positions)
@@ -116,7 +128,9 @@ public class Record {
position = new TNTPosition(this, tntPrimed, positions.get(positions.size() - 1).getLocation(), tntPrimed.getVelocity(), velocitySupplier, exploded);
}
positions.add(position);
- TraceShowManager.show(position);
+ if (trace) {
+ TraceShowManager.show(position);
+ }
}
public void explode(TNTPrimed tntPrimed) {