forked from SteamWar/SteamWar
Add some of the collision code
This commit is contained in:
+10
@@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||
import de.steamwar.bausystem.features.simulator.execute.SimulatorExecutor;
|
||||
import de.steamwar.bausystem.features.simulator.preview.SimulatorPreviewData;
|
||||
import de.steamwar.command.PreviousArguments;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
@@ -90,6 +91,15 @@ public class SimulatorCommand extends SWCommand {
|
||||
}
|
||||
}
|
||||
|
||||
@Register(value = "test")
|
||||
public void test(Player player) {
|
||||
SimulatorPreviewData data = new SimulatorPreviewData(null);
|
||||
data.spawnTNT(0, 120, 0);
|
||||
data.tick();
|
||||
data.tick();
|
||||
data.tick();
|
||||
}
|
||||
|
||||
@ClassMapper(value = Simulator.class, local = true)
|
||||
public TypeMapper<Simulator> allSimulators() {
|
||||
return new TypeMapper<>() {
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 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.preview;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.VoxelShape;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class SimulatorPreviewAABB {
|
||||
public double minX;
|
||||
public double minY;
|
||||
public double minZ;
|
||||
public double maxX;
|
||||
public double maxY;
|
||||
public double maxZ;
|
||||
|
||||
public SimulatorPreviewAABB copy() {
|
||||
return new SimulatorPreviewAABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public void expandTowards(double vx, double vy, double vz) {
|
||||
if (vx < 0) {
|
||||
minX += vx;
|
||||
} else {
|
||||
maxX += vx;
|
||||
}
|
||||
if (vy < 0) {
|
||||
minY += vy;
|
||||
} else {
|
||||
maxY += vy;
|
||||
}
|
||||
if (vz < 0) {
|
||||
minZ += vz;
|
||||
} else {
|
||||
maxZ += vz;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(double vx, double vy, double vz) {
|
||||
minX += vx;
|
||||
minY += vy;
|
||||
minZ += vz;
|
||||
}
|
||||
|
||||
public double sizeX() {
|
||||
return maxX - minX;
|
||||
}
|
||||
|
||||
public double sizeY() {
|
||||
return maxY - minY;
|
||||
}
|
||||
|
||||
public double sizeZ() {
|
||||
return maxZ - minZ;
|
||||
}
|
||||
|
||||
public List<BoundingBox> intersects(int x, int y, int z, VoxelShape voxelShape) {
|
||||
return voxelShape.getBoundingBoxes()
|
||||
.stream()
|
||||
.filter(boundingBox -> {
|
||||
return minX - (x + boundingBox.getMaxX()) < -1.0E-7 &&
|
||||
maxX - (x + boundingBox.getMinX()) > 1.0E-7 &&
|
||||
minY - (y + boundingBox.getMaxY()) < -1.0E-7 &&
|
||||
maxY - (y + boundingBox.getMinY()) > 1.0E-7 &&
|
||||
minZ - (z + boundingBox.getMaxZ()) < -1.0E-7 &&
|
||||
maxZ - (z + boundingBox.getMinZ()) > 1.0E-7;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean intersectsX(double x, double y, double z, BoundingBox boundingBox) {
|
||||
return minX - (x + boundingBox.getMaxX()) < -1.0E-7 &&
|
||||
maxX - (x + boundingBox.getMinX()) > 1.0E-7;
|
||||
}
|
||||
|
||||
public boolean intersectsY(int x, int y, int z, BoundingBox boundingBox) {
|
||||
return minY - (y + boundingBox.getMaxY()) < -1.0E-7 &&
|
||||
maxY - (y + boundingBox.getMinY()) > 1.0E-7;
|
||||
}
|
||||
|
||||
public boolean intersectsZ(double x, double y, double z, BoundingBox boundingBox) {
|
||||
return minZ - (z + boundingBox.getMaxZ()) < -1.0E-7 &&
|
||||
maxZ - (z + boundingBox.getMinZ()) > 1.0E-7;
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 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.preview;
|
||||
|
||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.util.VoxelShape;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SimulatorPreviewData {
|
||||
private static final World WORLD = Bukkit.getWorlds().get(0);
|
||||
|
||||
public final Simulator simulator;
|
||||
public final List<SimulatorPreviewTNT> tnts = new ArrayList<>();
|
||||
|
||||
private final Set<Pos> AIR = new HashSet<>();
|
||||
private final Map<Pos, BlockData> datas = new HashMap<>();
|
||||
private final Map<Pos, VoxelShape> shapes = new HashMap<>();
|
||||
|
||||
public BlockData getBlockData(int x, int y, int z) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
if (AIR.contains(pos)) return null;
|
||||
return datas.computeIfAbsent(pos, __ -> {
|
||||
BlockData blockData = WORLD.getBlockData(x, y, z);
|
||||
if (blockData.getMaterial().isAir()) {
|
||||
AIR.add(pos);
|
||||
return null;
|
||||
}
|
||||
return blockData;
|
||||
});
|
||||
}
|
||||
|
||||
public VoxelShape getBlockShape(int x, int y, int z) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
if (AIR.contains(pos)) return null;
|
||||
return shapes.computeIfAbsent(pos, __ -> {
|
||||
Block block = WORLD.getBlockAt(x, y, z);
|
||||
if (block.getType().isAir()) {
|
||||
AIR.add(pos);
|
||||
return null;
|
||||
}
|
||||
return block.getCollisionShape();
|
||||
});
|
||||
}
|
||||
|
||||
public void setAir(int x, int y, int z) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
AIR.add(pos);
|
||||
datas.remove(pos);
|
||||
shapes.remove(pos);
|
||||
}
|
||||
|
||||
public void spawnTNT(double x, double y, double z) {
|
||||
tnts.add(new SimulatorPreviewTNT(this, x, y, z));
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
tnts.forEach(SimulatorPreviewTNT::tick);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
private final class Pos {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
}
|
||||
}
|
||||
+170
-16
@@ -19,15 +19,21 @@
|
||||
|
||||
package de.steamwar.bausystem.features.simulator.preview;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.bukkit.util.VoxelShape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class SimulatorPreviewTNT {
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
private boolean gravity = false;
|
||||
private final SimulatorPreviewData data;
|
||||
private boolean gravity = true;
|
||||
private int fuse = 80;
|
||||
private double x;
|
||||
private double y;
|
||||
@@ -36,9 +42,12 @@ public class SimulatorPreviewTNT {
|
||||
private double vy;
|
||||
private double vz;
|
||||
|
||||
private SimulatorPreviewVec collide = new SimulatorPreviewVec();
|
||||
private boolean onGround;
|
||||
|
||||
public SimulatorPreviewTNT(double x, double y, double z) {
|
||||
public SimulatorPreviewTNT(SimulatorPreviewData data, double x, double y, double z) {
|
||||
this.data = data;
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
@@ -51,7 +60,7 @@ public class SimulatorPreviewTNT {
|
||||
|
||||
public void tick() {
|
||||
// Gravity
|
||||
if (!gravity) {
|
||||
if (gravity) {
|
||||
vy -= 0.04;
|
||||
}
|
||||
|
||||
@@ -83,19 +92,19 @@ public class SimulatorPreviewTNT {
|
||||
}
|
||||
|
||||
public void move() {
|
||||
Vector vec = collide();
|
||||
double d = vec.lengthSquared();
|
||||
if (d > 1.0E-7 || new Vector(vx, vy, vz).lengthSquared() - d < 1.0E-7) {
|
||||
x += vx;
|
||||
y += vy;
|
||||
z += vz;
|
||||
collide();
|
||||
double collisionLengthSquared = collide.lengthSquared();
|
||||
if (collisionLengthSquared > 1.0E-7 || new Vector(vx, vy, vz).lengthSquared() - collisionLengthSquared < 1.0E-7) {
|
||||
x += collide.x;
|
||||
y += collide.y;
|
||||
z += collide.z;
|
||||
}
|
||||
|
||||
boolean xCollision = !equal(vx, vec.getX());
|
||||
boolean zCollision = !equal(vz, vec.getZ());
|
||||
boolean xCollision = !equal(vx, collide.x);
|
||||
boolean zCollision = !equal(vz, collide.z);
|
||||
boolean horizontalCollision = xCollision || zCollision;
|
||||
if (Math.abs(vy) > 0.0F) {
|
||||
boolean verticalCollision = vy != vec.getY();
|
||||
boolean verticalCollision = vy != collide.y;
|
||||
onGround = verticalCollision && vy < (double) 0.0F;
|
||||
}
|
||||
|
||||
@@ -103,6 +112,9 @@ public class SimulatorPreviewTNT {
|
||||
if (xCollision) vx = 0;
|
||||
if (zCollision) vz = 0;
|
||||
}
|
||||
// vx = collide.x;
|
||||
vy = collide.y;
|
||||
// vz = collide.z;
|
||||
// TODO: Get Block -> updateEntityMovementAfterFallOn!
|
||||
// TODO: Get BlockSpeedFactor multiply
|
||||
}
|
||||
@@ -111,13 +123,155 @@ public class SimulatorPreviewTNT {
|
||||
return Math.abs(y - x) < (double) 1.0E-5F;
|
||||
}
|
||||
|
||||
public Vector collide() {
|
||||
if (x == 0 && y == 0 && z == 0) return new Vector(0, 0, 0);
|
||||
// TODO: Implement rest!
|
||||
return null;
|
||||
public void collide() {
|
||||
boolean xZero = vx == 0;
|
||||
boolean zZero = vz == 0;
|
||||
if (xZero && vy == 0 && zZero) {
|
||||
collide.x = 0;
|
||||
collide.y = 0;
|
||||
collide.z = 0;
|
||||
return;
|
||||
}
|
||||
SimulatorPreviewAABB box = new SimulatorPreviewAABB(x, y, z, x + 0.98, y + 0.98, z + 0.98);
|
||||
SimulatorPreviewAABB initialCollisionBox = box.copy();
|
||||
initialCollisionBox.expandTowards(vx, vy, vz);
|
||||
System.out.println(vy);
|
||||
|
||||
List<CollisionData> collisionDataList = new ArrayList<>();
|
||||
for (int x = floor(initialCollisionBox.minX - 1.0E-7) - 1; x < floor(initialCollisionBox.maxX + 1.0E-7) + 1; x++) {
|
||||
for (int y = floor(initialCollisionBox.minY - 1.0E-7) - 1; y < floor(initialCollisionBox.maxY + 1.0E-7) + 1; y++) {
|
||||
for (int z = floor(initialCollisionBox.minZ - 1.0E-7) - 1; z < floor(initialCollisionBox.maxZ + 1.0E-7) + 1; z++) {
|
||||
System.out.println(x + " " + y + " " + z);
|
||||
VoxelShape shape = data.getBlockShape(x, y, z);
|
||||
if (shape == null) continue;
|
||||
List<BoundingBox> collisionBoxes = initialCollisionBox.intersects(x, y, z, shape);
|
||||
if (collisionBoxes.isEmpty()) continue;
|
||||
collisionDataList.add(new CollisionData(x, y, z, collisionBoxes));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (collisionDataList.isEmpty()) {
|
||||
System.out.println("No collision found");
|
||||
collide.x = vx;
|
||||
collide.y = vy;
|
||||
collide.z = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
double vx = this.vx;
|
||||
double vy = this.vy;
|
||||
double vz = this.vz;
|
||||
|
||||
System.out.println(vx + " " + vy + " " + vz);
|
||||
|
||||
if (vy != 0) {
|
||||
for (CollisionData collisionData : collisionDataList) {
|
||||
vy = collideY(box, collisionData, vy);
|
||||
}
|
||||
if (vy != 0) box.add(0, vy, 0);
|
||||
}
|
||||
|
||||
boolean xSmaller = Math.abs(vx) < Math.abs(vz);
|
||||
if (xSmaller && vz != 0) {
|
||||
for (CollisionData collisionData : collisionDataList) {
|
||||
vz = collideZ(box, collisionData, vz);
|
||||
}
|
||||
if (vz != 0) box.add(0, 0, vz);
|
||||
}
|
||||
|
||||
if (vx != 0) {
|
||||
for (CollisionData collisionData : collisionDataList) {
|
||||
vx = collideX(box, collisionData, vx);
|
||||
}
|
||||
if (vx != 0) box.add(vx, 0, 0);
|
||||
}
|
||||
|
||||
if (!xSmaller && vz != 0) {
|
||||
for (CollisionData collisionData : collisionDataList) {
|
||||
vz = collideZ(box, collisionData, vz);
|
||||
}
|
||||
if (vz != 0) box.add(0, 0, vz);
|
||||
}
|
||||
|
||||
System.out.println(vx + " " + vy + " " + vz);
|
||||
|
||||
collide.x = vx;
|
||||
collide.y = vy;
|
||||
collide.z = vz;
|
||||
}
|
||||
|
||||
public static int floor(double value) {
|
||||
int i = (int) value;
|
||||
return value < (double) i ? i - 1 : i;
|
||||
}
|
||||
|
||||
public static double collideX(SimulatorPreviewAABB box, CollisionData collisionData, double vx) {
|
||||
if (vx < 0) {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsX(collisionData.x + vx, collisionData.y, collisionData.z, boundingBox)) {
|
||||
vx = Math.max(vx, boundingBox.getMaxX());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsX(collisionData.x + vx, collisionData.y, collisionData.z, boundingBox)) {
|
||||
vx = Math.min(vx, boundingBox.getMinX());
|
||||
}
|
||||
}
|
||||
vx -= box.sizeY();
|
||||
}
|
||||
return vx;
|
||||
}
|
||||
|
||||
public static double collideY(SimulatorPreviewAABB box, CollisionData collisionData, double vy) {
|
||||
double size = box.sizeY();
|
||||
box = box.copy();
|
||||
box.expandTowards(0, vy, 0);
|
||||
if (vy < 0) {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsY(collisionData.x, collisionData.y, collisionData.z, boundingBox)) {
|
||||
vy = Math.max(vy, boundingBox.getMaxY() + collisionData.y - box.minY - size);
|
||||
}
|
||||
}
|
||||
System.out.println("N: " + vy);
|
||||
} else {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsY(collisionData.x, collisionData.y, collisionData.z, boundingBox)) {
|
||||
vy = Math.min(vy, boundingBox.getMinY() + collisionData.y - box.minY - size);
|
||||
}
|
||||
}
|
||||
System.out.println("P: " + vy);
|
||||
}
|
||||
return vy;
|
||||
}
|
||||
|
||||
public static double collideZ(SimulatorPreviewAABB box, CollisionData collisionData, double vz) {
|
||||
if (vz < 0) {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsZ(collisionData.x, collisionData.y, collisionData.z + vz, boundingBox)) {
|
||||
vz = Math.max(vz, boundingBox.getMaxZ());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (BoundingBox boundingBox : collisionData.collisions) {
|
||||
if (box.intersectsZ(collisionData.x, collisionData.y, collisionData.z + vz, boundingBox)) {
|
||||
vz = Math.min(vz, boundingBox.getMinZ());
|
||||
}
|
||||
}
|
||||
vz -= box.sizeZ();
|
||||
}
|
||||
return vz;
|
||||
}
|
||||
|
||||
public void explode() {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private class CollisionData {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final List<BoundingBox> collisions;
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2020 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.preview;
|
||||
|
||||
public class SimulatorPreviewVec {
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
|
||||
public double lengthSquared() {
|
||||
return x * x + y * y + z * z;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user