test: add tests for minecart movement along rail networks
This commit is contained in:
1 parent
963a959452
commit
eff1e30678
1 file changed
+209
@@ -0,0 +1,209 @@
|
|||||||
|
#include "testHarness.h"
|
||||||
|
#include "vf/Minecart.h"
|
||||||
|
|
||||||
|
using namespace vf;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
auto neverPowered = [](const Vec3i&) { return false; };
|
||||||
|
auto alwaysPowered = [](const Vec3i&) { return true; };
|
||||||
|
|
||||||
|
void railLine(World& world, int x0, int x1, int y, int z, Block kind) {
|
||||||
|
for (int x = x0; x <= x1; ++x) world.setBlock(x, y, z, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
VF_TEST(cartRollsAlongFlatTrackAndFrictionBringsItToRest) {
|
||||||
|
World world;
|
||||||
|
railLine(world, 0, 60, 0, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.speed = 0.3f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(cart.speed < 0.3f);
|
||||||
|
CHECK(cart.offset > 0.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < 400; ++i) tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(!cart.derailed);
|
||||||
|
CHECK(cart.railPos.x > 5);
|
||||||
|
CHECK_NEAR(cart.speed, 0.0f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(poweredRailAcceleratesCartToMaxSpeed) {
|
||||||
|
World world;
|
||||||
|
railLine(world, 0, 300, 0, 0, Block::PoweredRail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.speed = 0.05f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, alwaysPowered, store);
|
||||||
|
CHECK(cart.speed > 0.05f);
|
||||||
|
|
||||||
|
for (int i = 0; i < 30; ++i) tickMinecart(world, cart, config, alwaysPowered, store);
|
||||||
|
CHECK_NEAR(cart.speed, config.maxSpeed, 1e-4f);
|
||||||
|
CHECK(!cart.derailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(inactivePoweredRailBrakesTheCart) {
|
||||||
|
World world;
|
||||||
|
railLine(world, 0, 60, 0, 0, Block::PoweredRail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.speed = 0.3f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(cart.speed < 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(gravityAcceleratesCartDownASlope) {
|
||||||
|
World world;
|
||||||
|
world.setBlock(0, 0, 0, Block::Rail);
|
||||||
|
world.setBlock(-1, 0, 0, Block::Rail);
|
||||||
|
world.setBlock(1, 1, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({0, 0, 0}, RailDir::West, CartKind::Empty);
|
||||||
|
cart.speed = 0.0f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(cart.speed > 0.04f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(uphillDecelerationRollsTheCartBack) {
|
||||||
|
World world;
|
||||||
|
world.setBlock(0, 0, 0, Block::Rail);
|
||||||
|
world.setBlock(-1, 0, 0, Block::Rail);
|
||||||
|
world.setBlock(1, 1, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({0, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.speed = 0.03f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(cart.moveDir == RailDir::West);
|
||||||
|
CHECK(cart.speed > 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(cartDerailsWhenTrackEnds) {
|
||||||
|
World world;
|
||||||
|
world.setBlock(0, 0, 0, Block::Rail);
|
||||||
|
world.setBlock(1, 0, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({1, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.speed = 0.4f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
for (int i = 0; i < 12 && !cart.derailed; ++i)
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK(cart.derailed);
|
||||||
|
CHECK_NEAR(cart.speed, 0.0f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(hopperCartPullsFromContainerAboveOnCooldown) {
|
||||||
|
World world;
|
||||||
|
world.setBlock(5, 0, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
store.ensure({5, 1, 0}, 5).insert(ItemId::Stone, 3);
|
||||||
|
|
||||||
|
Minecart cart = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Hopper);
|
||||||
|
cart.speed = 0.0f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK_EQ(cart.inventory.totalItems(), 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 60; ++i) tickMinecart(world, cart, config, neverPowered, store);
|
||||||
|
CHECK_EQ(cart.inventory.totalItems(), 3);
|
||||||
|
CHECK_EQ(store.at({5, 1, 0})->totalItems(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(chestCartCarriesAnInventory) {
|
||||||
|
Minecart cart = makeMinecart({0, 0, 0}, RailDir::East, CartKind::Chest);
|
||||||
|
CHECK_EQ(cart.inventory.size(), chestCartSlots);
|
||||||
|
cart.inventory.insert(ItemId::DiamondGem, 12);
|
||||||
|
CHECK_EQ(cart.inventory.totalItems(), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(cartWorldPositionTracksSubCellOffset) {
|
||||||
|
Minecart cart = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
cart.offset = 0.5f;
|
||||||
|
Vec3 pos = cartWorldPos(cart);
|
||||||
|
CHECK_NEAR(pos.x, 6.0f, 1e-5f);
|
||||||
|
CHECK_NEAR(pos.z, 0.5f, 1e-5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(headOnCartsBounceApart) {
|
||||||
|
World world;
|
||||||
|
railLine(world, -40, 40, 0, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
std::vector<Minecart> carts = {
|
||||||
|
makeMinecart({3, 0, 0}, RailDir::East, CartKind::Empty),
|
||||||
|
makeMinecart({7, 0, 0}, RailDir::West, CartKind::Empty),
|
||||||
|
};
|
||||||
|
carts[0].speed = 0.3f;
|
||||||
|
carts[1].speed = 0.3f;
|
||||||
|
|
||||||
|
for (int i = 0; i < 40; ++i)
|
||||||
|
stepMinecarts(world, carts, config, neverPowered, store);
|
||||||
|
|
||||||
|
CHECK(carts[0].moveDir == RailDir::West);
|
||||||
|
CHECK(carts[1].moveDir == RailDir::East);
|
||||||
|
CHECK(carts[0].railPos.x < carts[1].railPos.x);
|
||||||
|
CHECK(!carts[0].derailed);
|
||||||
|
CHECK(!carts[1].derailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(movingCartHandsMomentumToStationaryCart) {
|
||||||
|
World world;
|
||||||
|
railLine(world, -40, 40, 0, 0, Block::Rail);
|
||||||
|
ContainerStore store;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
std::vector<Minecart> carts = {
|
||||||
|
makeMinecart({0, 0, 0}, RailDir::East, CartKind::Empty),
|
||||||
|
makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty),
|
||||||
|
};
|
||||||
|
carts[0].speed = 0.3f;
|
||||||
|
carts[1].speed = 0.0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < 40; ++i)
|
||||||
|
stepMinecarts(world, carts, config, neverPowered, store);
|
||||||
|
|
||||||
|
CHECK(carts[1].speed > carts[0].speed);
|
||||||
|
CHECK(carts[1].railPos.x > carts[0].railPos.x);
|
||||||
|
CHECK(carts[0].speed < 0.05f);
|
||||||
|
}
|
||||||
|
|
||||||
|
VF_TEST(minecartSimulationIsDeterministic) {
|
||||||
|
World world;
|
||||||
|
railLine(world, 0, 300, 0, 0, Block::PoweredRail);
|
||||||
|
ContainerStore storeA, storeB;
|
||||||
|
|
||||||
|
Minecart a = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
Minecart b = makeMinecart({5, 0, 0}, RailDir::East, CartKind::Empty);
|
||||||
|
a.speed = 0.1f;
|
||||||
|
b.speed = 0.1f;
|
||||||
|
CartConfig config;
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; ++i) {
|
||||||
|
tickMinecart(world, a, config, alwaysPowered, storeA);
|
||||||
|
tickMinecart(world, b, config, alwaysPowered, storeB);
|
||||||
|
CHECK(a.railPos == b.railPos);
|
||||||
|
CHECK(a.moveDir == b.moveDir);
|
||||||
|
CHECK_NEAR(a.speed, b.speed, 1e-6f);
|
||||||
|
CHECK_NEAR(a.offset, b.offset, 1e-6f);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user