Signed-off-by: yoyosource <yoyosource@nidido.de>
Dieser Commit ist enthalten in:
Ursprung
ff0d3fe2e5
Commit
8d4f1bf2da
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Vector> 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<Vector> 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<Vector> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,8 +23,12 @@ import org.bukkit.Bukkit;
|
|||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
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.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -34,6 +38,7 @@ public class Simulator19 implements Simulator {
|
|||||||
|
|
||||||
private static final Map<Vector, Material> BLOCK_TYPES_MAP = new HashMap<>();
|
private static final Map<Vector, Material> BLOCK_TYPES_MAP = new HashMap<>();
|
||||||
private static final Map<Vector, BlockData> BLOCK_DATA_MAP = new HashMap<>();
|
private static final Map<Vector, BlockData> BLOCK_DATA_MAP = new HashMap<>();
|
||||||
|
private static final Map<Vector, VoxelShape> COLLISION_DATA_MAP = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void run() {
|
public synchronized void run() {
|
||||||
@ -45,6 +50,7 @@ public class Simulator19 implements Simulator {
|
|||||||
|
|
||||||
BLOCK_TYPES_MAP.clear();
|
BLOCK_TYPES_MAP.clear();
|
||||||
BLOCK_DATA_MAP.clear();
|
BLOCK_DATA_MAP.clear();
|
||||||
|
COLLISION_DATA_MAP.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Material getBlockType(int x, int y, int z) {
|
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());
|
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);
|
Vector vector = new Vector(x, y, z);
|
||||||
BLOCK_TYPES_MAP.put(vector, material);
|
return COLLISION_DATA_MAP.computeIfAbsent(vector, v -> WORLD.getBlockAt(v.getBlockX(), v.getBlockY(), v.getBlockZ()).getCollisionShape());
|
||||||
BLOCK_DATA_MAP.put(vector, material.createBlockData());
|
}
|
||||||
|
|
||||||
|
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<BoundingBox> getBoundingBoxes() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean overlaps(BoundingBox other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,23 +21,16 @@ package de.steamwar.bausystem.features.simulator;
|
|||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.minecraft.core.EnumDirection;
|
|
||||||
import net.minecraft.world.level.RayTrace;
|
import net.minecraft.world.level.RayTrace;
|
||||||
import net.minecraft.world.phys.AxisAlignedBB;
|
|
||||||
import net.minecraft.world.phys.MovingObjectPosition;
|
import net.minecraft.world.phys.MovingObjectPosition;
|
||||||
import net.minecraft.world.phys.Vec3D;
|
import net.minecraft.world.phys.Vec3D;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
import org.bukkit.Axis;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShapes;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.type.*;
|
import org.bukkit.block.data.type.*;
|
||||||
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
|
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 org.bukkit.util.Vector;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -95,7 +88,7 @@ public class TNT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void move(Vector movement) {
|
private void move(Vector movement) {
|
||||||
if (movement.lengthSquared() > 1.0E-7) {
|
if (movementMultiplier.lengthSquared() > 1.0E-7) {
|
||||||
movement.multiply(movementMultiplier);
|
movement.multiply(movementMultiplier);
|
||||||
movementMultiplier = new Vector(0, 0, 0);
|
movementMultiplier = new Vector(0, 0, 0);
|
||||||
vx = 0;
|
vx = 0;
|
||||||
@ -104,19 +97,20 @@ public class TNT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector vec3d = adjustMovementForCollisions(movement);
|
Vector vec3d = adjustMovementForCollisions(movement);
|
||||||
|
// System.out.println(movement + " " + vec3d);
|
||||||
double lengthSquared = vec3d.lengthSquared();
|
double lengthSquared = vec3d.lengthSquared();
|
||||||
if (lengthSquared > 1.0E-7) {
|
if (lengthSquared > 1.0E-7) {
|
||||||
if (fallDistance != 0.0F) {
|
if (fallDistance != 0.0F) {
|
||||||
// TODO: This could be wrong
|
// 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) {
|
if (movingObjectPosition.c() != MovingObjectPosition.EnumMovingObjectType.a) {
|
||||||
onLanding();
|
onLanding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.x += movement.getX();
|
this.x += vec3d.getX();
|
||||||
this.y += movement.getY();
|
this.y += vec3d.getY();
|
||||||
this.z += movement.getZ();
|
this.z += vec3d.getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean bl = !approximatelyEquals(movement.getX(), vec3d.getX());
|
boolean bl = !approximatelyEquals(movement.getX(), vec3d.getX());
|
||||||
@ -128,7 +122,7 @@ public class TNT {
|
|||||||
Vector blockPos = getLandingPos();
|
Vector blockPos = getLandingPos();
|
||||||
Material material = Simulator19.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
Material material = Simulator19.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
||||||
BlockData blockData = Simulator19.getBlockData(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) {
|
if (horizontalCollision) {
|
||||||
this.vx = bl ? 0.0 : this.vx;
|
this.vx = bl ? 0.0 : this.vx;
|
||||||
@ -140,11 +134,12 @@ public class TNT {
|
|||||||
if (this.vy < 0.0) {
|
if (this.vy < 0.0) {
|
||||||
this.vy = -this.vy * 0.8;
|
this.vy = -this.vy * 0.8;
|
||||||
}
|
}
|
||||||
}
|
} else if (blockData instanceof Bed) {
|
||||||
if (blockData instanceof Bed) {
|
|
||||||
if (this.vy < 0.0) {
|
if (this.vy < 0.0) {
|
||||||
this.vy = -this.vy * 0.6600000262260437 * 0.8;
|
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);
|
double cy = Math.abs(this.vy);
|
||||||
if (cy < 0.1) {
|
if (cy < 0.1) {
|
||||||
double cy2 = 0.4 + cy * 0.2;
|
double cy2 = 0.4 + cy * 0.2;
|
||||||
this.vx = vy * cy2;
|
this.vx = vx * cy2;
|
||||||
this.vz = vz * cy2;
|
this.vz = vz * cy2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,57 +156,26 @@ public class TNT {
|
|||||||
|
|
||||||
checkBlockCollision();
|
checkBlockCollision();
|
||||||
float j = this.getVelocityMultiplier();
|
float j = this.getVelocityMultiplier();
|
||||||
this.vy *= j;
|
|
||||||
this.vx *= j;
|
this.vx *= j;
|
||||||
|
this.vz *= j;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector adjustMovementForCollisions(Vector movement) {
|
private Vector adjustMovementForCollisions(Vector movement) {
|
||||||
AxisAlignedBB boundingBox = new AxisAlignedBB(x, y, z, x + 0.98, y + 0.98, z + 0.98);
|
if (movement.lengthSquared() == 0.0) {
|
||||||
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<VoxelShape> voxelShapes = ((CraftWorld) world).getHandle().d(((CraftEntity) entity).getHandle(), entityBoundingBox);
|
|
||||||
List<VoxelShape> collisions = new java.util.ArrayList<>();
|
|
||||||
voxelShapes.forEach(collisions::add);
|
|
||||||
|
|
||||||
return adjustMovementForCollisions(movement, entityBoundingBox, collisions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Vector adjustMovementForCollisions(Vector movement, AxisAlignedBB entityBoundingBox, List<VoxelShape> collisions) {
|
|
||||||
if (collisions.isEmpty()) {
|
|
||||||
return movement;
|
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 {
|
} else {
|
||||||
double d = movement.getX();
|
double mX = new AxisMovementLimiter(x, y + mY, z, Axis.X, movement.getX()).run();
|
||||||
double e = movement.getY();
|
double mZ = new AxisMovementLimiter(x + mX, y + mY, z, Axis.Z, movement.getZ()).run();
|
||||||
double f = movement.getZ();
|
return new Vector(mX, mY, mZ);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +183,7 @@ public class TNT {
|
|||||||
return Math.abs(b - a) < 9.999999747378752E-6;
|
return Math.abs(b - a) < 9.999999747378752E-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int floor(double value) {
|
public static int floor(double value) {
|
||||||
int i = (int)value;
|
int i = (int)value;
|
||||||
return value < (double)i ? i - 1 : i;
|
return value < (double)i ? i - 1 : i;
|
||||||
}
|
}
|
||||||
@ -240,12 +204,6 @@ public class TNT {
|
|||||||
|
|
||||||
private void fall(double heightDifference, boolean onGround) {
|
private void fall(double heightDifference, boolean onGround) {
|
||||||
if (onGround) {
|
if (onGround) {
|
||||||
/*
|
|
||||||
if (this.fallDistance > 0.0F) {
|
|
||||||
// TODO: Is this needed?: state.getBlock().onLandedUpon(this.world, state, landedPosition, this, this.fallDistance);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
this.onLanding();
|
this.onLanding();
|
||||||
} else if (heightDifference < 0.0) {
|
} else if (heightDifference < 0.0) {
|
||||||
this.fallDistance -= (float)heightDifference;
|
this.fallDistance -= (float)heightDifference;
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren