Files
voxelforge/tests/testDispenser.cpp

129 lines
4.5 KiB
C++

#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());
}
}