chute
This commit is contained in:
162
tests/Components/test_Chute.cpp
Normal file
162
tests/Components/test_Chute.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <doctest/doctest.h>
|
||||
#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<Inventory>().AddItems(stoneID, 3);
|
||||
|
||||
auto dest = world.GetEcsWorld().entity();
|
||||
Inventory_Helper(dest, config, 100);
|
||||
|
||||
// vertical drop: (0,10) -> (0,0), should be fast
|
||||
std::vector<Vector2> path = { {0, 10}, {0, 0} };
|
||||
auto chuteEntity = world.GetEcsWorld().entity();
|
||||
Chute_Helper(chuteEntity, path,
|
||||
source.get<Inventory>(),
|
||||
dest.get<Inventory>());
|
||||
|
||||
// get the transit time
|
||||
auto chute = chuteEntity.get<Chute>();
|
||||
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<Inventory>();
|
||||
CHECK(srcInv.GetItemsAmount(stoneID) == 0);
|
||||
|
||||
// tick until items arrive
|
||||
for (uint16_t i = 1; i < transitTicks; ++i)
|
||||
world.ProcessFrame();
|
||||
|
||||
auto destInv = dest.get<Inventory>();
|
||||
CHECK(destInv.GetItemsAmount(stoneID) == 0);
|
||||
|
||||
world.ProcessFrame();
|
||||
|
||||
destInv = dest.get<Inventory>();
|
||||
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<Inventory>().AddItems(ironID, 1);
|
||||
|
||||
auto dest = world.GetEcsWorld().entity();
|
||||
Inventory_Helper(dest, config, 100);
|
||||
|
||||
// multi-link path with gradual descent
|
||||
std::vector<Vector2> path = { {0, 10}, {1, 9}, {2, 8}, {3, 7}, {4, 6}, {5, 5} };
|
||||
auto chuteEntity = world.GetEcsWorld().entity();
|
||||
Chute_Helper(chuteEntity, path,
|
||||
source.get<Inventory>(),
|
||||
dest.get<Inventory>());
|
||||
|
||||
auto chute = chuteEntity.get<Chute>();
|
||||
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<Inventory>();
|
||||
CHECK(destInv.GetItemsAmount(ironID) == 0);
|
||||
|
||||
// one more tick — item arrives
|
||||
world.ProcessFrame();
|
||||
|
||||
destInv = dest.get<Inventory>();
|
||||
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<Inventory>().AddItems(stoneID, 3);
|
||||
|
||||
// destination can only hold 1
|
||||
auto dest = world.GetEcsWorld().entity();
|
||||
Inventory_Helper(dest, config, 1);
|
||||
|
||||
std::vector<Vector2> path = { {0, 10}, {0, 0} };
|
||||
auto chuteEntity = world.GetEcsWorld().entity();
|
||||
Chute_Helper(chuteEntity, path,
|
||||
source.get<Inventory>(),
|
||||
dest.get<Inventory>());
|
||||
|
||||
auto chute = chuteEntity.get<Chute>();
|
||||
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<Inventory>();
|
||||
CHECK(destInv.GetItemsAmount(stoneID) == 1);
|
||||
|
||||
auto& worldInv = world.GetEcsWorld().ensure<WorldInventory>();
|
||||
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<Inventory>().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<Vector2> path = { {0, 0}, {5, 0} };
|
||||
auto chuteEntity = world.GetEcsWorld().entity();
|
||||
Chute_Helper(chuteEntity, path,
|
||||
source.get<Inventory>(),
|
||||
dest.get<Inventory>(),
|
||||
chuteConfig);
|
||||
|
||||
auto chute = chuteEntity.get<Chute>();
|
||||
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<Inventory>();
|
||||
CHECK(destInv.GetItemsAmount(woodID) == 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user