Trace Refactor #233
@ -20,9 +20,7 @@
|
||||
package de.steamwar.bausystem.features.slaves.laufbau;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.states.FilteringTracesState;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.states.LaufbauState;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.states.CreatingLaufState;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.states.ProcessingTracesState;
|
||||
import de.steamwar.bausystem.utils.WorldEditUtils;
|
||||
import lombok.Getter;
|
||||
@ -40,9 +38,7 @@ public class Laufbau {
|
||||
private Location pos1;
|
||||
private Location pos2;
|
||||
|
||||
private FilteringTracesState filteringTracesState = null;
|
||||
private ProcessingTracesState processingTracesState = null;
|
||||
private CreatingLaufState creatingLaufState = null;
|
||||
private LaufbauState active;
|
||||
|
||||
private List<BlockBoundingBox> elements;
|
||||
|
||||
@ -62,8 +58,6 @@ public class Laufbau {
|
||||
int zFactor = (int) (Math.abs(selectionSize.getZ()) / 9.875);
|
||||
factor = Math.max(Math.max(xFactor, Math.max(yFactor, zFactor)), 8);
|
||||
|
||||
filteringTracesState = new FilteringTracesState(world, this::inRegion);
|
||||
|
||||
editSession = WorldEditUtils.getEditSession(player);
|
||||
|
||||
elements = BlockBoundingBox.elements.stream().filter(blockBoundingBox -> {
|
||||
@ -86,49 +80,32 @@ public class Laufbau {
|
||||
return -Double.compare(o1.blockData.getMaterial().getBlastResistance(), o2.blockData.getMaterial().getBlastResistance());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private LaufbauState getActive() {
|
||||
if (creatingLaufState != null) {
|
||||
return creatingLaufState;
|
||||
}
|
||||
if (processingTracesState != null) {
|
||||
return processingTracesState;
|
||||
}
|
||||
return filteringTracesState;
|
||||
active = new ProcessingTracesState(world, this::inRegion, editSession, elements, factor);
|
||||
}
|
||||
|
||||
private void createNextState() {
|
||||
if (creatingLaufState != null) {
|
||||
return;
|
||||
}
|
||||
if (processingTracesState != null) {
|
||||
creatingLaufState = new CreatingLaufState(processingTracesState.getBlocks(), processingTracesState.getCuboidIntersectionCache(), world, editSession, elements, factor);
|
||||
return;
|
||||
}
|
||||
processingTracesState = new ProcessingTracesState(filteringTracesState.getTntPositions(), this::inRegion, factor);
|
||||
if (active == null) return;
|
||||
active = active.getNextState();
|
||||
}
|
||||
|
||||
public String actionBarMessage(Player p) {
|
||||
return getActive().actionBarMessage(p);
|
||||
return active.actionBarMessage(p);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return getActive().hasNext();
|
||||
if (active == null) return false;
|
||||
return active.hasNext();
|
||||
}
|
||||
|
||||
public void next() {
|
||||
LaufbauState state = getActive();
|
||||
LaufbauState state = active;
|
||||
state.next();
|
||||
if (!state.hasNext()) {
|
||||
createNextState();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inRegion(Location location, int expansion) {
|
||||
return inRegion(location.toVector(), expansion);
|
||||
}
|
||||
|
||||
private boolean inRegion(Vector location, int expansion) {
|
||||
if (location.getBlockX() >= pos1.getBlockX() - expansion) {
|
||||
if (location.getBlockY() >= pos1.getBlockY() - expansion) {
|
||||
|
@ -196,4 +196,9 @@ public class CreatingLaufState implements LaufbauState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LaufbauState getNextState() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2022 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.slaves.laufbau.states;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.tracer.TNTRecord;
|
||||
import de.steamwar.bausystem.features.tracer.Trace;
|
||||
import de.steamwar.bausystem.features.tracer.TraceManager;
|
||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
public class FilteringTracesState implements LaufbauState {
|
||||
|
||||
@LinkedInstance
|
||||
TraceManager traceManager;
|
||||
private long start = System.currentTimeMillis();
|
||||
|
||||
private World world;
|
||||
private BiPredicate<Location, Integer> inRegionCheck;
|
||||
|
||||
private final int totalRecord;
|
||||
|
||||
List<Trace> traces;
|
||||
private List<List<TNTRecord>> tntHistories = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private List<TNTRecord> tntPositions = new ArrayList<>();
|
||||
|
||||
public FilteringTracesState(World world, BiPredicate<Location, Integer> inRegionCheck) {
|
||||
List<Trace> traces = new ArrayList<>(traceManager.getAll());
|
||||
totalRecord = traces.size();
|
||||
|
||||
this.world = world;
|
||||
this.inRegionCheck = inRegionCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String actionBarMessage(Player p) {
|
||||
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_FILTERING_TRACES", p), totalRecord - traces.size(), totalRecord, eta(p, start, totalRecord - traces.size(), totalRecord));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !traces.isEmpty() || !tntHistories.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() {
|
||||
if (tntHistories.isEmpty()) {
|
||||
Trace trace = traces.remove(0);
|
||||
tntHistories.addAll(trace.getHistories());
|
||||
}
|
||||
if (tntHistories.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<TNTRecord> tntRecords = tntHistories.remove(0);
|
||||
tntRecords.forEach(tntRecord -> {
|
||||
if (FlatteningWrapper.impl.inWater(world, tntRecord.getLocation().toVector())) {
|
||||
return;
|
||||
}
|
||||
if (inRegionCheck.test(tntRecord.getLocation(), 1)) {
|
||||
tntPositions.add(tntRecord);
|
||||
}
|
||||
if (tntRecord.getPrevious().isPresent() && inRegionCheck.test(tntRecord.getPrevious().get().getLocation(), 1)) {
|
||||
tntPositions.add(tntRecord);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -45,4 +45,6 @@ public interface LaufbauState {
|
||||
}
|
||||
return LocalTime.ofNanoOfDay(eta).format(DateTimeFormatter.ofPattern(BauSystem.MESSAGE.parse("TIME", p)));
|
||||
}
|
||||
|
||||
LaufbauState getNextState();
|
||||
}
|
||||
|
@ -1,117 +1,128 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2022 SteamWar.de-Serverteam
|
||||
* Copyright (C) 2024 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 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.
|
||||
* 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/>.
|
||||
* 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.slaves.laufbau.states;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.BlockBoundingBox;
|
||||
import de.steamwar.bausystem.features.slaves.laufbau.Cuboid;
|
||||
import de.steamwar.bausystem.features.tracer.TNTRecord;
|
||||
import de.steamwar.bausystem.features.tracer.TraceRecorder;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import lombok.Getter;
|
||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ProcessingTracesState implements LaufbauState {
|
||||
|
||||
private long start = System.currentTimeMillis();
|
||||
private final long start = System.currentTimeMillis();
|
||||
private final World world;
|
||||
private final BiPredicate<Vector, Integer> inRegionCheck;
|
||||
private final EditSession editSession;
|
||||
private final List<BlockBoundingBox> elements;
|
||||
private final int factor;
|
||||
|
||||
private int totalCuboids;
|
||||
private List<TNTRecord> tntPositionList;
|
||||
private BiPredicate<Vector, Integer> inRegionCheck;
|
||||
private int factor;
|
||||
private final List<TNTRecord> tntRecords;
|
||||
private final int totalTntRecords;
|
||||
|
||||
private List<Cuboid> toExpand = new ArrayList<>();
|
||||
private final Set<Point> affectedBlocks = new HashSet<>();
|
||||
private final Map<Point, Set<Cuboid>> cuboidsPerChunk = new HashMap<>();
|
||||
|
||||
private int cuboidsDone = 0;
|
||||
|
||||
@Getter
|
||||
private Set<Point> blocks = new HashSet<>();
|
||||
|
||||
@Getter
|
||||
private Map<Point, Set<Cuboid>> cuboidIntersectionCache = new HashMap<>();
|
||||
|
||||
public ProcessingTracesState(List<TNTRecord> tntPositionList, BiPredicate<Vector, Integer> inRegionCheck, int factor) {
|
||||
this.tntPositionList = tntPositionList;
|
||||
this.totalCuboids = tntPositionList.stream().mapToInt(tntPosition -> tntPosition.getPrevious() == null ? 1 : 3).sum();
|
||||
public ProcessingTracesState(World world, BiPredicate<Vector, Integer> inRegionCheck, EditSession editSession, List<BlockBoundingBox> elements, int factor) {
|
||||
this.world = world;
|
||||
this.inRegionCheck = inRegionCheck;
|
||||
this.editSession = editSession;
|
||||
this.elements = elements;
|
||||
this.factor = factor;
|
||||
|
||||
// TODO: Optimize only retrieving traces inside of the affected regions!
|
||||
tntRecords = TraceRecorder.instance.manager.getAll()
|
||||
.stream()
|
||||
.flatMap(trace -> trace.getHistories().stream())
|
||||
.flatMap(Collection::stream)
|
||||
.collect(Collectors.toList());
|
||||
totalTntRecords = tntRecords.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String actionBarMessage(Player p) {
|
||||
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), cuboidsDone, totalCuboids, eta(p, start, cuboidsDone, totalCuboids));
|
||||
return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), totalTntRecords - tntRecords.size(), totalTntRecords, eta(p, start, totalTntRecords - tntRecords.size(), totalTntRecords));
|
||||
}
|
||||
|
||||
private boolean inRegion(Vector location, int expansion) {
|
||||
return inRegionCheck.test(location, expansion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return !tntPositionList.isEmpty() || !toExpand.isEmpty();
|
||||
return !tntRecords.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void next() {
|
||||
if (!toExpand.isEmpty()) {
|
||||
Cuboid cuboid = toExpand.remove(0);
|
||||
expandCuboid(cuboid);
|
||||
} else {
|
||||
TNTRecord tntPosition = tntPositionList.remove(0);
|
||||
createCuboid(tntPosition);
|
||||
}
|
||||
}
|
||||
TNTRecord current = tntRecords.remove(0);
|
||||
if (FlatteningWrapper.impl.inWater(world, current.getLocation().toVector())) return;
|
||||
if (!(inRegion(current.getLocation().toVector(), 1) || (current.getPrevious().isPresent() && inRegion(current.getPrevious().get().getLocation().toVector(), 1))))
|
||||
return;
|
||||
|
||||
private void createCuboid(TNTRecord tntPosition) {
|
||||
Location location = tntPosition.getLocation();
|
||||
Optional<TNTRecord> previous = tntPosition.getPrevious();
|
||||
|
||||
if (!previous.isPresent()) {
|
||||
toExpand.add(new Cuboid(location.getX() - 0.49, location.getY(), location.getZ() - 0.49, 0.98, 0.98, 0.98));
|
||||
} else {
|
||||
Location previousLocation = tntPosition.getPrevious().get().getLocation();
|
||||
Location location = current.getLocation();
|
||||
if (current.getPrevious().isPresent()) {
|
||||
Vector velocity = current.getPrevious().get().getVelocity();
|
||||
Location previousLocation = current.getPrevious().get().getLocation();
|
||||
Location movement = location.clone().subtract(previousLocation);
|
||||
toExpand.add(new Cuboid(previousLocation.getX() - 0.49, Math.min(previousLocation.getY(), location.getY()), previousLocation.getZ() - 0.49, 0.98, Math.abs(movement.getY()) + 0.98, 0.98));
|
||||
if (tntPosition.getVelocity().getX() >= tntPosition.getVelocity().getZ()) {
|
||||
toExpand.add(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), previousLocation.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
|
||||
toExpand.add(new Cuboid(location.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
|
||||
calculateCuboid(new Cuboid(previousLocation.getX() - 0.49, Math.min(previousLocation.getY(), location.getY()), previousLocation.getZ() - 0.49, 0.98, Math.abs(movement.getY()) + 0.98, 0.98));
|
||||
if (velocity.getX() >= velocity.getZ()) {
|
||||
calculateCuboid(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), previousLocation.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
|
||||
calculateCuboid(new Cuboid(location.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
|
||||
} else {
|
||||
toExpand.add(new Cuboid(previousLocation.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
|
||||
toExpand.add(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), location.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
|
||||
calculateCuboid(new Cuboid(previousLocation.getX() - 0.49, location.getY(), Math.min(previousLocation.getZ(), location.getZ()) - 0.49, 0.98, 0.98, Math.abs(movement.getZ()) + 0.98));
|
||||
calculateCuboid(new Cuboid(Math.min(previousLocation.getX(), location.getX()) - 0.49, location.getY(), location.getZ() - 0.49, Math.abs(movement.getX()) + 0.98, 0.98, 0.98));
|
||||
}
|
||||
} else {
|
||||
calculateCuboid(new Cuboid(location.getX() - 0.49, location.getY(), location.getZ() - 0.49, 0.98, 0.98, 0.98));
|
||||
}
|
||||
}
|
||||
|
||||
private void expandCuboid(Cuboid cuboid) {
|
||||
cuboidsDone++;
|
||||
private void calculateCuboid(Cuboid cuboid) {
|
||||
for (double x = cuboid.getX() - 2; x < cuboid.getX() + cuboid.getDx() + 2; x++) {
|
||||
for (double y = cuboid.getY() - 2; y < cuboid.getY() + cuboid.getDy() + 2; y++) {
|
||||
for (double z = cuboid.getZ() - 2; z < cuboid.getZ() + cuboid.getDz() + 2; z++) {
|
||||
Vector location = new Vector(x, y, z);
|
||||
if (inRegionCheck.test(location, 0)) {
|
||||
Point point = new Point(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
blocks.add(point);
|
||||
cuboidIntersectionCache.computeIfAbsent(point.divide(factor), __ -> new HashSet<>())
|
||||
if (inRegion(location, 0)) {
|
||||
affectedBlocks.add(new Point(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
|
||||
cuboidsPerChunk.computeIfAbsent(new Point(location.getBlockX() / factor, location.getBlockY() / factor, location.getBlockZ() / factor), __ -> new HashSet<>())
|
||||
.add(cuboid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LaufbauState getNextState() {
|
||||
return new CreatingLaufState(affectedBlocks, cuboidsPerChunk, world, editSession, elements, factor);
|
||||
}
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ public class Trace { // TODO: Add UUID for file saving and so on!
|
||||
|
||||
for (Player player : serverMap.keySet()) {
|
||||
REntityServer server = serverMap.get(player);
|
||||
BundleFilter bundleFilter = bundleFilterMap.get(player);
|
||||
ViewFlagHolder viewFlagHolder = viewFlagMap.get(player);
|
||||
BundleFilter bundleFilter = bundleFilterMap.getOrDefault(player, BundleFilter.DEFAULT);
|
||||
ViewFlagHolder viewFlagHolder = viewFlagMap.computeIfAbsent(player, ignored -> new ViewFlagHolder());
|
||||
|
||||
render(server, records, viewFlagHolder, bundleFilter);
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren