From 935be23238d6d9817faccbad3455052dabc522fb Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 20 Jul 2022 23:52:21 +0200 Subject: [PATCH] Add basic sim preview for 1.19 Signed-off-by: yoyosource --- .../features/simulator/FakeExplosion19.java | 165 ++++++++++++++++++ .../features/simulator/FakeTNT19.java | 164 +++++++++++++++++ .../simulator/SimulatorPreview19.java | 111 ++++++++++++ .../features/simulator/SimulatorPreview.java | 44 +++++ .../simulator/SimulatorPreviewStorage.java | 71 ++++++++ .../simulator/TNTSimulatorListener.java | 43 ++++- .../features/simulator/gui/TNTElementGUI.java | 7 +- .../simulator/gui/TNTGroupEditGUI.java | 9 +- .../simulator/gui/TNTSimulatorGui.java | 10 +- .../simulator/tnt/SimulatorElement.java | 2 + .../features/simulator/tnt/TNTElement.java | 12 ++ .../features/simulator/tnt/TNTGroup.java | 9 + .../features/tracer/show/Record.java | 20 ++- 13 files changed, 655 insertions(+), 12 deletions(-) create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeExplosion19.java create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/simulator/FakeTNT19.java create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/simulator/SimulatorPreview19.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreview.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/SimulatorPreviewStorage.java 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 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) {