SteamWar/BauSystem2.0
Archiviert
12
0

Update simulator preview
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Signed-off-by: yoyosource <yoyosource@nidido.de>
Dieser Commit ist enthalten in:
yoyosource 2023-04-10 18:50:36 +02:00
Ursprung ff0d3fe2e5
Commit 8d4f1bf2da
3 geänderte Dateien mit 218 neuen und 72 gelöschten Zeilen

Datei anzeigen

@ -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);
}
}
}
}

Datei anzeigen

@ -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;
}
});
} }
} }

Datei anzeigen

@ -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;