From 0bb3c6d8f9c1d575978d1892bfd3466e6d4d985e Mon Sep 17 00:00:00 2001 From: ssquadteam Date: Tue, 4 Nov 2025 14:50:13 +0600 Subject: [PATCH 1/3] Implement convex selection enhancements and error handling for duplicate vertices and limits. (Resolve #2817) --- .../worldedit/command/SelectionCommands.java | 75 ++++++++++++- .../worldedit/command/tool/DistanceWand.java | 21 ++++ .../worldedit/command/tool/SelectionWand.java | 25 +++++ .../regions/ConvexPolyhedralRegion.java | 8 ++ .../ConvexPolyhedralRegionSelector.java | 45 +++++++- .../src/main/resources/lang/strings.json | 6 + .../ConvexPolyhedralRegionSpecTest.java | 105 ++++++++++++++++++ 7 files changed, 275 insertions(+), 10 deletions(-) create mode 100644 worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 007c773525..3719f80158 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -154,7 +154,27 @@ public void pos(Actor actor, World world, LocalSession session, regionSelector.selectPrimary(pos1, ActorSelectorLimits.forActor(actor)); for (BlockVector3 vector : pos2) { - regionSelector.selectSecondary(vector, ActorSelectorLimits.forActor(actor)); + boolean changed = regionSelector.selectSecondary(vector, ActorSelectorLimits.forActor(actor)); + if (!changed && regionSelector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { + com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) regionSelector.getIncompleteRegion(); + if (convex.getVertices().contains(vector)) { + actor.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.error.duplicate", + TextComponent.of(vector.toString()) + )); + } else { + ActorSelectorLimits limits = ActorSelectorLimits.forActor(actor); + limits.getPolyhedronVertexLimit().ifPresent(limit -> { + int total = convex.getVertices().size(); + if (total >= limit) { + actor.printInfo(TranslatableComponent.of( + "worldedit.select.convex.limit-message", + TextComponent.of(limit) + )); + } + }); + } + } } session.dispatchCUISelection(actor); @@ -205,8 +225,30 @@ public void pos2(Actor actor, World world, LocalSession session, } } - if (!session.getRegionSelector(world).selectSecondary(coordinates, ActorSelectorLimits.forActor(actor))) { - actor.printError(TranslatableComponent.of("worldedit.pos.already-set")); + RegionSelector selector = session.getRegionSelector(world); + if (!selector.selectSecondary(coordinates, ActorSelectorLimits.forActor(actor))) { + if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { + com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + if (convex.getVertices().contains(coordinates)) { + actor.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.error.duplicate", + TextComponent.of(coordinates.toString()) + )); + } else { + ActorSelectorLimits limits = ActorSelectorLimits.forActor(actor); + limits.getPolyhedronVertexLimit().ifPresent(limit -> { + int total = convex.getVertices().size(); + if (total >= limit) { + actor.printInfo(TranslatableComponent.of( + "worldedit.select.convex.limit-message", + TextComponent.of(limit) + )); + } + }); + } + } else { + actor.printError(TranslatableComponent.of("worldedit.pos.already-set")); + } return; } @@ -245,8 +287,31 @@ public void hpos2(Player player, LocalSession session) { Location pos = player.getBlockTrace(300); if (pos != null) { - if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos.toVector().toBlockPoint(), ActorSelectorLimits.forActor(player))) { - player.printError(TranslatableComponent.of("worldedit.hpos.already-set")); + RegionSelector selector = session.getRegionSelector(player.getWorld()); + BlockVector3 bp = pos.toVector().toBlockPoint(); + if (!selector.selectSecondary(bp, ActorSelectorLimits.forActor(player))) { + if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { + com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + if (convex.getVertices().contains(bp)) { + player.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.error.duplicate", + TextComponent.of(bp.toString()) + )); + } else { + ActorSelectorLimits limits = ActorSelectorLimits.forActor(player); + limits.getPolyhedronVertexLimit().ifPresent(limit -> { + int total = convex.getVertices().size(); + if (total >= limit) { + player.printInfo(TranslatableComponent.of( + "worldedit.select.convex.limit-message", + TextComponent.of(limit) + )); + } + }); + } + } else { + player.printError(TranslatableComponent.of("worldedit.hpos.already-set")); + } return; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java index 5d62d7abd0..8bea56d8f0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java @@ -65,6 +65,27 @@ public boolean actPrimary(Platform server, LocalConfiguration config, Player pla BlockVector3 blockPoint = target.toVector().toBlockPoint(); if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { selector.explainSecondarySelection(player, session, blockPoint); + } else if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { + com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + + if (convex.getVertices().contains(blockPoint)) { + player.printInfo(com.sk89q.worldedit.util.formatting.text.TranslatableComponent.of( + "worldedit.selection.convex.error.duplicate", + com.sk89q.worldedit.util.formatting.text.TextComponent.of(blockPoint.toString()) + )); + return true; + } + + ActorSelectorLimits limits = ActorSelectorLimits.forActor(player); + limits.getPolyhedronVertexLimit().ifPresent(limit -> { + int total = convex.getVertices().size(); + if (total >= limit) { + player.printInfo(com.sk89q.worldedit.util.formatting.text.TranslatableComponent.of( + "worldedit.select.convex.limit-message", + com.sk89q.worldedit.util.formatting.text.TextComponent.of(limit) + )); + } + }); } return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java index 34c4096e7a..fce0bfe36b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SelectionWand.java @@ -26,9 +26,13 @@ import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import javax.annotation.Nullable; @@ -52,6 +56,27 @@ public boolean actPrimary(Platform server, LocalConfiguration config, Player pla if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { selector.explainSecondarySelection(player, session, blockPoint); + } else if (selector instanceof ConvexPolyhedralRegionSelector) { + ConvexPolyhedralRegion convex = (ConvexPolyhedralRegion) selector.getIncompleteRegion(); + + if (convex.getVertices().contains(blockPoint)) { + player.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.error.duplicate", + TextComponent.of(blockPoint.toString()) + )); + return true; + } + + ActorSelectorLimits limits = ActorSelectorLimits.forActor(player); + limits.getPolyhedronVertexLimit().ifPresent(limit -> { + int total = convex.getVertices().size(); + if (total >= limit) { + player.printInfo(TranslatableComponent.of( + "worldedit.select.convex.limit-message", + TextComponent.of(limit) + )); + } + }); } return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegion.java index 4c1671fcc9..2ed784eca9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegion.java @@ -338,6 +338,14 @@ public Collection getVertices() { return ret; } + public boolean isBacklogVertex(BlockVector3 vertex) { + return vertexBacklog.contains(vertex); + } + + public Collection getBacklogVertices() { + return new ArrayList<>(vertexBacklog); + } + public Collection getTriangles() { return triangles; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java index af0dd9c344..4759c71223 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java @@ -131,7 +131,7 @@ public boolean selectSecondary(BlockVector3 position, SelectorLimits limits) { Optional vertexLimit = limits.getPolyhedronVertexLimit(); - if (vertexLimit.isPresent() && region.getVertices().size() > vertexLimit.get()) { + if (vertexLimit.isPresent() && region.getVertices().size() >= vertexLimit.get()) { return false; } @@ -169,7 +169,12 @@ public long getVolume() { @Override public void learnChanges() { - pos1 = region.getVertices().iterator().next(); + if (!region.getTriangles().isEmpty()) { + Triangle t = region.getTriangles().iterator().next(); + pos1 = t.getVertex(0).toBlockPoint(); + } else { + pos1 = region.getVertices().iterator().next(); + } } @Override @@ -186,8 +191,20 @@ public String getTypeName() { public List getSelectionInfoLines() { List ret = new ArrayList<>(); - ret.add(TranslatableComponent.of("worldedit.selection.convex.info.vertices", TextComponent.of(region.getVertices().size()))); - ret.add(TranslatableComponent.of("worldedit.selection.convex.info.triangles", TextComponent.of(region.getTriangles().size()))); + int vertexCount = region.getVertices().size(); + int triangleCount = region.getTriangles().size(); + ret.add(TranslatableComponent.of("worldedit.selection.convex.info.vertices", TextComponent.of(vertexCount))); + ret.add(TranslatableComponent.of("worldedit.selection.convex.info.triangles", TextComponent.of(triangleCount))); + + if (triangleCount == 0) { + if (vertexCount < 3) { + ret.add(TranslatableComponent.of("worldedit.selection.convex.error.too-few")); + } else { + ret.add(TranslatableComponent.of("worldedit.selection.convex.error.all-collinear")); + } + } else if (triangleCount == 2) { + ret.add(TranslatableComponent.of("worldedit.selection.convex.info.planar")); + } return ret; } @@ -212,7 +229,25 @@ public void explainSecondarySelection(Actor player, LocalSession session, BlockV session.describeCUI(player); - player.printInfo(TranslatableComponent.of("worldedit.selection.convex.explain.secondary", TextComponent.of(pos.toString()))); + if (region.isBacklogVertex(pos)) { + if (region.getTriangles().isEmpty()) { + player.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.info.backlog.collinear", + TextComponent.of(pos.toString()) + )); + } else { + player.printInfo(TranslatableComponent.of( + "worldedit.selection.convex.info.backlog.coplanar", + TextComponent.of(pos.toString()) + )); + } + } else { + player.printInfo(TranslatableComponent.of("worldedit.selection.convex.explain.secondary", TextComponent.of(pos.toString()))); + } + + if (!region.isDefined() && region.getVertices().size() >= 3) { + player.printInfo(TranslatableComponent.of("worldedit.selection.convex.error.all-collinear")); + } } @Override diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index e01e89e97a..1aa647deb5 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -419,6 +419,12 @@ "worldedit.selection.convex.info.triangles": "Triangles: {0}", "worldedit.selection.convex.explain.primary": "Started new selection with vertex {0}.", "worldedit.selection.convex.explain.secondary": "Added vertex {0} to the selection.", + "worldedit.selection.convex.info.backlog.collinear": "Point is collinear with existing vertices, added to backlog ({0}).", + "worldedit.selection.convex.info.backlog.coplanar": "Point is coplanar with existing vertices, added to backlog ({0}).", + "worldedit.selection.convex.error.duplicate": "Vertex already exists at {0}.", + "worldedit.selection.convex.error.all-collinear": "Cannot form a region with only collinear points.", + "worldedit.selection.convex.info.planar": "Selection is planar (2D), add a non-coplanar point for 3D volume.", + "worldedit.selection.convex.error.too-few": "Need at least 3 non-collinear vertices to define a region.", "worldedit.selection.cuboid.info.pos1": "Position 1: {0}", "worldedit.selection.cuboid.info.pos2": "Position 2: {0}", "worldedit.selection.cuboid.explain.primary": "First position set to {0}.", diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java new file mode 100644 index 0000000000..0a3501ac92 --- /dev/null +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java @@ -0,0 +1,105 @@ +/* + * Tests for ConvexPolyhedralRegion and ConvexPolyhedralRegionSelector edge cases per specification. + */ +package com.sk89q.worldedit.regions; + +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; +import com.sk89q.worldedit.regions.selector.limit.SelectorLimits; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +class ConvexPolyhedralRegionSpecTest { + + @Test + void allCollinearPoints_areUndefined() { + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); + assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); + // Third collinear point should be backlogged; no triangles should exist + assertTrue(region.addVertex(BlockVector3.at(20, 0, 0))); + assertFalse(region.isDefined()); + assertEquals(0, region.getTriangles().size()); + } + + @Test + void coplanarPoints_form2DDefinedRegion() { + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + // Three non-collinear, coplanar points define a 2D region (two triangles) + assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); + assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); + assertTrue(region.addVertex(BlockVector3.at(0, 0, 10))); + assertTrue(region.isDefined()); + assertEquals(2, region.getTriangles().size()); + + // Add another coplanar point; should remain planar (still two triangles) + assertTrue(region.addVertex(BlockVector3.at(10, 0, 10))); + assertEquals(2, region.getTriangles().size()); + } + + @Test + void vertexLimitEnforced_includesBacklog() { + ConvexPolyhedralRegionSelector selector = new ConvexPolyhedralRegionSelector((com.sk89q.worldedit.world.World) null); + SelectorLimits limits = new SelectorLimits() { + @Override + public Optional getPolygonVertexLimit() { + return Optional.empty(); + } + + @Override + public Optional getPolyhedronVertexLimit() { + // Limit total (vertices + backlog) to 3 + return Optional.of(3); + } + }; + + // First two vertices + assertTrue(selector.selectPrimary(BlockVector3.at(0, 0, 0), limits)); + assertTrue(selector.selectSecondary(BlockVector3.at(10, 0, 0), limits)); + // Third collinear point goes to backlog but counts towards limit + assertTrue(selector.selectSecondary(BlockVector3.at(20, 0, 0), limits)); + // Fourth should be rejected due to limit (>= check) + assertFalse(selector.selectSecondary(BlockVector3.at(0, 1, 0), limits)); + } + + @Test + void duplicateVertex_isRejected() { + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + BlockVector3 a = BlockVector3.at(1, 2, 3); + assertTrue(region.addVertex(a)); + assertFalse(region.addVertex(a)); + } + + @Test + void hullBecomes3D_withFourNonCoplanarPoints() { + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); + assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); + assertTrue(region.addVertex(BlockVector3.at(0, 0, 10))); + // Non-coplanar fourth point + assertTrue(region.addVertex(BlockVector3.at(0, 10, 0))); + assertTrue(region.isDefined()); + assertTrue(region.getTriangles().size() > 2, "3D hull should have more than 2 triangles"); + } + + @Test + void backlogProcessingOrder_isMaintained() { + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + BlockVector3 a = BlockVector3.at(0, 0, 0); + BlockVector3 b = BlockVector3.at(10, 0, 0); + BlockVector3 c = BlockVector3.at(5, 0, 0); // collinear -> backlog + BlockVector3 d = BlockVector3.at(0, 0, 10); // non-collinear + + assertTrue(region.addVertex(a)); + assertTrue(region.addVertex(b)); + assertTrue(region.addVertex(c)); + assertTrue(region.getBacklogVertices().contains(c)); + + // Adding d will trigger backlog processing; c should remain backlogged until non-coplanar point added later + assertTrue(region.addVertex(d)); + assertTrue(region.getBacklogVertices().contains(c)); + } +} From d9c7a5fcb8c737eaa8c4391750cdba82aea949f5 Mon Sep 17 00:00:00 2001 From: ssquadteam Date: Tue, 4 Nov 2025 15:03:52 +0600 Subject: [PATCH 2/3] Refactor ConvexPolyhedralRegion usage in SelectionCommands and DistanceWand for improved readability and consistency --- .../worldedit/command/SelectionCommands.java | 14 ++++++++------ .../worldedit/command/tool/DistanceWand.java | 15 +++++++++------ .../regions/ConvexPolyhedralRegionSpecTest.java | 11 ++++++----- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 3719f80158..34e45d0549 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -54,6 +54,8 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; +import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector; import com.sk89q.worldedit.regions.selector.RegionSelectorType; @@ -155,8 +157,8 @@ public void pos(Actor actor, World world, LocalSession session, for (BlockVector3 vector : pos2) { boolean changed = regionSelector.selectSecondary(vector, ActorSelectorLimits.forActor(actor)); - if (!changed && regionSelector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { - com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) regionSelector.getIncompleteRegion(); + if (!changed && regionSelector instanceof ConvexPolyhedralRegionSelector) { + ConvexPolyhedralRegion convex = (ConvexPolyhedralRegion) regionSelector.getIncompleteRegion(); if (convex.getVertices().contains(vector)) { actor.printInfo(TranslatableComponent.of( "worldedit.selection.convex.error.duplicate", @@ -227,8 +229,8 @@ public void pos2(Actor actor, World world, LocalSession session, RegionSelector selector = session.getRegionSelector(world); if (!selector.selectSecondary(coordinates, ActorSelectorLimits.forActor(actor))) { - if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { - com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + if (selector instanceof ConvexPolyhedralRegionSelector) { + ConvexPolyhedralRegion convex = (ConvexPolyhedralRegion) selector.getIncompleteRegion(); if (convex.getVertices().contains(coordinates)) { actor.printInfo(TranslatableComponent.of( "worldedit.selection.convex.error.duplicate", @@ -290,8 +292,8 @@ public void hpos2(Player player, LocalSession session) { RegionSelector selector = session.getRegionSelector(player.getWorld()); BlockVector3 bp = pos.toVector().toBlockPoint(); if (!selector.selectSecondary(bp, ActorSelectorLimits.forActor(player))) { - if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { - com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + if (selector instanceof ConvexPolyhedralRegionSelector) { + ConvexPolyhedralRegion convex = (ConvexPolyhedralRegion) selector.getIncompleteRegion(); if (convex.getVertices().contains(bp)) { player.printInfo(TranslatableComponent.of( "worldedit.selection.convex.error.duplicate", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java index 8bea56d8f0..73fee00053 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java @@ -26,8 +26,11 @@ import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; import com.sk89q.worldedit.regions.RegionSelector; +import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; /** @@ -65,13 +68,13 @@ public boolean actPrimary(Platform server, LocalConfiguration config, Player pla BlockVector3 blockPoint = target.toVector().toBlockPoint(); if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) { selector.explainSecondarySelection(player, session, blockPoint); - } else if (selector instanceof com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector) { - com.sk89q.worldedit.regions.ConvexPolyhedralRegion convex = (com.sk89q.worldedit.regions.ConvexPolyhedralRegion) selector.getIncompleteRegion(); + } else if (selector instanceof ConvexPolyhedralRegionSelector) { + ConvexPolyhedralRegion convex = (ConvexPolyhedralRegion) selector.getIncompleteRegion(); if (convex.getVertices().contains(blockPoint)) { - player.printInfo(com.sk89q.worldedit.util.formatting.text.TranslatableComponent.of( + player.printInfo(TranslatableComponent.of( "worldedit.selection.convex.error.duplicate", - com.sk89q.worldedit.util.formatting.text.TextComponent.of(blockPoint.toString()) + TextComponent.of(blockPoint.toString()) )); return true; } @@ -80,9 +83,9 @@ public boolean actPrimary(Platform server, LocalConfiguration config, Player pla limits.getPolyhedronVertexLimit().ifPresent(limit -> { int total = convex.getVertices().size(); if (total >= limit) { - player.printInfo(com.sk89q.worldedit.util.formatting.text.TranslatableComponent.of( + player.printInfo(TranslatableComponent.of( "worldedit.select.convex.limit-message", - com.sk89q.worldedit.util.formatting.text.TextComponent.of(limit) + TextComponent.of(limit) )); } }); diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java index 0a3501ac92..99fe4ed908 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java @@ -6,6 +6,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.regions.selector.limit.SelectorLimits; +import com.sk89q.worldedit.world.World; import org.junit.jupiter.api.Test; import java.util.Optional; @@ -16,7 +17,7 @@ class ConvexPolyhedralRegionSpecTest { @Test void allCollinearPoints_areUndefined() { - ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((World) null); assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); // Third collinear point should be backlogged; no triangles should exist @@ -27,7 +28,7 @@ void allCollinearPoints_areUndefined() { @Test void coplanarPoints_form2DDefinedRegion() { - ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((World) null); // Three non-collinear, coplanar points define a 2D region (two triangles) assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); @@ -67,7 +68,7 @@ public Optional getPolyhedronVertexLimit() { @Test void duplicateVertex_isRejected() { - ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((World) null); BlockVector3 a = BlockVector3.at(1, 2, 3); assertTrue(region.addVertex(a)); assertFalse(region.addVertex(a)); @@ -75,7 +76,7 @@ void duplicateVertex_isRejected() { @Test void hullBecomes3D_withFourNonCoplanarPoints() { - ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((World) null); assertTrue(region.addVertex(BlockVector3.at(0, 0, 0))); assertTrue(region.addVertex(BlockVector3.at(10, 0, 0))); assertTrue(region.addVertex(BlockVector3.at(0, 0, 10))); @@ -87,7 +88,7 @@ void hullBecomes3D_withFourNonCoplanarPoints() { @Test void backlogProcessingOrder_isMaintained() { - ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((com.sk89q.worldedit.world.World) null); + ConvexPolyhedralRegion region = new ConvexPolyhedralRegion((World) null); BlockVector3 a = BlockVector3.at(0, 0, 0); BlockVector3 b = BlockVector3.at(10, 0, 0); BlockVector3 c = BlockVector3.at(5, 0, 0); // collinear -> backlog From ad0b6dbb0d3735b6d6676d12201abe4e0df73f37 Mon Sep 17 00:00:00 2001 From: ssquadteam Date: Tue, 4 Nov 2025 15:08:58 +0600 Subject: [PATCH 3/3] Refactor import statements for ConvexPolyhedralRegion and enhance test assertions in ConvexPolyhedralRegionSpecTest --- .../worldedit/command/SelectionCommands.java | 2 +- .../ConvexPolyhedralRegionSpecTest.java | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 34e45d0549..a6c39707dc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -50,11 +50,11 @@ import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.MultiDirection; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.RegionSelector; -import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector; diff --git a/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java index 99fe4ed908..4c261e65f0 100644 --- a/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java +++ b/worldedit-core/src/test/java/com/sk89q/worldedit/regions/ConvexPolyhedralRegionSpecTest.java @@ -1,6 +1,22 @@ /* - * Tests for ConvexPolyhedralRegion and ConvexPolyhedralRegionSelector edge cases per specification. + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + package com.sk89q.worldedit.regions; import com.sk89q.worldedit.math.BlockVector3; @@ -11,7 +27,9 @@ import java.util.Optional; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class ConvexPolyhedralRegionSpecTest {