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.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<Vector, Material> BLOCK_TYPES_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
|
||||
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<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.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<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()) {
|
||||
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;
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren