From 8f54fa1ef0196062dac543c89aa989d7f19eb88c Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sun, 27 Aug 2023 20:48:45 +0200 Subject: [PATCH] Update code Signed-off-by: yoyosource --- .../simulator/AxisMovementLimiter.java | 2 +- .../features/simulator/Explosion.java | 195 ++++++++++++++---- .../features/simulator/Simulator19.java | 37 ++-- .../bausystem/features/simulator/TNT.java | 3 +- 4 files changed, 172 insertions(+), 65 deletions(-) diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java index 561af19c..7aeb4e06 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java @@ -103,7 +103,7 @@ public class AxisMovementLimiter { Double collision = null; for (Vector vector : vectors) { - VoxelShape voxelShape = Simulator19.getVoxelShape(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + VoxelShape voxelShape = Simulator19.getVoxelShape(vector); for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { boundingBox = boundingBox.clone().shift(vector); boolean collides = boundingBox.overlaps(movementBoundingBox); diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Explosion.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Explosion.java index 64d20126..8cd01ff1 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Explosion.java +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Explosion.java @@ -19,17 +19,36 @@ package de.steamwar.bausystem.features.simulator; +import org.bukkit.Material; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; import org.bukkit.util.Vector; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; +import java.util.*; public class Explosion { + private static final double[] FACE_BLOCKS = new double[(16 * 16 * 2 + 14 * 16 * 2 + 14 * 14 * 2) * 3]; + + static { + int index = 0; + for (int x = 0; x < 16; ++x) { + for (int y = 0; y < 16; ++y) { + for (int z = 0; z < 16; ++z) { + if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z == 15) { + double dX = x / 15.0F * 2.0F - 1.0F; + double dY = y / 15.0F * 2.0F - 1.0F; + double dZ = z / 15.0F * 2.0F - 1.0F; + double length = Math.sqrt(dX * dX + dY * dY + dZ * dZ); + FACE_BLOCKS[index++] = dX / length; + FACE_BLOCKS[index++] = dY / length; + FACE_BLOCKS[index++] = dZ / length; + } + } + } + } + } + private static final Random RANDOM = new Random(); private static final float POWER = 4.0F; @@ -50,53 +69,141 @@ public class Explosion { public void calculate() { Set affectedBlocks = new HashSet<>(); - for (int i = 0; i < 16; ++i) { - for (int j = 0; j < 16; ++j) { - for (int k = 0; k < 16; ++k) { - if (i == 0 || i == 15 || j == 0 || j == 15 || k == 0 || k == 15) { - double d = i / 15.0F * 2.0F - 1.0F; - double e = j / 15.0F * 2.0F - 1.0F; - double f = k / 15.0F * 2.0F - 1.0F; - double g = Math.sqrt(d * d + e * e + f * f); - d /= g; - e /= g; - f /= g; + for (int i = 0; i < FACE_BLOCKS.length; i += 3) { + double d = FACE_BLOCKS[i + 0]; + double e = FACE_BLOCKS[i + 1]; + double f = FACE_BLOCKS[i + 2]; - float h = POWER * (0.7F + RANDOM.nextFloat() * 0.6F); - double m = x; - double n = y; - double o = z; + float h = POWER * (0.7F + RANDOM.nextFloat() * 0.6F); + double m = x; + double n = y; + double o = z; - for (; h > 0.0F; h -= 0.22500001F) { - int x = TNT.floor(m); - int y = TNT.floor(n); - int z = TNT.floor(o); + for (; h > 0.0F; h -= 0.22500001F) { + int x = TNT.floor(m); + int y = TNT.floor(n); + int z = TNT.floor(o); - BlockData blockData = Simulator19.getBlockData(x, y, z); - if (blockData != null) { - h -= (blockData.getMaterial().getBlastResistance() + 0.3F) * 0.3F; - } - if (blockData instanceof Waterlogged) { - Waterlogged waterlogged = (Waterlogged) blockData; - if (waterlogged.isWaterlogged()) { - h = 0.0F; - } - } - - if (h > 0.0F) { - affectedBlocks.add(new Vector(x, y, z)); - } - - m += d * 0.30000001192092896; - n += e * 0.30000001192092896; - o += f * 0.30000001192092896; - } + BlockData blockData = Simulator19.getBlockData(x, y, z); + if (blockData != null) { + h -= (blockData.getMaterial().getBlastResistance() + 0.3F) * 0.3F; + } + if (blockData instanceof Waterlogged) { + Waterlogged waterlogged = (Waterlogged) blockData; + if (waterlogged.isWaterlogged()) { + h = 0.0F; } } + + if (h > 0.0F) { + affectedBlocks.add(new Vector(x, y, z)); + } + + m += d * 0.30000001192092896; + n += e * 0.30000001192092896; + o += f * 0.30000001192092896; + } + } + affectedBlocks.forEach(Simulator19::clearBlock); + + float q = POWER * 2.0F; + int k = floor(x - q - 1.0D); + int l = floor(x + q + 1.0D); + int r = floor(y - q - 1.0D); + int s = floor(y + q + 1.0D); + int t = floor(z - q - 1.0D); + int u = floor(z + q + 1.0D); + + for (TNT currentTNT : entities) { + if (currentTNT == tnt) continue; + if (!(currentTNT.getX() >= k && currentTNT.getY() >= r && currentTNT.getZ() >= t && currentTNT.getX() <= l && currentTNT.getY() <= s && currentTNT.getZ() <= u)) { + continue; + } + + double x = currentTNT.getX() - this.x; + double y = currentTNT.getY() - this.y; + double z = currentTNT.getZ() - this.z; + double aa = Math.sqrt(x * x + y * y + z * z); + double w = aa / q; + if (w > 1.0) { + continue; + } + if (aa == 0.0) { + continue; + } + x /= aa; + y /= aa; + z /= aa; + + double ab = getExposure(this.x, this.y, this.z); + double ac = (1.0 - w) * ab; + currentTNT.setVx(currentTNT.getVx() + x * ac); + currentTNT.setVy(currentTNT.getVy() + y * ac); + currentTNT.setVz(currentTNT.getVz() + z * ac); + } + } + + private static int floor(double value) { + int i = (int) value; + return value < (double) i ? i - 1 : i; + } + + private static final double SIZE = 0.98; + private static final double MIN_POINT = 0.01; + private static final double MAX_POINT = SIZE + MIN_POINT; + private static final double EXPOSURE_CONSTANT_1 = 1.0 / (SIZE * 2 + 1.0); + private static final double EXPOSURE_CONSTANT_2 = (1.0 - Math.floor(1.0 / EXPOSURE_CONSTANT_1) * EXPOSURE_CONSTANT_1) / 2.0; + + private static float getExposure(double x, double y, double z) { + float blockMisses = 0; + float blockTotal = 0; + + for (double k = 0.0; k <= 1.0; k += EXPOSURE_CONSTANT_1) { + for (double l = 0.0; l <= 1.0; l += EXPOSURE_CONSTANT_1) { + for (double m = 0.0; m <= 1.0; m += EXPOSURE_CONSTANT_1) { + double dx = lerp(k, MIN_POINT, MAX_POINT) + EXPOSURE_CONSTANT_2; + double dy = lerp(l, 0.0, SIZE); + double dz = lerp(m, MIN_POINT, MAX_POINT) + EXPOSURE_CONSTANT_2; + + if (rayTrace(x, y, z, dx, dy, dz)) { + blockMisses++; + } + blockTotal++; + } } } - // TODO: Add velocity change of other tnt entities - // System.out.println(affectedBlocks.size()); + return blockMisses / blockTotal; + } + + public static double lerp(double delta, double start, double end) { + return start + delta * (end - start); + } + + public static boolean rayTrace(double sX, double sY, double sZ, double dX, double dY, double dZ) { + double x = sX; + double y = sY; + double z = sZ; + int oX = sX > dX ? -1 : 1; + int oY = sY > dY ? -1 : 1; + int oZ = sZ > dZ ? -1 : 1; + while (true) { + if (Simulator19.getBlockType(floor(x), floor(y), floor(z)) != Material.AIR) { + return true; + } + + double cX = x - (floor(x) + oX); + double cY = y - (floor(y) + oY); + double cZ = z - (floor(z) + oZ); + + double maxChange = Math.min(Math.abs(cX), Math.min(Math.abs(cY), Math.abs(cZ))); + x += Math.signum(cX) * maxChange; + y += Math.signum(cY) * maxChange; + z += Math.signum(cZ) * maxChange; + + if (floor(x) == floor(dX) && floor(y) == floor(dY) && floor(z) == floor(dZ)) { + return false; + } + } } } diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java index 2c0bb8eb..276150b0 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java @@ -33,6 +33,19 @@ public class Simulator19 implements Simulator { protected static final World WORLD = Bukkit.getWorlds().get(0); + private static final BlockData AIR_BLOCK_DATA = Material.AIR.createBlockData(); + private static final VoxelShape AIR_VOXEL_SHAPE = new VoxelShape() { + @Override + public Collection getBoundingBoxes() { + return Collections.emptyList(); + } + + @Override + public boolean overlaps(BoundingBox boundingBox) { + return false; + } + }; + private static final Map BLOCK_TYPES_MAP = new HashMap<>(); private static final Map BLOCK_DATA_MAP = new HashMap<>(); private static final Map COLLISION_DATA_MAP = new HashMap<>(); @@ -47,11 +60,9 @@ public class Simulator19 implements Simulator { while (!tntList.isEmpty()) { List remove = new ArrayList<>(); for (TNT tnt : tntList) { - if (tnt.getFuse() == 0) { + if (tnt.tick()) { remove.add(tnt); - continue; } - tnt.tick(); } tntList.removeAll(remove); } @@ -72,25 +83,13 @@ public class Simulator19 implements Simulator { return BLOCK_DATA_MAP.computeIfAbsent(vector, v -> WORLD.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).getBlockData()); } - public static VoxelShape getVoxelShape(int x, int y, int z) { - Vector vector = new Vector(x, y, z); + public static VoxelShape getVoxelShape(Vector vector) { return COLLISION_DATA_MAP.computeIfAbsent(vector, v -> WORLD.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).getCollisionShape()); } - public static void clearBlock(int x, int y, int z) { - Vector vector = new Vector(x, y, z); + public static void clearBlock(Vector vector) { BLOCK_TYPES_MAP.put(vector, Material.AIR); - BLOCK_DATA_MAP.put(vector, Material.AIR.createBlockData()); - COLLISION_DATA_MAP.put(vector, new VoxelShape() { - @Override - public Collection getBoundingBoxes() { - return Collections.emptyList(); - } - - @Override - public boolean overlaps(BoundingBox other) { - return false; - } - }); + BLOCK_DATA_MAP.put(vector, AIR_BLOCK_DATA); + COLLISION_DATA_MAP.put(vector, AIR_VOXEL_SHAPE); } } diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java index bb8d70e6..a3389c1d 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java @@ -31,6 +31,7 @@ import org.bukkit.block.data.type.*; import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; import org.bukkit.util.Vector; +import java.util.ArrayList; import java.util.Random; @Getter @@ -81,7 +82,7 @@ public class TNT { this.fuse--; if (this.fuse <= 0) { - Explosion explosion = new Explosion(this, x, y + 0.98 * 0.0625, z); + Explosion explosion = new Explosion(this, x, y + 0.98 * 0.0625, z, new ArrayList<>()); explosion.calculate(); return true; }