From 90b33d2f5d36bba826279de0f7026ab4bf31a7e2 Mon Sep 17 00:00:00 2001 From: Pablete1234 Date: Mon, 19 Apr 2021 03:18:46 +0200 Subject: [PATCH] Add long render distance tnt Signed-off-by: Pablete1234 --- core/src/main/java/tc/oc/pgm/api/Modules.java | 2 + .../pgm/tntrender/TNTRenderMatchModule.java | 102 ++++++++++++++++++ .../java/tc/oc/pgm/util/nms/NMSHacks.java | 5 + 3 files changed, 109 insertions(+) create mode 100644 core/src/main/java/tc/oc/pgm/tntrender/TNTRenderMatchModule.java diff --git a/core/src/main/java/tc/oc/pgm/api/Modules.java b/core/src/main/java/tc/oc/pgm/api/Modules.java index b31a869763..54525c743c 100644 --- a/core/src/main/java/tc/oc/pgm/api/Modules.java +++ b/core/src/main/java/tc/oc/pgm/api/Modules.java @@ -112,6 +112,7 @@ import tc.oc.pgm.timelimit.TimeLimitModule; import tc.oc.pgm.tnt.TNTMatchModule; import tc.oc.pgm.tnt.TNTModule; +import tc.oc.pgm.tntrender.TNTRenderMatchModule; import tc.oc.pgm.tracker.TrackerMatchModule; import tc.oc.pgm.wool.WoolMatchModule; import tc.oc.pgm.wool.WoolModule; @@ -157,6 +158,7 @@ static void registerAll() { register(FireworkMatchModule.class, FireworkMatchModule::new); register(StatsMatchModule.class, StatsMatchModule::new); register(MapmakerMatchModule.class, MapmakerMatchModule::new); + register(TNTRenderMatchModule.class, TNTRenderMatchModule::new); // FIXME: Disabled due to lag - look into future optimization // register(ProjectileTrailMatchModule.class, ProjectileTrailMatchModule::new); diff --git a/core/src/main/java/tc/oc/pgm/tntrender/TNTRenderMatchModule.java b/core/src/main/java/tc/oc/pgm/tntrender/TNTRenderMatchModule.java new file mode 100644 index 0000000000..3a8767d2a7 --- /dev/null +++ b/core/src/main/java/tc/oc/pgm/tntrender/TNTRenderMatchModule.java @@ -0,0 +1,102 @@ +package tc.oc.pgm.tntrender; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ExplosionPrimeEvent; +import tc.oc.pgm.api.match.Match; +import tc.oc.pgm.api.match.MatchModule; +import tc.oc.pgm.api.match.MatchScope; +import tc.oc.pgm.api.player.MatchPlayer; +import tc.oc.pgm.util.nms.NMSHacks; + +public class TNTRenderMatchModule implements MatchModule, Listener { + + private static final double MAX_DISTANCE = Math.pow(64d, 2); + + private final Match match; + private final List entities; + + public TNTRenderMatchModule(Match match) { + this.match = match; + this.entities = new ArrayList<>(); + } + + @Override + public void enable() { + match + .getExecutor(MatchScope.LOADED) + .scheduleAtFixedRate( + () -> entities.removeIf(PrimedTnt::update), 0, 50, TimeUnit.MILLISECONDS); + } + + @EventHandler + public void onTntSpawn(ExplosionPrimeEvent event) { + if (event.getEntity() instanceof TNTPrimed) + entities.add(new PrimedTnt((TNTPrimed) event.getEntity())); + } + + @EventHandler + public void onTntExplode(EntityExplodeEvent event) { + if (!(event.getEntity() instanceof TNTPrimed)) return; + Location explosion = event.getLocation(); + for (MatchPlayer player : match.getPlayers()) { + if (explosion.distanceSquared(player.getBukkit().getLocation()) >= MAX_DISTANCE) + player + .getBukkit() + .spigot() + .playEffect(explosion, Effect.EXPLOSION_HUGE, 0, 0, 0f, 0f, 0f, 1f, 1, 256); + } + } + + private class PrimedTnt { + private final TNTPrimed entity; + private final Set viewers = new HashSet<>(); + private Location lastLocation, currentLocation; + private boolean moved = false; + + public PrimedTnt(TNTPrimed entity) { + this.entity = entity; + this.lastLocation = currentLocation = entity.getLocation().toBlockLocation(); + } + + public boolean update() { + if (entity.isDead()) { + for (MatchPlayer viewer : viewers) + NMSHacks.sendBlockChange(currentLocation, viewer.getBukkit(), null); + return true; + } + + this.lastLocation = currentLocation; + this.currentLocation = entity.getLocation().toBlockLocation(); + this.moved = !currentLocation.equals(lastLocation); + + for (MatchPlayer player : match.getPlayers()) { + updatePlayer(player); + } + return false; + } + + private void updatePlayer(MatchPlayer player) { + if (currentLocation.distanceSquared(player.getBukkit().getLocation()) >= MAX_DISTANCE) { + if (viewers.add(player)) { + NMSHacks.sendBlockChange(currentLocation, player.getBukkit(), Material.TNT); + } else if (moved) { + NMSHacks.sendBlockChange(lastLocation, player.getBukkit(), null); + NMSHacks.sendBlockChange(currentLocation, player.getBukkit(), Material.TNT); + } + } else if (viewers.remove(player)) { + NMSHacks.sendBlockChange(lastLocation, player.getBukkit(), null); + } + } + } +} diff --git a/util/src/main/java/tc/oc/pgm/util/nms/NMSHacks.java b/util/src/main/java/tc/oc/pgm/util/nms/NMSHacks.java index 3abd765d08..d52cc33466 100644 --- a/util/src/main/java/tc/oc/pgm/util/nms/NMSHacks.java +++ b/util/src/main/java/tc/oc/pgm/util/nms/NMSHacks.java @@ -1189,6 +1189,11 @@ static void updateChunkSnapshot(ChunkSnapshot snapshot, org.bukkit.block.BlockSt } } + static void sendBlockChange(Location loc, Player player, @Nullable Material material) { + if (material != null) player.sendBlockChange(loc, material, (byte) 0); + else player.sendBlockChange(loc, loc.getBlock().getType(), loc.getBlock().getData()); + } + interface FakeEntity { int entityId();