#include #include "Components/Configs/WorldConfig.hpp" #include "Core/WorldInstance.h" #include "Components/Chute.hpp" TEST_SUITE("Chute") { TEST_CASE("chute transports item from source to destination") { WorldConfig config{}; uint16_t stoneID = config.RegisterItem("Stone"); WorldInstance world{ config }; // source inventory with items, destination empty auto source = world.GetEcsWorld().entity(); Inventory_Helper(source, config, 100); source.ensure().AddItems(stoneID, 3); auto dest = world.GetEcsWorld().entity(); Inventory_Helper(dest, config, 100); // vertical drop: (0,10) -> (0,0), should be fast std::vector path = { {0, 10}, {0, 0} }; auto chuteEntity = world.GetEcsWorld().entity(); Chute_Helper(chuteEntity, path, source.get(), dest.get()); // get the transit time auto chute = chuteEntity.get(); uint16_t transitTicks = chute.Data.GetMetaData()->TicksToReachEnd; CHECK(transitTicks > 0); // tick once to pull items from source into chute world.ProcessFrame(); auto srcInv = source.get(); CHECK(srcInv.GetItemsAmount(stoneID) == 0); // tick until items arrive for (uint16_t i = 1; i < transitTicks; ++i) world.ProcessFrame(); auto destInv = dest.get(); CHECK(destInv.GetItemsAmount(stoneID) == 0); world.ProcessFrame(); destInv = dest.get(); CHECK(destInv.GetItemsAmount(stoneID) == 3); } TEST_CASE("chute respects transit time for longer paths") { WorldConfig config{}; uint16_t ironID = config.RegisterItem("Iron"); WorldInstance world{ config }; auto source = world.GetEcsWorld().entity(); Inventory_Helper(source, config, 100); source.ensure().AddItems(ironID, 1); auto dest = world.GetEcsWorld().entity(); Inventory_Helper(dest, config, 100); // multi-link path with gradual descent std::vector path = { {0, 10}, {1, 9}, {2, 8}, {3, 7}, {4, 6}, {5, 5} }; auto chuteEntity = world.GetEcsWorld().entity(); Chute_Helper(chuteEntity, path, source.get(), dest.get()); auto chute = chuteEntity.get(); uint16_t transitTicks = chute.Data.GetMetaData()->TicksToReachEnd; CHECK(transitTicks > 1); // pull items into chute world.ProcessFrame(); // tick one less than transit time — item should not have arrived for (uint16_t i = 1; i < transitTicks; ++i) world.ProcessFrame(); auto destInv = dest.get(); CHECK(destInv.GetItemsAmount(ironID) == 0); // one more tick — item arrives world.ProcessFrame(); destInv = dest.get(); CHECK(destInv.GetItemsAmount(ironID) == 1); } TEST_CASE("chute overflows to world inventory when destination is full") { WorldConfig config{}; uint16_t stoneID = config.RegisterItem("Stone"); WorldInstance world{ config }; auto source = world.GetEcsWorld().entity(); Inventory_Helper(source, config, 100); source.ensure().AddItems(stoneID, 3); // destination can only hold 1 auto dest = world.GetEcsWorld().entity(); Inventory_Helper(dest, config, 1); std::vector path = { {0, 10}, {0, 0} }; auto chuteEntity = world.GetEcsWorld().entity(); Chute_Helper(chuteEntity, path, source.get(), dest.get()); auto chute = chuteEntity.get(); uint16_t transitTicks = chute.Data.GetMetaData()->TicksToReachEnd; // tick enough for all items to arrive for (uint16_t i = 0; i <= transitTicks; ++i) world.ProcessFrame(); auto destInv = dest.get(); CHECK(destInv.GetItemsAmount(stoneID) == 1); auto& worldInv = world.GetEcsWorld().ensure(); CHECK(worldInv.GetItemsAmount(stoneID) == 2); } TEST_CASE("horizontal chute uses minimum speed") { WorldConfig config{}; uint16_t woodID = config.RegisterItem("Wood"); WorldInstance world{ config }; auto source = world.GetEcsWorld().entity(); Inventory_Helper(source, config, 100); source.ensure().AddItems(woodID, 1); auto dest = world.GetEcsWorld().entity(); Inventory_Helper(dest, config, 100); // flat path: dy=0 throughout, should use MinSpeed ChuteConfig chuteConfig{ .Gravity = 1.0f, .MinSpeed = 0.5f }; std::vector path = { {0, 0}, {5, 0} }; auto chuteEntity = world.GetEcsWorld().entity(); Chute_Helper(chuteEntity, path, source.get(), dest.get(), chuteConfig); auto chute = chuteEntity.get(); uint16_t transitTicks = chute.Data.GetMetaData()->TicksToReachEnd; // distance=5, speed=0.5 -> 10 ticks CHECK(transitTicks == 10); // tick enough for item to arrive for (uint16_t i = 0; i <= transitTicks; ++i) world.ProcessFrame(); auto destInv = dest.get(); CHECK(destInv.GetItemsAmount(woodID) == 1); } }