Signed-off-by: yoyosource <yoyosource@nidido.de>
Dieser Commit ist enthalten in:
Ursprung
d09c4970a0
Commit
4fbbdf3a49
@ -19,17 +19,5 @@
|
||||
|
||||
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 {
|
||||
|
||||
@Override
|
||||
public void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) {
|
||||
consumer.accept(null);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class AxisMovementLimiter {
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
BoundingBox movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
@ -112,7 +112,7 @@ public class AxisMovementLimiter {
|
||||
|
||||
Double collision = null;
|
||||
for (Pos pos : poss) {
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(pos.x, pos.y, pos.z);
|
||||
boolean collides = boundingBox.overlaps(movementBoundingBox);
|
||||
|
@ -73,7 +73,7 @@ public class Explosion {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void calculate() {
|
||||
public void calculate(SimulatorData simulatorData) {
|
||||
Set<Pos> affectedBlocks = new HashSet<>();
|
||||
for (int i = 0; i < FACE_BLOCKS.length; i += 3) {
|
||||
double d = FACE_BLOCKS[i + 0];
|
||||
@ -90,12 +90,12 @@ public class Explosion {
|
||||
int y = TNT.floor(n);
|
||||
int z = TNT.floor(o);
|
||||
|
||||
Material material = Simulator19.getBlockType(x, y, z);
|
||||
Material material = simulatorData.getBlockType(x, y, z);
|
||||
if (!material.isAir()) {
|
||||
h -= (material.getBlastResistance() + 0.3F) * 0.3F;
|
||||
}
|
||||
if (WATER_LOGABLE.contains(material)) {
|
||||
Waterlogged waterlogged = (Waterlogged) Simulator19.getBlockData(x, y, z);
|
||||
Waterlogged waterlogged = (Waterlogged) simulatorData.getBlockData(x, y, z);
|
||||
if (waterlogged.isWaterlogged()) {
|
||||
h = 0.0F;
|
||||
}
|
||||
@ -110,7 +110,7 @@ public class Explosion {
|
||||
o += f * 0.30000001192092896;
|
||||
}
|
||||
}
|
||||
Simulator19.clearBlocks(affectedBlocks);
|
||||
simulatorData.clearBlocks(affectedBlocks);
|
||||
|
||||
float q = POWER * 2.0F;
|
||||
int k = floor(x - q - 1.0D);
|
||||
@ -120,7 +120,7 @@ public class Explosion {
|
||||
int t = 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.getX() >= k && currentTNT.getY() >= r && currentTNT.getZ() >= t && currentTNT.getX() <= l && currentTNT.getY() <= s && currentTNT.getZ() <= u)) {
|
||||
continue;
|
||||
@ -141,7 +141,7 @@ public class Explosion {
|
||||
y /= 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;
|
||||
currentTNT.setVx(currentTNT.getVx() + x * 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_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 blockTotal = 0;
|
||||
|
||||
@ -171,7 +171,7 @@ public class Explosion {
|
||||
double dy = lerp(l, 0.0, SIZE);
|
||||
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++;
|
||||
}
|
||||
blockTotal++;
|
||||
@ -186,7 +186,7 @@ public class Explosion {
|
||||
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 y = sY;
|
||||
double z = sZ;
|
||||
@ -194,7 +194,7 @@ public class Explosion {
|
||||
int oY = sY > dY ? -1 : 1;
|
||||
int oZ = sZ > dZ ? -1 : 1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -92,38 +92,38 @@ public class OptimizedAxisMovementLimiter {
|
||||
movementBoundingBox = new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public double run() {
|
||||
public double run(SimulatorData simulatorData) {
|
||||
if (movement == 0.0) return 0.0;
|
||||
switch (axis) {
|
||||
case X:
|
||||
if (movement < 0.0) {
|
||||
return runNX();
|
||||
return runNX(simulatorData);
|
||||
} else {
|
||||
return runPX();
|
||||
return runPX(simulatorData);
|
||||
}
|
||||
case Y:
|
||||
if (movement < 0.0) {
|
||||
return runNY();
|
||||
return runNY(simulatorData);
|
||||
} else {
|
||||
return runPY();
|
||||
return runPY(simulatorData);
|
||||
}
|
||||
case Z:
|
||||
default:
|
||||
if (movement < 0.0) {
|
||||
return runNZ();
|
||||
return runNZ(simulatorData);
|
||||
} else {
|
||||
return runPZ();
|
||||
return runPZ(simulatorData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private double runNX() {
|
||||
private double runNX(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int x = maxIX - 1; x >= minIX; x--) {
|
||||
for (int y = minIY; y < maxIY; y++) {
|
||||
for (int z = minIZ; z < maxIZ; z++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
@ -147,13 +147,13 @@ public class OptimizedAxisMovementLimiter {
|
||||
return movement + (collision - minX);
|
||||
}
|
||||
|
||||
private double runPX() {
|
||||
private double runPX(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int x = minIX; x < maxIX; x++) {
|
||||
for (int y = minIY; y < maxIY; y++) {
|
||||
for (int z = minIZ; z < maxIZ; z++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
@ -177,13 +177,13 @@ public class OptimizedAxisMovementLimiter {
|
||||
return movement + (collision - minX);
|
||||
}
|
||||
|
||||
private double runNY() {
|
||||
private double runNY(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int y = maxIY - 1; y >= minIY; y--) {
|
||||
for (int x = minIX; x < maxIX; x++) {
|
||||
for (int z = minIZ; z < maxIZ; z++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
@ -207,13 +207,13 @@ public class OptimizedAxisMovementLimiter {
|
||||
return movement + (collision - minY);
|
||||
}
|
||||
|
||||
private double runPY() {
|
||||
private double runPY(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int y = minIY; y < maxIY; y++) {
|
||||
for (int x = minIX; x < maxIX; x++) {
|
||||
for (int z = minIZ; z < maxIZ; z++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
@ -237,13 +237,13 @@ public class OptimizedAxisMovementLimiter {
|
||||
return movement + (collision - minY);
|
||||
}
|
||||
|
||||
private double runNZ() {
|
||||
private double runNZ(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int z = maxIZ - 1; z >= minIZ; z--) {
|
||||
for (int x = minIX; x < maxIX; x++) {
|
||||
for (int y = minIY; y < maxIY; y++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
@ -267,13 +267,13 @@ public class OptimizedAxisMovementLimiter {
|
||||
return movement + (collision - minZ);
|
||||
}
|
||||
|
||||
private double runPZ() {
|
||||
private double runPZ(SimulatorData simulatorData) {
|
||||
Double collision = null;
|
||||
for (int z = minIZ; z < maxIZ; z++) {
|
||||
for (int x = minIX; x < maxIX; x++) {
|
||||
for (int y = minIY; y < maxIY; y++) {
|
||||
Pos pos = new Pos(x, y, z);
|
||||
VoxelShape voxelShape = Simulator19.getVoxelShape(pos);
|
||||
VoxelShape voxelShape = simulatorData.getVoxelShape(pos);
|
||||
for (BoundingBox boundingBox : voxelShape.getBoundingBoxes()) {
|
||||
boundingBox = boundingBox.clone().shift(x, y, z);
|
||||
if (!boundingBox.overlaps(movementBoundingBox)) continue;
|
||||
|
@ -19,18 +19,20 @@
|
||||
|
||||
package de.steamwar.bausystem.features.simulator.preview;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.simulator.TNTData;
|
||||
import de.steamwar.bausystem.features.tracer.show.Record;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
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.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
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.function.Consumer;
|
||||
|
||||
@ -38,126 +40,67 @@ public class Simulator19 implements Simulator {
|
||||
|
||||
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
|
||||
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
|
||||
if (toCalculate == null) return;
|
||||
PreviewRecord previewRecord = new PreviewRecord();
|
||||
int currentTick = 0;
|
||||
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 null;
|
||||
|
||||
Map<TNT, Record.TNTRecord> recordMap = new HashMap<>();
|
||||
long time = System.currentTimeMillis();
|
||||
while (!tntList.isEmpty() || currentTick <= toCalculate.getKey()) {
|
||||
List<List<Pair<TNTData, Integer>>> toSpawnInTick = toCalculate.getValue().get(currentTick);
|
||||
if (toSpawnInTick != null) {
|
||||
int finalCurrentTick = currentTick;
|
||||
toSpawnInTick.forEach(pairs -> {
|
||||
AtomicBoolean hasSomeLeft = new AtomicBoolean(true);
|
||||
while(hasSomeLeft.get()) {
|
||||
hasSomeLeft.set(false);
|
||||
pairs.forEach(pair -> {
|
||||
if (pair.getValue() > 0) {
|
||||
hasSomeLeft.set(true);
|
||||
TNT tnt = new TNT(pair.getKey().location.getX(), pair.getKey().location.getY(), pair.getKey().location.getZ());
|
||||
if (!pair.getKey().xVelocity) tnt.setVx(0.0);
|
||||
if (!pair.getKey().yVelocity) tnt.setVy(0.0);
|
||||
if (!pair.getKey().zVelocity) tnt.setVz(0.0);
|
||||
tnt.setFuse(tnt.getFuse());
|
||||
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);
|
||||
BukkitRunnable bukkitRunnable = new BukkitRunnable() {
|
||||
private SimulatorData simulatorData = new SimulatorData();
|
||||
private PreviewRecord previewRecord = new PreviewRecord();
|
||||
private int currentTick = 0;
|
||||
private Map<TNT, Record.TNTRecord> recordMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long time = System.currentTimeMillis();
|
||||
while (!simulatorData.tntList.isEmpty() || currentTick <= toCalculate.getKey() && System.currentTimeMillis() - time < 40) {
|
||||
List<List<Pair<TNTData, Integer>>> toSpawnInTick = toCalculate.getValue().get(currentTick);
|
||||
if (toSpawnInTick != null) {
|
||||
int finalCurrentTick = currentTick;
|
||||
toSpawnInTick.forEach(pairs -> {
|
||||
AtomicBoolean hasSomeLeft = new AtomicBoolean(true);
|
||||
while(hasSomeLeft.get()) {
|
||||
hasSomeLeft.set(false);
|
||||
pairs.forEach(pair -> {
|
||||
if (pair.getValue() > 0) {
|
||||
hasSomeLeft.set(true);
|
||||
TNT tnt = new TNT(pair.getKey().location.getX(), pair.getKey().location.getY(), pair.getKey().location.getZ());
|
||||
if (!pair.getKey().xVelocity) tnt.setVx(0.0);
|
||||
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<>();
|
||||
for (TNT tnt : tntList) {
|
||||
if (tnt.tick()) {
|
||||
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());
|
||||
} else {
|
||||
recordMap.get(tnt).location(new Vector(tnt.getX(), tnt.getY(), tnt.getZ()), new Vector(tnt.getVx(), tnt.getVy(), tnt.getVz()), tnt.getFuse());
|
||||
List<TNT> remove = new ArrayList<>();
|
||||
for (TNT tnt : simulatorData.tntList) {
|
||||
if (tnt.tick(simulatorData)) {
|
||||
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());
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
};
|
||||
return bukkitRunnable.runTaskTimer(BauSystem.getInstance(), 0, 1);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -71,10 +71,10 @@ public class TNT {
|
||||
this.fuse = 80;
|
||||
}
|
||||
|
||||
public boolean tick() {
|
||||
public boolean tick(SimulatorData simulatorData) {
|
||||
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.vy *= 0.98;
|
||||
@ -83,13 +83,13 @@ public class TNT {
|
||||
this.fuse--;
|
||||
if (this.fuse <= 0) {
|
||||
Explosion explosion = new Explosion(this, x, y + 0.98 * 0.0625, z);
|
||||
explosion.calculate();
|
||||
explosion.calculate(simulatorData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void move(Vector movement) {
|
||||
private void move(SimulatorData simulatorData, Vector movement) {
|
||||
if (movementMultiplier.lengthSquared() > 1.0E-7) {
|
||||
movement.multiply(movementMultiplier);
|
||||
movementMultiplier = new Vector(0, 0, 0);
|
||||
@ -98,7 +98,7 @@ public class TNT {
|
||||
vz = 0;
|
||||
}
|
||||
|
||||
Vector vec3d = adjustMovementForCollisions(movement);
|
||||
Vector vec3d = adjustMovementForCollisions(simulatorData, movement);
|
||||
// System.out.println(movement + " " + vec3d);
|
||||
double lengthSquared = vec3d.lengthSquared();
|
||||
if (lengthSquared > 1.0E-7) {
|
||||
@ -121,9 +121,9 @@ public class TNT {
|
||||
this.verticalCollision = movement.getY() != vec3d.getY();
|
||||
|
||||
this.onGround = this.verticalCollision && movement.getY() < 0.0D;
|
||||
Vector blockPos = getLandingPos();
|
||||
Material material = Simulator19.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
||||
BlockData blockData = Simulator19.getBlockData(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
||||
Vector blockPos = getLandingPos(simulatorData);
|
||||
Material material = simulatorData.getBlockType(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
||||
BlockData blockData = simulatorData.getBlockData(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ());
|
||||
fall(vec3d.getY(), onGround);
|
||||
|
||||
if (horizontalCollision) {
|
||||
@ -154,27 +154,27 @@ public class TNT {
|
||||
}
|
||||
}
|
||||
|
||||
checkBlockCollision();
|
||||
float j = this.getVelocityMultiplier();
|
||||
checkBlockCollision(simulatorData);
|
||||
float j = this.getVelocityMultiplier(simulatorData);
|
||||
this.vx *= j;
|
||||
this.vz *= j;
|
||||
}
|
||||
|
||||
private Vector adjustMovementForCollisions(Vector movement) {
|
||||
private Vector adjustMovementForCollisions(SimulatorData simulatorData, Vector movement) {
|
||||
if (movement.lengthSquared() == 0.0) {
|
||||
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());
|
||||
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();
|
||||
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(simulatorData);
|
||||
return new Vector(mX, mY, mZ);
|
||||
} else {
|
||||
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();
|
||||
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(simulatorData);
|
||||
return new Vector(mX, mY, mZ);
|
||||
}
|
||||
}
|
||||
@ -188,13 +188,13 @@ public class TNT {
|
||||
return value < (double)i ? i - 1 : i;
|
||||
}
|
||||
|
||||
private Vector getLandingPos() {
|
||||
private Vector getLandingPos(SimulatorData simulatorData) {
|
||||
int x = floor(this.x);
|
||||
int y = floor(this.y - 0.2F);
|
||||
int z = floor(this.z);
|
||||
|
||||
if (Simulator19.getBlockType(x, y, z).isAir()) {
|
||||
BlockData blockData = Simulator19.getBlockData(x, y - 1, z);
|
||||
if (simulatorData.getBlockType(x, y, z).isAir()) {
|
||||
BlockData blockData = simulatorData.getBlockData(x, y - 1, z);
|
||||
if (blockData instanceof Fence || blockData instanceof Wall || blockData instanceof Gate) {
|
||||
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 y1 = floor(y + 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 y = y1; y <= y2; y++) {
|
||||
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) {
|
||||
slowMovement(new Vector(0.8999999761581421, 1.5, 0.8999999761581421));
|
||||
@ -232,8 +232,8 @@ public class TNT {
|
||||
} else if (material == Material.COBWEB) {
|
||||
slowMovement(new Vector(0.25, 0.05000000074505806, 0.25));
|
||||
} else if (material == Material.BUBBLE_COLUMN) {
|
||||
boolean drag = ((BubbleColumn) Simulator19.getBlockData(x, y, z)).isDrag();
|
||||
if (Simulator19.getBlockType(x, y + 1, z).isAir()) {
|
||||
boolean drag = ((BubbleColumn) simulatorData.getBlockData(x, y, z)).isDrag();
|
||||
if (simulatorData.getBlockType(x, y + 1, z).isAir()) {
|
||||
if (drag) {
|
||||
this.vy = Math.max(-0.9, vy - 0.03);
|
||||
} else {
|
||||
@ -278,8 +278,8 @@ public class TNT {
|
||||
return d + 1.0E-7 > f || e + 1.0E-7 > f;
|
||||
}
|
||||
|
||||
private float getVelocityMultiplier() {
|
||||
Material material = Simulator19.getBlockType(floor(x), floor(y), floor(z));
|
||||
private float getVelocityMultiplier(SimulatorData simulatorData) {
|
||||
Material material = simulatorData.getBlockType(floor(x), floor(y), floor(z));
|
||||
float f = 1F;
|
||||
if (material == Material.SOUL_SAND) {
|
||||
f = 0.5F;
|
||||
@ -288,7 +288,7 @@ public class TNT {
|
||||
}
|
||||
if (material != Material.WATER && material != Material.BUBBLE_COLUMN) {
|
||||
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) {
|
||||
f = 0.5F;
|
||||
} else if (material == Material.HONEY_BLOCK) {
|
||||
|
@ -19,17 +19,5 @@
|
||||
|
||||
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 {
|
||||
|
||||
@Override
|
||||
public void run(Pair<Integer, Map<Integer, List<List<Pair<TNTData, Integer>>>>> toCalculate, Consumer<PreviewRecord> consumer) {
|
||||
consumer.accept(null);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import yapion.hierarchy.types.YAPIONArray;
|
||||
import yapion.hierarchy.types.YAPIONObject;
|
||||
import yapion.hierarchy.types.YAPIONType;
|
||||
@ -49,17 +50,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
public class TNTSimulator {
|
||||
|
||||
@Getter
|
||||
private Set<Player> players = new HashSet<>();
|
||||
|
||||
@Getter
|
||||
private REntityServer entityServer = new REntityServer();
|
||||
|
||||
@Getter
|
||||
private Material material = Material.TNT;
|
||||
|
||||
@Getter
|
||||
private List<SimulatorElement> tntElementList = new ArrayList<>();
|
||||
|
||||
private boolean currentlyCalculating = false;
|
||||
private List<Player> toShow = new ArrayList<>();
|
||||
private BukkitTask currentlyCalculating = null;
|
||||
private PreviewRecord previewRecord = null;
|
||||
|
||||
public TNTSimulator() {
|
||||
@ -108,17 +114,21 @@ public class TNTSimulator {
|
||||
}
|
||||
|
||||
public void showPreview(Player player) {
|
||||
if (previewRecord == null) {
|
||||
calcPreview(true);
|
||||
}
|
||||
if (previewRecord != null) {
|
||||
previewRecord.show(player);
|
||||
return;
|
||||
}
|
||||
toShow.add(player);
|
||||
calcPreview(true);
|
||||
}
|
||||
|
||||
public void hidePreview(Player player) {
|
||||
if (previewRecord != null && previewRecord.hide(player)) {
|
||||
previewRecord = null;
|
||||
if (currentlyCalculating != null) {
|
||||
currentlyCalculating.cancel();
|
||||
currentlyCalculating = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,27 +140,24 @@ public class TNTSimulator {
|
||||
if (!force && previewRecord == null) {
|
||||
return;
|
||||
}
|
||||
if (currentlyCalculating) return;
|
||||
currentlyCalculating = true;
|
||||
|
||||
Simulator.impl.run(locations(true), newRecord -> {
|
||||
boolean recalculate = currentlyCalculating;
|
||||
currentlyCalculating = false;
|
||||
if (currentlyCalculating != null) currentlyCalculating.cancel();
|
||||
currentlyCalculating = Simulator.impl.run(locations(true), newRecord -> {
|
||||
currentlyCalculating = null;
|
||||
|
||||
PreviewRecord oldRecord = previewRecord;
|
||||
previewRecord = newRecord;
|
||||
if (newRecord == null) return;
|
||||
if (newRecord == null) {
|
||||
toShow.clear();
|
||||
return;
|
||||
}
|
||||
if (oldRecord != null) {
|
||||
oldRecord.getPlayers().forEach(player -> {
|
||||
oldRecord.hide(player);
|
||||
newRecord.show(player);
|
||||
});
|
||||
}
|
||||
if (recalculate) {
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
calcPreview(force);
|
||||
}, 1);
|
||||
}
|
||||
toShow.forEach(newRecord::show);
|
||||
toShow.clear();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.simulator.TNTData;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -31,5 +32,7 @@ import java.util.function.Consumer;
|
||||
public interface Simulator {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren