SteamWar/BauSystem2.0
Archiviert
12
0

Add initial Multi Tick calculation
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Signed-off-by: yoyosource <yoyosource@nidido.de>
Dieser Commit ist enthalten in:
yoyosource 2023-09-08 20:16:51 +02:00
Ursprung d09c4970a0
Commit 4fbbdf3a49
10 geänderte Dateien mit 239 neuen und 217 gelöschten Zeilen

Datei anzeigen

@ -19,17 +19,5 @@
package de.steamwar.bausystem.features.simulator.preview; package de.steamwar.bausystem.features.simulator.preview;
import de.steamwar.bausystem.features.simulator.TNTData;
import de.steamwar.bausystem.shared.Pair;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class Simulator15 implements Simulator { public class Simulator15 implements Simulator {
@Override
public void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) {
consumer.accept(null);
}
} }

Datei anzeigen

@ -104,7 +104,7 @@ public class AxisMovementLimiter {
} }
// TODO: This can be optimized by optimizing the x,y,z loop layout // TODO: This can be optimized by optimizing the x,y,z loop layout
public double run() { public double run(SimulatorData simulatorData) {
if (movement == 0.0) return 0.0; if (movement == 0.0) return 0.0;
BoundingBox movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); BoundingBox movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
@ -112,7 +112,7 @@ public class AxisMovementLimiter {
Double collision = null; Double collision = null;
for (Pos pos : poss) { for (Pos pos : poss) {
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(pos.x, pos.y, pos.z); boundingBox = boundingBox.clone().shift(pos.x, pos.y, pos.z);
boolean collides = boundingBox.overlaps(movementBoundingBox); boolean collides = boundingBox.overlaps(movementBoundingBox);

Datei anzeigen

@ -73,7 +73,7 @@ public class Explosion {
this.z = z; this.z = z;
} }
public void calculate() { public void calculate(SimulatorData simulatorData) {
Set<Pos> affectedBlocks = new HashSet<>(); Set<Pos> affectedBlocks = new HashSet<>();
for (int i = 0; i < FACE_BLOCKS.length; i += 3) { for (int i = 0; i < FACE_BLOCKS.length; i += 3) {
double d = FACE_BLOCKS[i + 0]; double d = FACE_BLOCKS[i + 0];
@ -90,12 +90,12 @@ public class Explosion {
int y = TNT.floor(n); int y = TNT.floor(n);
int z = TNT.floor(o); int z = TNT.floor(o);
Material material = Simulator19.getBlockType(x, y, z); Material material = simulatorData.getBlockType(x, y, z);
if (!material.isAir()) { if (!material.isAir()) {
h -= (material.getBlastResistance() + 0.3F) * 0.3F; h -= (material.getBlastResistance() + 0.3F) * 0.3F;
} }
if (WATER_LOGABLE.contains(material)) { if (WATER_LOGABLE.contains(material)) {
Waterlogged waterlogged = (Waterlogged) Simulator19.getBlockData(x, y, z); Waterlogged waterlogged = (Waterlogged) simulatorData.getBlockData(x, y, z);
if (waterlogged.isWaterlogged()) { if (waterlogged.isWaterlogged()) {
h = 0.0F; h = 0.0F;
} }
@ -110,7 +110,7 @@ public class Explosion {
o += f * 0.30000001192092896; o += f * 0.30000001192092896;
} }
} }
Simulator19.clearBlocks(affectedBlocks); simulatorData.clearBlocks(affectedBlocks);
float q = POWER * 2.0F; float q = POWER * 2.0F;
int k = floor(x - q - 1.0D); int k = floor(x - q - 1.0D);
@ -120,7 +120,7 @@ public class Explosion {
int t = floor(z - q - 1.0D); int t = floor(z - q - 1.0D);
int u = floor(z + q + 1.0D); int u = floor(z + q + 1.0D);
for (TNT currentTNT : Simulator19.tntList) { for (TNT currentTNT : simulatorData.tntList) {
if (currentTNT == tnt) continue; if (currentTNT == tnt) continue;
if (!(currentTNT.getX() >= k && currentTNT.getY() >= r && currentTNT.getZ() >= t && currentTNT.getX() <= l && currentTNT.getY() <= s && currentTNT.getZ() <= u)) { if (!(currentTNT.getX() >= k && currentTNT.getY() >= r && currentTNT.getZ() >= t && currentTNT.getX() <= l && currentTNT.getY() <= s && currentTNT.getZ() <= u)) {
continue; continue;
@ -141,7 +141,7 @@ public class Explosion {
y /= aa; y /= aa;
z /= aa; z /= aa;
double ab = getExposure(this.x, this.y, this.z); double ab = getExposure(simulatorData, this.x, this.y, this.z);
double ac = (1.0 - w) * ab; double ac = (1.0 - w) * ab;
currentTNT.setVx(currentTNT.getVx() + x * ac); currentTNT.setVx(currentTNT.getVx() + x * ac);
currentTNT.setVy(currentTNT.getVy() + y * ac); currentTNT.setVy(currentTNT.getVy() + y * ac);
@ -160,7 +160,7 @@ public class Explosion {
private static final double EXPOSURE_CONSTANT_1 = 1.0 / (SIZE * 2 + 1.0); private static final double EXPOSURE_CONSTANT_1 = 1.0 / (SIZE * 2 + 1.0);
private static final double EXPOSURE_CONSTANT_2 = (1.0 - Math.floor(1.0 / EXPOSURE_CONSTANT_1) * EXPOSURE_CONSTANT_1) / 2.0; private static final double EXPOSURE_CONSTANT_2 = (1.0 - Math.floor(1.0 / EXPOSURE_CONSTANT_1) * EXPOSURE_CONSTANT_1) / 2.0;
private static float getExposure(double x, double y, double z) { private static float getExposure(SimulatorData simulatorData, double x, double y, double z) {
float blockMisses = 0; float blockMisses = 0;
float blockTotal = 0; float blockTotal = 0;
@ -171,7 +171,7 @@ public class Explosion {
double dy = lerp(l, 0.0, SIZE); double dy = lerp(l, 0.0, SIZE);
double dz = lerp(m, MIN_POINT, MAX_POINT) + EXPOSURE_CONSTANT_2; double dz = lerp(m, MIN_POINT, MAX_POINT) + EXPOSURE_CONSTANT_2;
if (rayTrace(x, y, z, dx, dy, dz)) { if (rayTrace(simulatorData, x, y, z, dx, dy, dz)) {
blockMisses++; blockMisses++;
} }
blockTotal++; blockTotal++;
@ -186,7 +186,7 @@ public class Explosion {
return start + delta * (end - start); return start + delta * (end - start);
} }
public static boolean rayTrace(double sX, double sY, double sZ, double dX, double dY, double dZ) { public static boolean rayTrace(SimulatorData simulatorData, double sX, double sY, double sZ, double dX, double dY, double dZ) {
double x = sX; double x = sX;
double y = sY; double y = sY;
double z = sZ; double z = sZ;
@ -194,7 +194,7 @@ public class Explosion {
int oY = sY > dY ? -1 : 1; int oY = sY > dY ? -1 : 1;
int oZ = sZ > dZ ? -1 : 1; int oZ = sZ > dZ ? -1 : 1;
while (true) { while (true) {
if (Simulator19.getBlockType(floor(x), floor(y), floor(z)) != Material.AIR) { if (simulatorData.getBlockType(floor(x), floor(y), floor(z)) != Material.AIR) {
return true; return true;
} }

Datei anzeigen

@ -92,38 +92,38 @@ public class OptimizedAxisMovementLimiter {
movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
} }
public double run() { public double run(SimulatorData simulatorData) {
if (movement == 0.0) return 0.0; if (movement == 0.0) return 0.0;
switch (axis) { switch (axis) {
case X: case X:
if (movement < 0.0) { if (movement < 0.0) {
return runNX(); return runNX(simulatorData);
} else { } else {
return runPX(); return runPX(simulatorData);
} }
case Y: case Y:
if (movement < 0.0) { if (movement < 0.0) {
return runNY(); return runNY(simulatorData);
} else { } else {
return runPY(); return runPY(simulatorData);
} }
case Z: case Z:
default: default:
if (movement < 0.0) { if (movement < 0.0) {
return runNZ(); return runNZ(simulatorData);
} else { } else {
return runPZ(); return runPZ(simulatorData);
} }
} }
} }
private double runNX() { private double runNX(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int x = maxIX - 1; x >= minIX; x--) { for (int x = maxIX - 1; x >= minIX; x--) {
for (int y = minIY; y < maxIY; y++) { for (int y = minIY; y < maxIY; y++) {
for (int z = minIZ; z < maxIZ; z++) { for (int z = minIZ; z < maxIZ; z++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;
@ -147,13 +147,13 @@ public class OptimizedAxisMovementLimiter {
return movement + (collision - minX); return movement + (collision - minX);
} }
private double runPX() { private double runPX(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int x = minIX; x < maxIX; x++) { for (int x = minIX; x < maxIX; x++) {
for (int y = minIY; y < maxIY; y++) { for (int y = minIY; y < maxIY; y++) {
for (int z = minIZ; z < maxIZ; z++) { for (int z = minIZ; z < maxIZ; z++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;
@ -177,13 +177,13 @@ public class OptimizedAxisMovementLimiter {
return movement + (collision - minX); return movement + (collision - minX);
} }
private double runNY() { private double runNY(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int y = maxIY - 1; y >= minIY; y--) { for (int y = maxIY - 1; y >= minIY; y--) {
for (int x = minIX; x < maxIX; x++) { for (int x = minIX; x < maxIX; x++) {
for (int z = minIZ; z < maxIZ; z++) { for (int z = minIZ; z < maxIZ; z++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;
@ -207,13 +207,13 @@ public class OptimizedAxisMovementLimiter {
return movement + (collision - minY); return movement + (collision - minY);
} }
private double runPY() { private double runPY(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int y = minIY; y < maxIY; y++) { for (int y = minIY; y < maxIY; y++) {
for (int x = minIX; x < maxIX; x++) { for (int x = minIX; x < maxIX; x++) {
for (int z = minIZ; z < maxIZ; z++) { for (int z = minIZ; z < maxIZ; z++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;
@ -237,13 +237,13 @@ public class OptimizedAxisMovementLimiter {
return movement + (collision - minY); return movement + (collision - minY);
} }
private double runNZ() { private double runNZ(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int z = maxIZ - 1; z >= minIZ; z--) { for (int z = maxIZ - 1; z >= minIZ; z--) {
for (int x = minIX; x < maxIX; x++) { for (int x = minIX; x < maxIX; x++) {
for (int y = minIY; y < maxIY; y++) { for (int y = minIY; y < maxIY; y++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;
@ -267,13 +267,13 @@ public class OptimizedAxisMovementLimiter {
return movement + (collision - minZ); return movement + (collision - minZ);
} }
private double runPZ() { private double runPZ(SimulatorData simulatorData) {
Double collision = null; Double collision = null;
for (int z = minIZ; z < maxIZ; z++) { for (int z = minIZ; z < maxIZ; z++) {
for (int x = minIX; x < maxIX; x++) { for (int x = minIX; x < maxIX; x++) {
for (int y = minIY; y < maxIY; y++) { for (int y = minIY; y < maxIY; y++) {
Pos pos = new Pos(x, y, z); Pos pos = new Pos(x, y, z);
VoxelShape voxelShape = Simulator19.getVoxelShape(pos); VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) { for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
boundingBox = boundingBox.clone().shift(x, y, z); boundingBox = boundingBox.clone().shift(x, y, z);
if (!boundingBox.overlaps(movementBoundingBox)) continue; if (!boundingBox.overlaps(movementBoundingBox)) continue;

Datei anzeigen

@ -19,18 +19,20 @@
package de.steamwar.bausystem.features.simulator.preview; package de.steamwar.bausystem.features.simulator.preview;
import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.TNTData; import de.steamwar.bausystem.features.simulator.TNTData;
import de.steamwar.bausystem.features.tracer.show.Record; import de.steamwar.bausystem.features.tracer.show.Record;
import de.steamwar.bausystem.shared.Pair; import de.steamwar.bausystem.shared.Pair;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.BoundingBox; import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.bukkit.util.VoxelShape;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -38,126 +40,67 @@ public class Simulator19 implements Simulator {
protected static final World WORLD = Bukkit.getWorlds().get(0); protected static final World WORLD = Bukkit.getWorlds().get(0);
private static final BlockData AIR_BLOCK_DATA = Material.AIR.createBlockData();
private static final VoxelShape AIR_VOXEL_SHAPE = new VoxelShape() {
@Override
public Collection<BoundingBox> getBoundingBoxes() {
return Collections.emptyList();
}
@Override
public boolean overlaps(BoundingBox boundingBox) {
return false;
}
};
private static long accessed = 0;
private static long cacheMisses = 0;
private static long aired = 0;
static final List<TNT> tntList = new ArrayList<>();
private static final Set<Pos> AIR_BLOCKS = new HashSet<>();
private static final Map<Pos, Material> BLOCK_TYPES_MAP = new HashMap<>();
private static final Map<Pos, BlockData> BLOCK_DATA_MAP = new HashMap<>();
private static final Map<Pos, VoxelShape> COLLISION_DATA_MAP = new HashMap<>();
@Override @Override
public void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) { // TODO: Implement multi tick calculation max 40 ms per tick public BukkitTask run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) { // TODO: Implement multi tick calculation max 40 ms per tick
if (toCalculate == null) return; if (toCalculate == null) return null;
PreviewRecord previewRecord = new PreviewRecord();
int currentTick = 0;
Map<TNT, Record.TNTRecord> recordMap = new HashMap<>(); BukkitRunnable bukkitRunnable = new BukkitRunnable() {
long time = System.currentTimeMillis(); private SimulatorData simulatorData = new SimulatorData();
while (!tntList.isEmpty() || currentTick <= toCalculate.getKey()) { private PreviewRecord previewRecord = new PreviewRecord();
List<List<Pair<TNTData, Integer>>> toSpawnInTick = toCalculate.getValue().get(currentTick); private int currentTick = 0;
if (toSpawnInTick != null) { private Map<TNT, Record.TNTRecord> recordMap = new HashMap<>();
int finalCurrentTick = currentTick;
toSpawnInTick.forEach(pairs -> { @Override
AtomicBoolean hasSomeLeft = new AtomicBoolean(true); public void run() {
while(hasSomeLeft.get()) { long time = System.currentTimeMillis();
hasSomeLeft.set(false); while (!simulatorData.tntList.isEmpty() || currentTick <= toCalculate.getKey() && System.currentTimeMillis() - time < 40) {
pairs.forEach(pair -> { List<List<Pair<TNTData, Integer>>> toSpawnInTick = toCalculate.getValue().get(currentTick);
if (pair.getValue() > 0) { if (toSpawnInTick != null) {
hasSomeLeft.set(true); int finalCurrentTick = currentTick;
TNT tnt = new TNT(pair.getKey().location.getX(), pair.getKey().location.getY(), pair.getKey().location.getZ()); toSpawnInTick.forEach(pairs -> {
if (!pair.getKey().xVelocity) tnt.setVx(0.0); AtomicBoolean hasSomeLeft = new AtomicBoolean(true);
if (!pair.getKey().yVelocity) tnt.setVy(0.0); while(hasSomeLeft.get()) {
if (!pair.getKey().zVelocity) tnt.setVz(0.0); hasSomeLeft.set(false);
tnt.setFuse(tnt.getFuse()); pairs.forEach(pair -> {
tntList.add(tnt); if (pair.getValue() > 0) {
pair.setValue(pair.getValue() - 1); hasSomeLeft.set(true);
Record.TNTRecord record = previewRecord.getRecord().spawn(finalCurrentTick); TNT tnt = new TNT(pair.getKey().location.getX(), pair.getKey().location.getY(), pair.getKey().location.getZ());
record.source(pair.getKey().location.toVector(), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse()); if (!pair.getKey().xVelocity) tnt.setVx(0.0);
recordMap.put(tnt, record); if (!pair.getKey().yVelocity) tnt.setVy(0.0);
if (!pair.getKey().zVelocity) tnt.setVz(0.0);
tnt.setFuse(tnt.getFuse());
simulatorData.tntList.add(tnt);
pair.setValue(pair.getValue() - 1);
Record.TNTRecord record = previewRecord.getRecord().spawn(finalCurrentTick);
record.source(pair.getKey().location.toVector(), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse());
recordMap.put(tnt, record);
}
});
} }
}); });
} }
}); currentTick++;
}
currentTick++;
List<TNT> remove = new ArrayList<>(); List<TNT> remove = new ArrayList<>();
for (TNT tnt : tntList) { for (TNT tnt : simulatorData.tntList) {
if (tnt.tick()) { if (tnt.tick(simulatorData)) {
remove.add(tnt); remove.add(tnt);
recordMap.remove(tnt).explode(new Vector(tnt.getX(), tnt.getY(), tnt.getZ()), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse()); recordMap.remove(tnt).explode(new Vector(tnt.getX(), tnt.getY(), tnt.getZ()), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse());
} else { } else {
recordMap.get(tnt).location(new Vector(tnt.getX(), tnt.getY(), tnt.getZ()), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse()); recordMap.get(tnt).location(new Vector(tnt.getX(), tnt.getY(), tnt.getZ()), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse());
}
}
simulatorData.tntList.removeAll(remove);
}
System.out.println("Time: " + (System.currentTimeMillis() - time) + "ms " + simulatorData.cacheMisses + "/" + simulatorData.accessed + "/" + simulatorData.aired);
if (simulatorData.tntList.isEmpty() && currentTick <= toCalculate.getKey()) {
simulatorData.airBlocks.forEach(pos -> previewRecord.addAir(new Vector(pos.x, pos.y, pos.z)));
consumer.accept(previewRecord);
cancel();
} }
} }
tntList.removeAll(remove); };
} return bukkitRunnable.runTaskTimer(BauSystem.getInstance(), 0, 1);
AIR_BLOCKS.forEach(pos -> previewRecord.addAir(new Vector(pos.x, pos.y, pos.z)));
System.out.println("Time: " + (System.currentTimeMillis() - time) + "ms " + cacheMisses + "/" + accessed + "/" + aired);
AIR_BLOCKS.clear();
BLOCK_TYPES_MAP.clear();
BLOCK_DATA_MAP.clear();
COLLISION_DATA_MAP.clear();
accessed = 0;
cacheMisses = 0;
aired = 0;
consumer.accept(previewRecord);
}
public static Material getBlockType(int x, int y, int z) { // Get BlockType of Chunk Data array?
accessed++;
Pos pos = new Pos(x, y, z);
if (AIR_BLOCKS.contains(pos)) {
return Material.AIR;
}
return BLOCK_TYPES_MAP.computeIfAbsent(pos, v -> {
cacheMisses++;
return WORLD.getBlockAt(x, y, z).getType();
});
}
public static BlockData getBlockData(int x, int y, int z) {
accessed++;
return BLOCK_DATA_MAP.computeIfAbsent(new Pos(x, y, z), v -> {
cacheMisses++;
return WORLD.getBlockAt(x, y, z).getBlockData();
});
}
public static VoxelShape getVoxelShape(Pos pos) {
accessed++;
if (AIR_BLOCKS.contains(pos)) {
return AIR_VOXEL_SHAPE;
}
return COLLISION_DATA_MAP.computeIfAbsent(pos, v -> {
cacheMisses++;
return WORLD.getBlockAt(pos.x, pos.y, pos.z).getCollisionShape();
});
}
public static void clearBlock(Pos pos) {
aired++;
AIR_BLOCKS.add(pos);
BlockData blockData = BLOCK_DATA_MAP.put(pos, AIR_BLOCK_DATA);
}
public static void clearBlocks(Set<Pos> poss) { // TODO: Optimize
poss.forEach(Simulator19::clearBlock);
} }
} }

Datei anzeigen

@ -0,0 +1,93 @@
/*
* 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.preview;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.VoxelShape;
import java.util.*;
public class SimulatorData {
private static final BlockData AIR_BLOCK_DATA = Material.AIR.createBlockData();
private static final VoxelShape AIR_VOXEL_SHAPE = new VoxelShape() {
@Override
public Collection<BoundingBox> getBoundingBoxes() {
return Collections.emptyList();
}
@Override
public boolean overlaps(BoundingBox boundingBox) {
return false;
}
};
long accessed = 0;
long cacheMisses = 0;
long aired = 0;
final List<TNT> tntList = new ArrayList<>();
final Set<Pos> airBlocks = new HashSet<>();
final Map<Pos, Material> blockTypesMap = new HashMap<>();
final Map<Pos, BlockData> blockDataMap = new HashMap<>();
final Map<Pos, VoxelShape> collisionDataMap = new HashMap<>();
public Material getBlockType(int x, int y, int z) { // Get BlockType of Chunk Data array?
accessed++;
Pos pos = new Pos(x, y, z);
if (airBlocks.contains(pos)) {
return Material.AIR;
}
return blockTypesMap.computeIfAbsent(pos, v -> {
cacheMisses++;
return Simulator19.WORLD.getBlockAt(x, y, z).getType();
});
}
public BlockData getBlockData(int x, int y, int z) {
accessed++;
return blockDataMap.computeIfAbsent(new Pos(x, y, z), v -> {
cacheMisses++;
return Simulator19.WORLD.getBlockAt(x, y, z).getBlockData();
});
}
public VoxelShape getVoxelShape(Pos pos) {
accessed++;
if (airBlocks.contains(pos)) {
return AIR_VOXEL_SHAPE;
}
return collisionDataMap.computeIfAbsent(pos, v -> {
cacheMisses++;
return Simulator19.WORLD.getBlockAt(pos.x, pos.y, pos.z).getCollisionShape();
});
}
public void clearBlock(Pos pos) {
aired++;
airBlocks.add(pos);
blockDataMap.put(pos, AIR_BLOCK_DATA);
}
public void clearBlocks(Set<Pos> poss) { // TODO: Optimize
poss.forEach(this::clearBlock);
}
}

Datei anzeigen

@ -71,10 +71,10 @@ public class TNT {
this.fuse = 80; this.fuse = 80;
} }
public boolean tick() { public boolean tick(SimulatorData simulatorData) {
this.vy -= 0.04; this.vy -= 0.04;
move(new Vector(this.vx, this.vy, this.vz)); move(simulatorData, new Vector(this.vx, this.vy, this.vz));
this.vx *= 0.98; this.vx *= 0.98;
this.vy *= 0.98; this.vy *= 0.98;
@ -83,13 +83,13 @@ public class TNT {
this.fuse--; this.fuse--;
if (this.fuse <= 0) { if (this.fuse <= 0) {
Explosion explosion = new Explosion(this, x, y + 0.98 * 0.0625, z); Explosion explosion = new Explosion(this, x, y + 0.98 * 0.0625, z);
explosion.calculate(); explosion.calculate(simulatorData);
return true; return true;
} }
return false; return false;
} }
private void move(Vector movement) { private void move(SimulatorData simulatorData, Vector movement) {
if (movementMultiplier.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);
@ -98,7 +98,7 @@ public class TNT {
vz = 0; vz = 0;
} }
Vector vec3d = adjustMovementForCollisions(movement); Vector vec3d = adjustMovementForCollisions(simulatorData, movement);
// System.out.println(movement + " " + vec3d); // System.out.println(movement + " " + vec3d);
double lengthSquared = vec3d.lengthSquared(); double lengthSquared = vec3d.lengthSquared();
if (lengthSquared > 1.0E-7) { if (lengthSquared > 1.0E-7) {
@ -121,9 +121,9 @@ public class TNT {
this.verticalCollision = movement.getY() != vec3d.getY(); this.verticalCollision = movement.getY() != vec3d.getY();
this.onGround = this.verticalCollision && movement.getY() < 0.0D; this.onGround = this.verticalCollision && movement.getY() < 0.0D;
Vector blockPos = getLandingPos(); Vector blockPos = getLandingPos(simulatorData);
Material material = Simulator19.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ()); Material material = simulatorData.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
BlockData blockData = Simulator19.getBlockData(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ()); BlockData blockData = simulatorData.getBlockData(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
fall(vec3d.getY(), onGround); fall(vec3d.getY(), onGround);
if (horizontalCollision) { if (horizontalCollision) {
@ -154,27 +154,27 @@ public class TNT {
} }
} }
checkBlockCollision(); checkBlockCollision(simulatorData);
float j = this.getVelocityMultiplier(); float j = this.getVelocityMultiplier(simulatorData);
this.vx *= j; this.vx *= j;
this.vz *= j; this.vz *= j;
} }
private Vector adjustMovementForCollisions(Vector movement) { private Vector adjustMovementForCollisions(SimulatorData simulatorData, Vector movement) {
if (movement.lengthSquared() == 0.0) { if (movement.lengthSquared() == 0.0) {
return movement; return movement;
} }
double mY = new AxisMovementLimiter(x, y, z, Axis.Y, movement.getY()).run(); double mY = new AxisMovementLimiter(x, y, z, Axis.Y, movement.getY()).run(simulatorData);
boolean bl = Math.abs(movement.getX()) < Math.abs(movement.getZ()); boolean bl = Math.abs(movement.getX()) < Math.abs(movement.getZ());
if (bl) { if (bl) {
double mZ = new AxisMovementLimiter(x, y + mY, z, Axis.Z, movement.getZ()).run(); double mZ = new AxisMovementLimiter(x, y + mY, z, Axis.Z, movement.getZ()).run(simulatorData);
double mX = new AxisMovementLimiter(x, y + mY, z + mZ, Axis.X, movement.getX()).run(); double mX = new AxisMovementLimiter(x, y + mY, z + mZ, Axis.X, movement.getX()).run(simulatorData);
return new Vector(mX, mY, mZ); return new Vector(mX, mY, mZ);
} else { } else {
double mX = new AxisMovementLimiter(x, y + mY, z, Axis.X, movement.getX()).run(); double mX = new AxisMovementLimiter(x, y + mY, z, Axis.X, movement.getX()).run(simulatorData);
double mZ = new AxisMovementLimiter(x + mX, y + mY, z, Axis.Z, movement.getZ()).run(); double mZ = new AxisMovementLimiter(x + mX, y + mY, z, Axis.Z, movement.getZ()).run(simulatorData);
return new Vector(mX, mY, mZ); return new Vector(mX, mY, mZ);
} }
} }
@ -188,13 +188,13 @@ public class TNT {
return value < (double)i ? i - 1 : i; return value < (double)i ? i - 1 : i;
} }
private Vector getLandingPos() { private Vector getLandingPos(SimulatorData simulatorData) {
int x = floor(this.x); int x = floor(this.x);
int y = floor(this.y - 0.2F); int y = floor(this.y - 0.2F);
int z = floor(this.z); int z = floor(this.z);
if (Simulator19.getBlockType(x, y, z).isAir()) { if (simulatorData.getBlockType(x, y, z).isAir()) {
BlockData blockData = Simulator19.getBlockData(x, y - 1, z); BlockData blockData = simulatorData.getBlockData(x, y - 1, z);
if (blockData instanceof Fence || blockData instanceof Wall || blockData instanceof Gate) { if (blockData instanceof Fence || blockData instanceof Wall || blockData instanceof Gate) {
return new Vector(x, y - 1, z); return new Vector(x, y - 1, z);
} }
@ -210,7 +210,7 @@ public class TNT {
} }
} }
private void checkBlockCollision() { private void checkBlockCollision(SimulatorData simulatorData) {
int x1 = floor(x + 1.0E-7); int x1 = floor(x + 1.0E-7);
int y1 = floor(y + 1.0E-7); int y1 = floor(y + 1.0E-7);
int z1 = floor(z + 1.0E-7); int z1 = floor(z + 1.0E-7);
@ -221,7 +221,7 @@ public class TNT {
for (int x = x1; x <= x2; x++) { for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) { for (int y = y1; y <= y2; y++) {
for (int z = z1; z <= z2; z++) { for (int z = z1; z <= z2; z++) {
Material material = Simulator19.getBlockType(x, y, z); Material material = simulatorData.getBlockType(x, y, z);
if (material == Material.POWDER_SNOW) { if (material == Material.POWDER_SNOW) {
slowMovement(new Vector(0.8999999761581421, 1.5, 0.8999999761581421)); slowMovement(new Vector(0.8999999761581421, 1.5, 0.8999999761581421));
@ -232,8 +232,8 @@ public class TNT {
} else if (material == Material.COBWEB) { } else if (material == Material.COBWEB) {
slowMovement(new Vector(0.25, 0.05000000074505806, 0.25)); slowMovement(new Vector(0.25, 0.05000000074505806, 0.25));
} else if (material == Material.BUBBLE_COLUMN) { } else if (material == Material.BUBBLE_COLUMN) {
boolean drag = ((BubbleColumn) Simulator19.getBlockData(x, y, z)).isDrag(); boolean drag = ((BubbleColumn) simulatorData.getBlockData(x, y, z)).isDrag();
if (Simulator19.getBlockType(x, y + 1, z).isAir()) { if (simulatorData.getBlockType(x, y + 1, z).isAir()) {
if (drag) { if (drag) {
this.vy = Math.max(-0.9, vy - 0.03); this.vy = Math.max(-0.9, vy - 0.03);
} else { } else {
@ -278,8 +278,8 @@ public class TNT {
return d + 1.0E-7 > f || e + 1.0E-7 > f; return d + 1.0E-7 > f || e + 1.0E-7 > f;
} }
private float getVelocityMultiplier() { private float getVelocityMultiplier(SimulatorData simulatorData) {
Material material = Simulator19.getBlockType(floor(x), floor(y), floor(z)); Material material = simulatorData.getBlockType(floor(x), floor(y), floor(z));
float f = 1F; float f = 1F;
if (material == Material.SOUL_SAND) { if (material == Material.SOUL_SAND) {
f = 0.5F; f = 0.5F;
@ -288,7 +288,7 @@ public class TNT {
} }
if (material != Material.WATER && material != Material.BUBBLE_COLUMN) { if (material != Material.WATER && material != Material.BUBBLE_COLUMN) {
if (f != 1) return f; if (f != 1) return f;
material = Simulator19.getBlockType(floor(x), floor(y - 0.5000001), floor(z)); material = simulatorData.getBlockType(floor(x), floor(y - 0.5000001), floor(z));
if (material == Material.SOUL_SAND) { if (material == Material.SOUL_SAND) {
f = 0.5F; f = 0.5F;
} else if (material == Material.HONEY_BLOCK) { } else if (material == Material.HONEY_BLOCK) {

Datei anzeigen

@ -19,17 +19,5 @@
package de.steamwar.bausystem.features.simulator.preview; package de.steamwar.bausystem.features.simulator.preview;
import de.steamwar.bausystem.features.simulator.TNTData;
import de.steamwar.bausystem.shared.Pair;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class Simulator20 implements Simulator { public class Simulator20 implements Simulator {
@Override
public void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) {
consumer.accept(null);
}
} }

Datei anzeigen

@ -40,6 +40,7 @@ import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed; import org.bukkit.entity.TNTPrimed;
import org.bukkit.scheduler.BukkitTask;
import yapion.hierarchy.types.YAPIONArray; import yapion.hierarchy.types.YAPIONArray;
import yapion.hierarchy.types.YAPIONObject; import yapion.hierarchy.types.YAPIONObject;
import yapion.hierarchy.types.YAPIONType; import yapion.hierarchy.types.YAPIONType;
@ -49,17 +50,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter
public class TNTSimulator { public class TNTSimulator {
@Getter
private Set<Player> players = new HashSet<>(); private Set<Player> players = new HashSet<>();
@Getter
private REntityServer entityServer = new REntityServer(); private REntityServer entityServer = new REntityServer();
@Getter
private Material material = Material.TNT; private Material material = Material.TNT;
@Getter
private List<SimulatorElement> tntElementList = new ArrayList<>(); private List<SimulatorElement> tntElementList = new ArrayList<>();
private boolean currentlyCalculating = false; private List<Player> toShow = new ArrayList<>();
private BukkitTask currentlyCalculating = null;
private PreviewRecord previewRecord = null; private PreviewRecord previewRecord = null;
public TNTSimulator() { public TNTSimulator() {
@ -108,17 +114,21 @@ public class TNTSimulator {
} }
public void showPreview(Player player) { public void showPreview(Player player) {
if (previewRecord == null) {
calcPreview(true);
}
if (previewRecord != null) { if (previewRecord != null) {
previewRecord.show(player); previewRecord.show(player);
return;
} }
toShow.add(player);
calcPreview(true);
} }
public void hidePreview(Player player) { public void hidePreview(Player player) {
if (previewRecord != null && previewRecord.hide(player)) { if (previewRecord != null && previewRecord.hide(player)) {
previewRecord = null; previewRecord = null;
if (currentlyCalculating != null) {
currentlyCalculating.cancel();
currentlyCalculating = null;
}
} }
} }
@ -130,27 +140,24 @@ public class TNTSimulator {
if (!force && previewRecord == null) { if (!force && previewRecord == null) {
return; return;
} }
if (currentlyCalculating) return; if (currentlyCalculating != null) currentlyCalculating.cancel();
currentlyCalculating = true; currentlyCalculating = Simulator.impl.run(locations(true), newRecord -> {
currentlyCalculating = null;
Simulator.impl.run(locations(true), newRecord -> {
boolean recalculate = currentlyCalculating;
currentlyCalculating = false;
PreviewRecord oldRecord = previewRecord; PreviewRecord oldRecord = previewRecord;
previewRecord = newRecord; previewRecord = newRecord;
if (newRecord == null) return; if (newRecord == null) {
toShow.clear();
return;
}
if (oldRecord != null) { if (oldRecord != null) {
oldRecord.getPlayers().forEach(player -> { oldRecord.getPlayers().forEach(player -> {
oldRecord.hide(player); oldRecord.hide(player);
newRecord.show(player); newRecord.show(player);
}); });
} }
if (recalculate) { toShow.forEach(newRecord::show);
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { toShow.clear();
calcPreview(force);
}, 1);
}
}); });
} }

Datei anzeigen

@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.features.simulator.TNTData; import de.steamwar.bausystem.features.simulator.TNTData;
import de.steamwar.bausystem.shared.Pair; import de.steamwar.bausystem.shared.Pair;
import de.steamwar.core.VersionDependent; import de.steamwar.core.VersionDependent;
import org.bukkit.scheduler.BukkitTask;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -31,5 +32,7 @@ import java.util.function.Consumer;
public interface Simulator { public interface Simulator {
Simulator impl = VersionDependent.getVersionImpl(BauSystem.getInstance()); Simulator impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> finished); default BukkitTask run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> finished) {
return null;
}
} }