From dd5527667505c87701c1134327fc8c6a565cab2c Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sat, 12 Sep 2026 18:10:15 +0200 Subject: [PATCH] test: cover testPortal --- tests/testPortal.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/tests/testPortal.cpp b/tests/testPortal.cpp index 656518a..2fd4d8a 100644 --- a/tests/testPortal.cpp +++ b/tests/testPortal.cpp @@ -159,3 +159,162 @@ VF_TEST(breakingTheFrameUnmakesTheLitPortal) { CHECK(!network.portal(id)->active); } +VF_TEST(ignitingTheSameFrameTwiceReusesItsRegistration) { + DimensionSet dimensions(78u); + PortalNetwork network(dimensions); + World& world = dimensions.overworld().world(); + layFrame(world, {4, 40, 4}, 2, 3, true); + + int first = network.ignite(DimensionId::Overworld, {4, 41, 4}); + int second = network.ignite(DimensionId::Overworld, {5, 42, 4}); + CHECK_EQ(first, second); + CHECK_EQ(network.links().size(), static_cast(1)); + + CHECK_EQ(network.ignite(DimensionId::Overworld, {40, 40, 40}), -1); +} + +VF_TEST(travellersChargeInThePortalAndThenSitOutACooldown) { + DimensionSet dimensions(80u); + PortalNetwork network(dimensions); + World& world = dimensions.overworld().world(); + layFrame(world, {4, 40, 4}, 2, 3, true); + int source = network.ignite(DimensionId::Overworld, {4, 41, 4}); + + for (int tick = 0; tick < network.requiredStandingTicks() - 1; ++tick) + network.tickEntity(1, true); + CHECK_EQ(network.standingTicks(1), network.requiredStandingTicks() - 1); + CHECK(!network.readyToTravel(1)); + + PortalSearch tooEarly = network.travel(1, source, DimensionId::Nether); + CHECK(!tooEarly.found); + CHECK(tooEarly.blocked); + + network.tickEntity(1, true); + CHECK(network.readyToTravel(1)); + + PortalSearch crossing = network.travel(1, source, DimensionId::Nether); + CHECK(crossing.found); + CHECK_EQ(network.cooldownTicks(1), network.cooldownLength()); + CHECK_EQ(network.standingTicks(1), 0); + + PortalSearch immediate = network.travel(1, source, DimensionId::Nether); + CHECK(immediate.blocked); + + // Stepping out of the portal resets the charge; the cooldown drains anyway. + for (int tick = 0; tick < network.cooldownLength(); ++tick) network.tickEntity(1, false); + CHECK_EQ(network.cooldownTicks(1), 0); + CHECK_EQ(network.standingTicks(1), 0); + CHECK(!network.readyToTravel(1)); +} + +VF_TEST(crossingToAnEmptyNetherRaisesANewPortalThere) { + DimensionSet dimensions(4242u); + PortalNetwork network(dimensions); + dimensions.overworld().generateArea(0, 0, 1); + layFrame(dimensions.overworld().world(), {800, 40, 400}, 2, 3, true); + + int source = network.ignite(DimensionId::Overworld, {800, 41, 400}); + CHECK(source >= 0); + chargeTraveller(network, 3); + + PortalSearch crossing = network.travel(3, source, DimensionId::Nether); + CHECK(crossing.found); + CHECK(crossing.built); + CHECK_EQ(crossing.plan.scaledTarget.x, 100); + CHECK_EQ(crossing.plan.scaledTarget.z, 50); + CHECK(crossing.plan.needsPortal); + CHECK_EQ(network.activeCountIn(DimensionId::Nether), 1); + + const PortalLink* raised = network.portal(crossing.portalId); + CHECK_EQ(static_cast(raised->dimension), static_cast(DimensionId::Nether)); + CHECK(PortalScan::intact(dimensions.nether().world(), raised->frame)); + CHECK_EQ(countInterior(dimensions.nether().world(), raised->frame, Block::NetherPortal), 6); + + // The arrival must sit close to the scaled coordinates, not anywhere. + CHECK(std::abs(crossing.position.x - 100) <= DimensionTravel::buildRadiusFor(DimensionId::Nether)); + CHECK(std::abs(crossing.position.z - 50) <= DimensionTravel::buildRadiusFor(DimensionId::Nether)); + + CHECK_EQ(network.portal(source)->linkedId, crossing.portalId); + CHECK_EQ(raised->linkedId, source); +} + +VF_TEST(crossingReusesAPortalThatIsAlreadyOnTheFarSide) { + DimensionSet dimensions(4242u); + PortalNetwork network(dimensions); + dimensions.overworld().generateArea(50, 25, 1); + layFrame(dimensions.overworld().world(), {800, 40, 400}, 2, 3, true); + int source = network.ignite(DimensionId::Overworld, {800, 41, 400}); + + PortalFrame waiting; + waiting.origin = {104, 44, 52}; + waiting.width = 2; + waiting.height = 3; + waiting.alongX = true; + PortalScan::buildFrame(dimensions.nether().world(), waiting); + PortalScan::light(dimensions.nether().world(), waiting); + int existing = network.registerPortal(DimensionId::Nether, waiting); + + chargeTraveller(network, 5); + PortalSearch crossing = network.travel(5, source, DimensionId::Nether); + CHECK(crossing.found); + CHECK(!crossing.built); + CHECK_EQ(crossing.portalId, existing); + CHECK_EQ(network.activeCountIn(DimensionId::Nether), 1); + CHECK_EQ(crossing.position.x, waiting.entry().x); + CHECK_EQ(crossing.position.y, waiting.entry().y); + CHECK_EQ(crossing.position.z, waiting.entry().z); +} + +VF_TEST(findNearestOnlyReportsLivePortalsInRange) { + DimensionSet dimensions(91u); + PortalNetwork network(dimensions); + World& world = dimensions.overworld().world(); + + layFrame(world, {0, 40, 0}, 2, 3, true); + layFrame(world, {60, 40, 0}, 2, 3, true); + int close = network.ignite(DimensionId::Overworld, {0, 41, 0}); + int far = network.ignite(DimensionId::Overworld, {60, 41, 0}); + CHECK(close != far); + + PortalSearch found = network.findNearest(DimensionId::Overworld, {3, 41, 0}, 16); + CHECK(found.found); + CHECK_EQ(found.portalId, close); + + CHECK(!network.findNearest(DimensionId::Nether, {0, 41, 0}, 128).found); + CHECK(!network.findNearest(DimensionId::Overworld, {300, 41, 0}, 16).found); + + PortalSearch reach = network.findNearest(DimensionId::Overworld, {30, 41, 0}, 64); + CHECK(reach.found); +} + +VF_TEST(relinkingAPortalDropsItsPreviousPartner) { + DimensionSet dimensions(93u); + PortalNetwork network(dimensions); + World& world = dimensions.overworld().world(); + + layFrame(world, {0, 40, 0}, 2, 3, true); + layFrame(world, {20, 40, 0}, 2, 3, true); + layFrame(world, {40, 40, 0}, 2, 3, true); + int first = network.ignite(DimensionId::Overworld, {0, 41, 0}); + int second = network.ignite(DimensionId::Overworld, {20, 41, 0}); + int third = network.ignite(DimensionId::Overworld, {40, 41, 0}); + + network.linkPortals(first, second); + CHECK_EQ(network.portal(first)->linkedId, second); + CHECK_EQ(network.portal(second)->linkedId, first); + + network.linkPortals(first, third); + CHECK_EQ(network.portal(first)->linkedId, third); + CHECK_EQ(network.portal(third)->linkedId, first); + CHECK_EQ(network.portal(second)->linkedId, -1); +} + +VF_TEST(builtFrameCarvesItsOwnApproachOutOfTheTerrain) { + DimensionSet dimensions(95u); + World& world = dimensions.nether().world(); + + for (int gx = 0; gx < 10; ++gx) + for (int gy = 40; gy < 50; ++gy) + for (int gz = 0; gz < 10; ++gz) + world.setBlock(gx, gy, gz, Block::Netherrack); +