Optimize ProcessingTracesState
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Dieser Commit ist enthalten in:
yoyosource 2024-04-08 13:25:13 +02:00
Ursprung b8e79f9c55
Commit af19931946
6 geänderte Dateien mit 88 neuen und 188 gelöschten Zeilen

Datei anzeigen

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

Datei anzeigen

@ -196,4 +196,9 @@ public class CreatingLaufState implements LaufbauState {
}
}
}
@Override
public LaufbauState getNextState() {
return null;
}
}

Datei anzeigen

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

Datei anzeigen

@ -45,4 +45,6 @@ public interface LaufbauState {
}
return LocalTime.ofNanoOfDay(eta).format(DateTimeFormatter.ofPattern(BauSystem.MESSAGE.parse("TIME", p)));
}
LaufbauState getNextState();
}

Datei anzeigen

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

Datei anzeigen

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