diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java
new file mode 100644
index 00000000..561af19c
--- /dev/null
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/AxisMovementLimiter.java
@@ -0,0 +1,166 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2023 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 org.bukkit.Axis;
+import org.bukkit.util.BoundingBox;
+import org.bukkit.util.Vector;
+import org.bukkit.util.VoxelShape;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AxisMovementLimiter {
+
+ private Axis axis;
+ private double movement;
+
+ private double minX;
+ private double maxX;
+ private double minY;
+ private double maxY;
+ private double minZ;
+ private double maxZ;
+
+ public AxisMovementLimiter(double x, double y, double z, Axis axis, double movement) {
+ this.axis = axis;
+ this.movement = movement;
+
+ // Calculate the min and max values for the movement
+ minX = x;
+ maxX = x + 0.98;
+
+ minY = y;
+ maxY = y + 0.98;
+
+ minZ = z;
+ maxZ = z + 0.98;
+
+ switch (axis) {
+ case X:
+ if (movement < 0) {
+ minX += movement;
+ } else if (movement > 0) {
+ maxX += movement;
+ }
+ break;
+ case Y:
+ if (movement < 0) {
+ minY += movement;
+ } else if (movement > 0) {
+ maxY += movement;
+ }
+ break;
+ case Z:
+ if (movement < 0) {
+ minZ += movement;
+ } else if (movement > 0) {
+ maxZ += movement;
+ }
+ break;
+ }
+ }
+
+ private List possibleCollisions() {
+ int minX = TNT.floor(this.minX);
+ int maxX = TNT.floor(this.maxX);
+ int minY = TNT.floor(this.minY) - 1;
+ int maxY = TNT.floor(this.maxY);
+ int minZ = TNT.floor(this.minZ);
+ int maxZ = TNT.floor(this.maxZ);
+
+ List vectors = new ArrayList<>();
+ for (int x = minX; x <= maxX; x++) {
+ for (int y = minY; y <= maxY; y++) {
+ for (int z = minZ; z <= maxZ; z++) {
+ vectors.add(new Vector(x, y, z));
+ }
+ }
+ }
+ return vectors;
+ }
+
+ public double run() {
+ BoundingBox movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
+ List vectors = possibleCollisions();
+
+ Double collision = null;
+ for (Vector vector : vectors) {
+ VoxelShape voxelShape = Simulator19.getVoxelShape(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
+ for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
+ boundingBox = boundingBox.clone().shift(vector);
+ boolean collides = boundingBox.overlaps(movementBoundingBox);
+ if (!collides) continue;
+
+ double value;
+ switch (axis) {
+ case X:
+ if (movement < 0) {
+ value = boundingBox.getMaxX();
+ } else {
+ value = boundingBox.getMinX() - 0.98;
+ }
+ break;
+ case Y:
+ if (movement < 0) {
+ value = boundingBox.getMaxY();
+ } else {
+ value = boundingBox.getMinY() - 0.98;
+ }
+ break;
+ case Z:
+ if (movement < 0) {
+ value = boundingBox.getMaxZ();
+ } else {
+ value = boundingBox.getMinZ() - 0.98;
+ }
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + axis);
+ }
+
+ if (collision == null) {
+ collision = value;
+ } else {
+ if (movement < 0) {
+ collision = Math.max(collision, value);
+ } else {
+ collision = Math.min(collision, value);
+ }
+ }
+ }
+ }
+
+ if (collision == null) {
+ return movement;
+ } else {
+ switch (axis) {
+ case X:
+ return movement + (collision - minX);
+ case Y:
+ return movement + (collision - minY);
+ case Z:
+ return movement + (collision - minZ);
+ default:
+ throw new IllegalStateException("Unexpected value: " + axis);
+ }
+ }
+ }
+}
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 6bad4658..96a8d382 100644
--- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java
@@ -23,8 +23,12 @@ import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
+import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
+import org.bukkit.util.VoxelShape;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -34,6 +38,7 @@ public class Simulator19 implements Simulator {
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<>();
@Override
public synchronized void run() {
@@ -45,6 +50,7 @@ public class Simulator19 implements Simulator {
BLOCK_TYPES_MAP.clear();
BLOCK_DATA_MAP.clear();
+ COLLISION_DATA_MAP.clear();
}
public static Material getBlockType(int x, int y, int z) {
@@ -57,9 +63,25 @@ public class Simulator19 implements Simulator {
return BLOCK_DATA_MAP.computeIfAbsent(vector, v -> WORLD.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).getBlockData());
}
- public static void setBlock(int x, int y, int z, Material material) {
+ public static VoxelShape getVoxelShape(int x, int y, int z) {
Vector vector = new Vector(x, y, z);
- BLOCK_TYPES_MAP.put(vector, material);
- BLOCK_DATA_MAP.put(vector, material.createBlockData());
+ 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);
+ 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;
+ }
+ });
}
}
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 9c67507f..bbc9c137 100644
--- a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java
+++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java
@@ -21,23 +21,16 @@ package de.steamwar.bausystem.features.simulator;
import lombok.Getter;
import lombok.Setter;
-import net.minecraft.core.EnumDirection;
import net.minecraft.world.level.RayTrace;
-import net.minecraft.world.phys.AxisAlignedBB;
import net.minecraft.world.phys.MovingObjectPosition;
import net.minecraft.world.phys.Vec3D;
-import net.minecraft.world.phys.shapes.VoxelShape;
-import net.minecraft.world.phys.shapes.VoxelShapes;
+import org.bukkit.Axis;
import org.bukkit.Material;
-import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.*;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
-import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity;
-import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
-import java.util.List;
import java.util.Random;
@Getter
@@ -95,7 +88,7 @@ public class TNT {
}
private void move(Vector movement) {
- if (movement.lengthSquared() > 1.0E-7) {
+ if (movementMultiplier.lengthSquared() > 1.0E-7) {
movement.multiply(movementMultiplier);
movementMultiplier = new Vector(0, 0, 0);
vx = 0;
@@ -104,19 +97,20 @@ public class TNT {
}
Vector vec3d = adjustMovementForCollisions(movement);
+ // System.out.println(movement + " " + vec3d);
double lengthSquared = vec3d.lengthSquared();
if (lengthSquared > 1.0E-7) {
if (fallDistance != 0.0F) {
// TODO: This could be wrong
- MovingObjectPosition movingObjectPosition = ((CraftWorld) Simulator19.WORLD).getHandle().a(new RayTrace(new Vec3D(x, y, z), new Vec3D(x + vx, y + vy, z + vz), RayTrace.BlockCollisionOption.d, RayTrace.FluidCollisionOption.d, null));
+ MovingObjectPosition movingObjectPosition = ((CraftWorld) Simulator19.WORLD).getHandle().a(new RayTrace(new Vec3D(x, y, z), new Vec3D(x + vec3d.getX(), y + vec3d.getY(), z + vec3d.getZ()), RayTrace.BlockCollisionOption.d, RayTrace.FluidCollisionOption.d, null));
if (movingObjectPosition.c() != MovingObjectPosition.EnumMovingObjectType.a) {
onLanding();
}
}
- this.x += movement.getX();
- this.y += movement.getY();
- this.z += movement.getZ();
+ this.x += vec3d.getX();
+ this.y += vec3d.getY();
+ this.z += vec3d.getZ();
}
boolean bl = !approximatelyEquals(movement.getX(), vec3d.getX());
@@ -128,7 +122,7 @@ public class TNT {
Vector blockPos = getLandingPos();
Material material = Simulator19.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
BlockData blockData = Simulator19.getBlockData(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
- fall(vec3d.getX(), onGround);
+ fall(vec3d.getY(), onGround);
if (horizontalCollision) {
this.vx = bl ? 0.0 : this.vx;
@@ -140,11 +134,12 @@ public class TNT {
if (this.vy < 0.0) {
this.vy = -this.vy * 0.8;
}
- }
- if (blockData instanceof Bed) {
+ } else if (blockData instanceof Bed) {
if (this.vy < 0.0) {
this.vy = -this.vy * 0.6600000262260437 * 0.8;
}
+ } else {
+ this.vy = 0.0;
}
}
@@ -153,7 +148,7 @@ public class TNT {
double cy = Math.abs(this.vy);
if (cy < 0.1) {
double cy2 = 0.4 + cy * 0.2;
- this.vx = vy * cy2;
+ this.vx = vx * cy2;
this.vz = vz * cy2;
}
}
@@ -161,57 +156,26 @@ public class TNT {
checkBlockCollision();
float j = this.getVelocityMultiplier();
- this.vy *= j;
this.vx *= j;
+ this.vz *= j;
}
private Vector adjustMovementForCollisions(Vector movement) {
- AxisAlignedBB boundingBox = new AxisAlignedBB(x, y, z, x + 0.98, y + 0.98, z + 0.98);
- return movement.lengthSquared() == 0.0 ? movement : adjustMovementForCollisions(null, movement, boundingBox, Simulator19.WORLD);
- }
-
- public static Vector adjustMovementForCollisions(Entity entity, Vector movement, AxisAlignedBB entityBoundingBox, World world) {
- Iterable voxelShapes = ((CraftWorld) world).getHandle().d(((CraftEntity) entity).getHandle(), entityBoundingBox);
- List collisions = new java.util.ArrayList<>();
- voxelShapes.forEach(collisions::add);
-
- return adjustMovementForCollisions(movement, entityBoundingBox, collisions);
- }
-
- private static Vector adjustMovementForCollisions(Vector movement, AxisAlignedBB entityBoundingBox, List collisions) {
- if (collisions.isEmpty()) {
+ if (movement.lengthSquared() == 0.0) {
return movement;
+ }
+
+ double mY = new AxisMovementLimiter(x, y, z, Axis.Y, movement.getY()).run();
+
+ boolean bl = Math.abs(movement.getX()) < Math.abs(movement.getZ());
+ if (bl) {
+ double mZ = new AxisMovementLimiter(x, y + mY, z, Axis.Z, movement.getZ()).run();
+ double mX = new AxisMovementLimiter(x, y + mY, z + mZ, Axis.X, movement.getX()).run();
+ return new Vector(mX, mY, mZ);
} else {
- double d = movement.getX();
- double e = movement.getY();
- double f = movement.getZ();
- if (e != 0.0) {
- e = VoxelShapes.a(EnumDirection.EnumAxis.b, entityBoundingBox, collisions, e);
- if (e != 0.0) {
- entityBoundingBox = entityBoundingBox.c(0.0, e, 0.0);
- }
- }
-
- boolean bl = Math.abs(d) < Math.abs(f);
- if (bl && f != 0.0) {
- f = VoxelShapes.a(EnumDirection.EnumAxis.c, entityBoundingBox, collisions, f);
- if (f != 0.0) {
- entityBoundingBox = entityBoundingBox.c(0.0, 0.0, f);
- }
- }
-
- if (d != 0.0) {
- d = VoxelShapes.a(EnumDirection.EnumAxis.a, entityBoundingBox, collisions, d);
- if (!bl && d != 0.0) {
- entityBoundingBox = entityBoundingBox.c(d, 0.0, 0.0);
- }
- }
-
- if (!bl && f != 0.0) {
- f = VoxelShapes.a(EnumDirection.EnumAxis.c, entityBoundingBox, collisions, f);
- }
-
- return new Vector(d, e, f);
+ double mX = new AxisMovementLimiter(x, y + mY, z, Axis.X, movement.getX()).run();
+ double mZ = new AxisMovementLimiter(x + mX, y + mY, z, Axis.Z, movement.getZ()).run();
+ return new Vector(mX, mY, mZ);
}
}
@@ -219,7 +183,7 @@ public class TNT {
return Math.abs(b - a) < 9.999999747378752E-6;
}
- private int floor(double value) {
+ public static int floor(double value) {
int i = (int)value;
return value < (double)i ? i - 1 : i;
}
@@ -240,12 +204,6 @@ public class TNT {
private void fall(double heightDifference, boolean onGround) {
if (onGround) {
- /*
- if (this.fallDistance > 0.0F) {
- // TODO: Is this needed?: state.getBlock().onLandedUpon(this.world, state, landedPosition, this, this.fallDistance);
- }
- */
-
this.onLanding();
} else if (heightDifference < 0.0) {
this.fallDistance -= (float)heightDifference;