test: add tests for dispenser item ejection triggered by circuit signal
This commit is contained in:
1 parent
854dcfaf15
commit
825ce42d8d
1 file changed
+128
@@ -0,0 +1,128 @@
|
||||
#include "testHarness.h"
|
||||
#include "vf/Dispenser.h"
|
||||
|
||||
using namespace vf;
|
||||
|
||||
VF_TEST(dispenserFiresOnlyOnRisingEdge) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::Stone, 5);
|
||||
store.ensure(pos + Vec3i{1, 0, 0}, dispenserSlots); // container in front
|
||||
|
||||
DispenserState state;
|
||||
CHECK(tickDropper(world, pos, state, store, 0).action == DispenseAction::None);
|
||||
CHECK(tickDropper(world, pos, state, store, 15).action == DispenseAction::InsertedToContainer);
|
||||
CHECK(tickDropper(world, pos, state, store, 15).action == DispenseAction::None);
|
||||
CHECK(tickDropper(world, pos, state, store, 0).action == DispenseAction::None);
|
||||
CHECK(tickDropper(world, pos, state, store, 15).action == DispenseAction::InsertedToContainer);
|
||||
|
||||
CHECK_EQ(store.at(pos + Vec3i{1, 0, 0})->totalItems(), 2);
|
||||
CHECK_EQ(store.at(pos)->totalItems(), 3);
|
||||
}
|
||||
|
||||
VF_TEST(dispenserPlacesBlockItemIntoAirInFront) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
Vec3i front{6, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::Stone, 1);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDispenser(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::PlacedBlock);
|
||||
CHECK(world.blockAt(front.x, front.y, front.z) == Block::Stone);
|
||||
CHECK_EQ(store.at(pos)->totalItems(), 0);
|
||||
}
|
||||
|
||||
VF_TEST(dispenserEjectsNonBlockItemIntoFrontContainer) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::IronIngot, 2);
|
||||
store.ensure(pos + Vec3i{1, 0, 0}, dispenserSlots);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDispenser(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::InsertedToContainer);
|
||||
CHECK_EQ(store.at(pos + Vec3i{1, 0, 0})->totalItems(), 1);
|
||||
CHECK_EQ(store.at(pos)->totalItems(), 1);
|
||||
}
|
||||
|
||||
VF_TEST(dispenserEjectsToWorldWhenItCannotPlaceOrDeposit) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::IronIngot, 1);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDispenser(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::EjectedToWorld);
|
||||
CHECK(static_cast<int>(res.item.item) == static_cast<int>(ItemId::IronIngot));
|
||||
CHECK(world.blockAt(6, 5, 5) == Block::Air);
|
||||
}
|
||||
|
||||
VF_TEST(dispenserThatCannotPlaceIntoOccupiedCellEjectsInstead) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
world.setBlock(6, 5, 5, Block::Stone); // front already occupied
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::Dirt, 1);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDispenser(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::EjectedToWorld);
|
||||
CHECK(world.blockAt(6, 5, 5) == Block::Stone); // unchanged
|
||||
}
|
||||
|
||||
VF_TEST(dropperNeverPlacesBlocksEvenForBlockItems) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::Stone, 1);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDropper(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::EjectedToWorld);
|
||||
CHECK(world.blockAt(6, 5, 5) == Block::Air);
|
||||
}
|
||||
|
||||
VF_TEST(dropperDepositsBlockItemIntoFrontContainer) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots).insert(ItemId::Stone, 1);
|
||||
store.ensure(pos + Vec3i{1, 0, 0}, dispenserSlots);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDropper(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::InsertedToContainer);
|
||||
CHECK_EQ(store.at(pos + Vec3i{1, 0, 0})->totalItems(), 1);
|
||||
}
|
||||
|
||||
VF_TEST(emptyDispenserDoesNothingOnEdge) {
|
||||
World world;
|
||||
Vec3i pos{5, 5, 5};
|
||||
ContainerStore store;
|
||||
store.ensure(pos, dispenserSlots);
|
||||
|
||||
DispenserState state;
|
||||
DispenseResult res = tickDispenser(world, pos, state, store, 15);
|
||||
CHECK(res.action == DispenseAction::None);
|
||||
}
|
||||
|
||||
VF_TEST(slotSelectionIsDeterministicAndAlwaysHitsAFilledSlot) {
|
||||
Container inventory(9);
|
||||
inventory.setSlot(0, ItemSlot{ItemId::Stone, 10, 0});
|
||||
inventory.setSlot(3, ItemSlot{ItemId::Dirt, 10, 0});
|
||||
inventory.setSlot(7, ItemSlot{ItemId::Sand, 10, 0});
|
||||
|
||||
std::uint32_t rngA = 0x1234abcdu;
|
||||
std::uint32_t rngB = 0x1234abcdu;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
int a = chooseNonEmptySlot(inventory, rngA);
|
||||
int b = chooseNonEmptySlot(inventory, rngB);
|
||||
CHECK_EQ(a, b);
|
||||
CHECK(!inventory.slot(a).empty());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user