Use independent street and avenue settings

This commit is contained in:
2026-09-27 08:11:52 -07:00
parent d68f7543ea
commit 8d99c2e67f
14 changed files with 425 additions and 161 deletions

View File

@@ -40,6 +40,39 @@ import org.bukkit.block.data.type.Stairs;
import org.junit.jupiter.api.Test;
class AvenueStairwayBuilderTest {
@Test
void buildsStreetStairsFacingEastWithWestFacingInvertedBacking() {
Cuboid plot = new Cuboid(2, 62, 2, 33, 71, 33);
Flight flight =
AvenueStairwayLayout.forUpperStreetSegments(plot, 32, 36, 0, 1, 4, 2, 62, 14, 3).getFirst();
World world = mock(World.class);
Map<Step, Block> blocks = new HashMap<>();
Map<Step, Stairs> blockData = new HashMap<>();
when(world.getBlockAt(anyInt(), anyInt(), anyInt()))
.thenAnswer(
invocation -> {
Step position =
new Step(
invocation.getArgument(0),
invocation.getArgument(1),
invocation.getArgument(2));
return blocks.computeIfAbsent(
position,
ignored -> {
Block block = mock(Block.class);
Stairs stairs = mock(Stairs.class);
when(block.getBlockData()).thenReturn(stairs);
blockData.put(position, stairs);
return block;
});
});
AvenueStairwayBuilder.build(world, flight, Material.COBBLESTONE_STAIRS);
verify(blockData.get(flight.stairBlocks().getFirst())).setFacing(BlockFace.EAST);
verify(blockData.get(flight.invertedBackingBlocks().getFirst())).setFacing(BlockFace.WEST);
}
@Test
void buildsAscendingAndInvertedStairsAndClearsOnlyThePlannedOpening() {
Cuboid plot = new Cuboid(2, 62, 2, 33, 71, 33);

View File

@@ -104,6 +104,25 @@ class AvenueStairwayLayoutTest {
new AvenueStairwayLayout.Step(-1, 63, 48), flights.getLast().stairBlocks().getFirst());
}
@Test
void createsStreetFlightsAlongXOnBothNorthAndSouthBorders() {
Cuboid twoByTwoPlot = new Cuboid(2, 62, 2, 69, 71, 69);
List<AvenueStairwayLayout.Flight> flights =
AvenueStairwayLayout.forUpperStreetSegments(twoByTwoPlot, 32, 36, 0, 1, 4, 2, 62, 14, 3);
assertEquals(4, flights.size());
assertEquals(AvenueStairwayLayout.Side.NORTH, flights.getFirst().side());
assertEquals(
new AvenueStairwayLayout.Step(12, 63, -1), flights.getFirst().stairBlocks().getFirst());
assertEquals(AvenueStairwayLayout.Side.SOUTH, flights.get(1).side());
assertEquals(
new AvenueStairwayLayout.Step(12, 63, 71), flights.get(1).stairBlocks().getFirst());
assertEquals(
new AvenueStairwayLayout.Step(48, 63, -1), flights.get(2).stairBlocks().getFirst());
assertTrue(flights.stream().allMatch(flight -> flight.stairBlocks().getLast().y() == 76));
}
@Test
void rejectsAStairRunThatCannotFitWithinThePlotLength() {
Cuboid plot = new Cuboid(2, 62, 2, 33, 71, 13);

View File

@@ -30,19 +30,30 @@ class RoadLayoutTest {
@Test
void buildsFullRoadWidthAndNonOverlappingCornersAtOnce() {
List<RoadLayout.BlockPosition> road = RoadLayout.surroundingRoad(PLOT, 4);
List<RoadLayout.BlockPosition> road = RoadLayout.surroundingRoad(PLOT, 4, 4);
HashSet<RoadLayout.BlockPosition> uniqueBlocks = new HashSet<>(road);
assertEquals(576, road.size());
assertEquals(road.size(), uniqueBlocks.size());
assertTrue(road.contains(new RoadLayout.BlockPosition(34, 2)));
assertTrue(road.contains(new RoadLayout.BlockPosition(37, 33)));
assertTrue(road.contains(new RoadLayout.BlockPosition(2, 34)));
assertTrue(road.contains(new RoadLayout.BlockPosition(33, 37)));
assertTrue(road.contains(new RoadLayout.BlockPosition(34, 2, RoadLayout.RoadType.AVENUE)));
assertTrue(road.contains(new RoadLayout.BlockPosition(2, 34, RoadLayout.RoadType.STREET)));
assertTrue(
road.contains(new RoadLayout.BlockPosition(34, 34, RoadLayout.RoadType.INTERSECTION)));
}
@Test
void returnsNoRoadForZeroWidth() {
assertTrue(RoadLayout.surroundingRoad(PLOT, 0).isEmpty());
assertTrue(RoadLayout.surroundingRoad(PLOT, 0, 0).isEmpty());
}
@Test
void usesIndependentWidthsForStreetAndAvenueBands() {
List<RoadLayout.BlockPosition> road = RoadLayout.surroundingRoad(PLOT, 2, 4);
assertEquals(416, road.size());
assertTrue(road.contains(new RoadLayout.BlockPosition(2, 0, RoadLayout.RoadType.STREET)));
assertTrue(road.contains(new RoadLayout.BlockPosition(-2, 2, RoadLayout.RoadType.AVENUE)));
assertTrue(
road.contains(new RoadLayout.BlockPosition(-2, 0, RoadLayout.RoadType.INTERSECTION)));
}
}

View File

@@ -26,30 +26,37 @@ import org.junit.jupiter.api.Test;
class SpawnLayoutTest {
@Test
void defaultMultipliersPreserveTheOnePlotSpawnBounds() {
Cuboid spawn = SpawnLayout.bounds(1, 1, 1, 32, 10, 32, 4, 62);
Cuboid spawn = SpawnLayout.bounds(1, 1, 1, 32, 10, 32, 4, 4, 62);
assertEqualsBounds(spawn, 2, 62, 2, 33, 71, 33);
}
@Test
void appliesEachMultiplierToItsOwnAlignedGridDimension() {
Cuboid spawn = SpawnLayout.bounds(2, 3, 4, 32, 10, 32, 4, 62);
Cuboid spawn = SpawnLayout.bounds(2, 3, 4, 32, 10, 32, 4, 4, 62);
assertEqualsBounds(spawn, 2, 62, 2, 69, 91, 141);
}
@Test
void validatesTheEntireSpawnHeightAgainstWorldBounds() {
Cuboid spawn = SpawnLayout.bounds(1, 3, 1, 32, 10, 32, 4, 62);
Cuboid spawn = SpawnLayout.bounds(1, 3, 1, 32, 10, 32, 4, 4, 62);
assertTrue(SpawnLayout.withinBuildHeight(spawn, -64, 320));
assertFalse(SpawnLayout.withinBuildHeight(spawn, -64, 91));
}
@Test
void alignsSpawnAxesToTheirIndependentRoadWidths() {
Cuboid spawn = SpawnLayout.bounds(2, 1, 3, 32, 10, 32, 6, 2, 62);
assertEqualsBounds(spawn, 3, 62, 1, 72, 71, 100);
}
@Test
void rejectsNonPositiveSpawnMultipliers() {
assertThrows(
IllegalArgumentException.class, () -> SpawnLayout.bounds(0, 1, 1, 32, 10, 32, 4, 62));
IllegalArgumentException.class, () -> SpawnLayout.bounds(0, 1, 1, 32, 10, 32, 4, 4, 62));
}
private static void assertEqualsBounds(

View File

@@ -82,6 +82,6 @@ class MetropolisHomeAcquireTest {
assertEquals(4, MetropolisPlugin.normalizeMaxLevels(4));
assertEquals(3, MetropolisPlugin.clampMaxLevels(10, 3));
assertEquals(1, MetropolisPlugin.clampMaxLevels(2, 1));
assertEquals(1, MetropolisPlugin.clampMaxLevels(0, 0));
assertEquals(0, MetropolisPlugin.clampMaxLevels(0, 0));
}
}