From db349c2a05f3c6c557f88cf50072364f50c3ff42 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 2 Sep 2023 15:30:48 +0200 Subject: [PATCH] Optimize Laufbau performance Signed-off-by: yoyosource --- .../features/slaves/laufbau/Laufbau.java | 12 +++++- .../slaves/laufbau/LaufbauCommand.java | 1 + .../laufbau/states/CreatingLaufState.java | 38 +++++++++---------- .../laufbau/states/ProcessingTracesState.java | 30 +++++++-------- .../de/steamwar/bausystem/region/Point.java | 4 ++ 5 files changed, 48 insertions(+), 37 deletions(-) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java index a2506042..d53995a3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/Laufbau.java @@ -49,11 +49,19 @@ public class Laufbau { @Getter private EditSession editSession; + private int factor; + public Laufbau(Player player, Location pos1, Location pos2, boolean preferingBlastResistance) { this.world = pos1.getWorld(); this.pos1 = new Location(world, Math.min(pos1.getBlockX(), pos2.getBlockX()), Math.min(pos1.getBlockY(), pos2.getBlockY()), Math.min(pos1.getBlockZ(), pos2.getBlockZ())); this.pos2 = new Location(world, Math.max(pos1.getBlockX(), pos2.getBlockX()), Math.max(pos1.getBlockY(), pos2.getBlockY()), Math.max(pos1.getBlockZ(), pos2.getBlockZ())); + Vector selectionSize = pos2.toVector().subtract(pos1.toVector()); + int xFactor = (int) (Math.abs(selectionSize.getX()) / 12.375); + int yFactor = (int) (Math.abs(selectionSize.getY()) / 7.125); + 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); @@ -95,10 +103,10 @@ public class Laufbau { return; } if (processingTracesState != null) { - creatingLaufState = new CreatingLaufState(processingTracesState.getBlocks(), processingTracesState.getCuboidList(), world, editSession, elements); + creatingLaufState = new CreatingLaufState(processingTracesState.getBlocks(), processingTracesState.getCuboidIntersectionCache(), world, editSession, elements, factor); return; } - processingTracesState = new ProcessingTracesState(filteringTracesState.getTntPositions(), world, this::inRegion); + processingTracesState = new ProcessingTracesState(filteringTracesState.getTntPositions(), this::inRegion, factor); } public String actionBarMessage(Player p) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java index f1b69ba6..86585417 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/LaufbauCommand.java @@ -46,6 +46,7 @@ public class LaufbauCommand extends SWCommand { BauSystem.MESSAGE.send("LAUFBAU_NO_WORLDEDIT", player); return; } + Laufbau laufbau = new Laufbau(player, selection.getKey(), selection.getValue(), preferingBlastResistance); new BukkitRunnable() { @Override diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/CreatingLaufState.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/CreatingLaufState.java index cc49c88e..9522518d 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/CreatingLaufState.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/CreatingLaufState.java @@ -32,11 +32,7 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.*; public class CreatingLaufState implements LaufbauState { @@ -51,22 +47,24 @@ public class CreatingLaufState implements LaufbauState { private long start = System.currentTimeMillis(); private List blocks; - private List cuboids; + private Map> cuboidIntersectionCache; private List outerPoints = new ArrayList<>(); private Set innerPoints = new HashSet<>(); private World world; private EditSession editSession; private List elements; + private int factor; private int operations = 0; private int totalOperations; - public CreatingLaufState(Set blocks, List cuboids, World world, EditSession editSession, List elements) { + public CreatingLaufState(Set blocks, Map> cuboidIntersectionCache, World world, EditSession editSession, List elements, int factor) { this.blocks = new ArrayList<>(blocks); - this.cuboids = cuboids; + this.cuboidIntersectionCache = cuboidIntersectionCache; this.world = world; this.editSession = editSession; this.elements = elements; + this.factor = factor; totalOperations = blocks.size() * 2; } @@ -90,7 +88,7 @@ public class CreatingLaufState implements LaufbauState { Cuboid tempCuboid = ONE.add(point); Cuboid aboveHalfTempCuboid = ABOVE_HALF.add(point); List intersectedCuboids = new ArrayList<>(); - for (Cuboid cuboid : cuboids) { + for (Cuboid cuboid : cuboidIntersectionCache.get(point.divide(factor))) { if (cuboid.intersects(tempCuboid)) { isInCuboid = true; intersectedCuboids.add(cuboid); @@ -118,34 +116,36 @@ public class CreatingLaufState implements LaufbauState { } private void calcInnerBlock(Point point, List neededCuboids) { - List blockDataWithBoundingBoxList = new ArrayList<>(); + BlockBoundingBox highestBlockBoundingBox = null; for (BlockBoundingBox blockDataWithBoundingBox : elements) { - List cuboids = blockDataWithBoundingBox.getCuboidList().stream().map(c -> c.add(point)).collect(Collectors.toList()); - boolean isInCuboid = false; for (Cuboid cuboid : neededCuboids) { - if (cuboids.stream().anyMatch(cuboid::intersects)) { - isInCuboid = true; + for (Cuboid currentCuboid : blockDataWithBoundingBox.getCuboidList()) { + if (cuboid.intersects(currentCuboid.add(point))) { + isInCuboid = true; + break; + } + } + if (isInCuboid) { break; } } if (!isInCuboid) { - blockDataWithBoundingBoxList.add(blockDataWithBoundingBox); + highestBlockBoundingBox = blockDataWithBoundingBox; break; } } - if (blockDataWithBoundingBoxList.isEmpty()) { + if (highestBlockBoundingBox == null) { return; } - BlockBoundingBox highest = blockDataWithBoundingBoxList.get(0); Location location = new Location(world, point.getX(), point.getY(), point.getZ()); if (!location.getBlock().getType().isAir()) { return; } try { - BaseBlock block = BukkitAdapter.adapt(highest.blockData).toBaseBlock(); - if (highest.blockConsumer != null) highest.blockConsumer.accept(block); + BaseBlock block = BukkitAdapter.adapt(highestBlockBoundingBox.blockData).toBaseBlock(); + if (highestBlockBoundingBox.blockConsumer != null) highestBlockBoundingBox.blockConsumer.accept(block); editSession.setBlock(BukkitAdapter.asBlockVector(location), block); } catch (MaxChangedBlocksException e) { e.printStackTrace(); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/ProcessingTracesState.java b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/ProcessingTracesState.java index e3fc265a..c34e5024 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/ProcessingTracesState.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/slaves/laufbau/states/ProcessingTracesState.java @@ -24,15 +24,10 @@ import de.steamwar.bausystem.features.slaves.laufbau.Cuboid; import de.steamwar.bausystem.features.tracer.TNTPosition; import de.steamwar.bausystem.region.Point; import lombok.Getter; -import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.function.BiPredicate; public class ProcessingTracesState implements LaufbauState { @@ -41,28 +36,29 @@ public class ProcessingTracesState implements LaufbauState { private int totalCuboids; private List tntPositionList; - - private World world; private BiPredicate inRegionCheck; + private int factor; private List toExpand = new ArrayList<>(); - @Getter - private List cuboidList = new ArrayList<>(); + private int cuboidsDone = 0; @Getter private Set blocks = new HashSet<>(); - public ProcessingTracesState(List tntPositionList, World world, BiPredicate inRegionCheck) { + @Getter + private Map> cuboidIntersectionCache = new HashMap<>(); + + public ProcessingTracesState(List tntPositionList, BiPredicate inRegionCheck, int factor) { this.tntPositionList = tntPositionList; this.totalCuboids = tntPositionList.stream().mapToInt(tntPosition -> tntPosition.getPreviousLocation() == null ? 1 : 3).sum(); - this.world = world; this.inRegionCheck = inRegionCheck; + this.factor = factor; } @Override public String actionBarMessage(Player p) { - return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), totalCuboids - cuboidList.size(), totalCuboids, eta(p, start, totalCuboids - cuboidList.size(), totalCuboids)); + return BauSystem.MESSAGE.parse("LAUFBAU_SIMPLE_PROGRESS", p, BauSystem.MESSAGE.parse("LAUFBAU_STATE_PROCESSING_TRACES", p), cuboidsDone, totalCuboids, eta(p, start, cuboidsDone, totalCuboids)); } @Override @@ -101,14 +97,16 @@ public class ProcessingTracesState implements LaufbauState { } private void expandCuboid(Cuboid cuboid) { - cuboidList.add(cuboid); + cuboidsDone++; 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++) { - Location location = new Location(world, x, y, z); - if (inRegionCheck.test(new Vector(location.getBlockX(), location.getBlockY(), location.getBlockZ()), 0)) { + 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<>()) + .add(cuboid); } } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java b/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java index b6efac3a..4a659169 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/region/Point.java @@ -49,6 +49,10 @@ public class Point { return new Point(this.x - x, this.y - y, this.z - z); } + public Point divide(int factor) { + return new Point(x / factor, y / factor, z / factor); + } + public Location toLocation(World world) { return new Location(world, x, y, z); }