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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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

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

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

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