|
|
|
|
@@ -8,8 +8,8 @@
|
|
|
|
|
#include "DespawnAtComponent.h"
|
|
|
|
|
#include "EntityAdmin.h"
|
|
|
|
|
#include "EntityHitTest.h"
|
|
|
|
|
#include "ScrapDataComponent.h"
|
|
|
|
|
#include "ScrapSystem.h"
|
|
|
|
|
#include "DebrisComponent.h"
|
|
|
|
|
#include "DebrisSystem.h"
|
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
@@ -23,15 +23,15 @@ bool contains(const std::vector<entt::entity>& v, entt::entity e)
|
|
|
|
|
// Spawn
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: spawn returns a valid entity with correct scrap data", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: spawn returns a valid entity with correct debris data", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(3.0f, 4.0f), 5, 100);
|
|
|
|
|
|
|
|
|
|
REQUIRE(admin.isValid(e));
|
|
|
|
|
REQUIRE(admin.get<ScrapDataComponent>(e).amount == 5);
|
|
|
|
|
REQUIRE(admin.get<DebrisComponent>(e).amount == 5);
|
|
|
|
|
REQUIRE(admin.get<DespawnAtComponent>(e).tick == 100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -39,10 +39,10 @@ TEST_CASE("ScrapSystem: spawn returns a valid entity with correct scrap data", "
|
|
|
|
|
// Despawn timing
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: scrap still present one tick before despawnAt", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: debris still present one tick before despawnAt", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(0.0f, 0.0f), 1, 50);
|
|
|
|
|
|
|
|
|
|
@@ -50,10 +50,10 @@ TEST_CASE("ScrapSystem: scrap still present one tick before despawnAt", "[scrap]
|
|
|
|
|
REQUIRE(admin.isValid(e));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: scrap removed at despawnAt tick", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: debris removed at despawnAt tick", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(0.0f, 0.0f), 1, 50);
|
|
|
|
|
|
|
|
|
|
@@ -65,10 +65,10 @@ TEST_CASE("ScrapSystem: scrap removed at despawnAt tick", "[scrap]")
|
|
|
|
|
// Selective removal
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: tickDespawn removes only expired scraps", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: tickDespawn removes only expired debris", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity earlyE = ss.spawn(QVector2D(0.0f, 0.0f), 1, 30);
|
|
|
|
|
const entt::entity lateE = ss.spawn(QVector2D(1.0f, 0.0f), 2, 60);
|
|
|
|
|
@@ -83,10 +83,10 @@ TEST_CASE("ScrapSystem: tickDespawn removes only expired scraps", "[scrap]")
|
|
|
|
|
// Consume
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: consume returns amount and destroys entity", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: consume returns amount and destroys entity", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(0.0f, 0.0f), 7, 100);
|
|
|
|
|
|
|
|
|
|
@@ -96,10 +96,10 @@ TEST_CASE("ScrapSystem: consume returns amount and destroys entity", "[scrap]")
|
|
|
|
|
REQUIRE_FALSE(admin.isValid(e));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: consume returns nullopt for invalid entity", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: consume returns nullopt for invalid entity", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const std::optional<int> amount = ss.consume(entt::null);
|
|
|
|
|
REQUIRE_FALSE(amount.has_value());
|
|
|
|
|
@@ -109,118 +109,118 @@ TEST_CASE("ScrapSystem: consume returns nullopt for invalid entity", "[scrap]")
|
|
|
|
|
// collectOne
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: collectOne depletes one scrap and keeps the pile until empty", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: collectOne depletes one scrap and keeps the debris until empty", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(0.0f, 0.0f), 3, 100);
|
|
|
|
|
|
|
|
|
|
REQUIRE(ss.collectOne(e));
|
|
|
|
|
REQUIRE(admin.isValid(e));
|
|
|
|
|
REQUIRE(admin.get<ScrapDataComponent>(e).amount == 2);
|
|
|
|
|
REQUIRE(admin.get<DebrisComponent>(e).amount == 2);
|
|
|
|
|
|
|
|
|
|
REQUIRE(ss.collectOne(e));
|
|
|
|
|
REQUIRE(admin.isValid(e));
|
|
|
|
|
REQUIRE(admin.get<ScrapDataComponent>(e).amount == 1);
|
|
|
|
|
REQUIRE(admin.get<DebrisComponent>(e).amount == 1);
|
|
|
|
|
|
|
|
|
|
// Final unit collected: the pile is removed once depleted.
|
|
|
|
|
// Final unit collected: the debris is removed once depleted.
|
|
|
|
|
REQUIRE(ss.collectOne(e));
|
|
|
|
|
REQUIRE_FALSE(admin.isValid(e));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: collectOne returns false for an invalid entity", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: collectOne returns false for an invalid entity", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
REQUIRE_FALSE(ss.collectOne(entt::null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// allScrapInfo
|
|
|
|
|
// getAllDebrisInfo
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: allScrapInfo returns all spawned scrap", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: getAllDebrisInfo returns all spawned debris", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
|
|
|
|
|
ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
|
|
|
|
|
|
|
|
|
|
const std::vector<ScrapInfo> info = ss.getAllScrapInfo();
|
|
|
|
|
const std::vector<DebrisInfo> info = ss.getAllDebrisInfo();
|
|
|
|
|
REQUIRE(info.size() == 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("ScrapSystem: allScrapInfo reports each pile's remaining amount", "[scrap]")
|
|
|
|
|
TEST_CASE("DebrisSystem: getAllDebrisInfo reports each debris entry.s remaining amount", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity a = ss.spawn(QVector2D(1.0f, 2.0f), 3, 100);
|
|
|
|
|
const entt::entity b = ss.spawn(QVector2D(4.0f, 5.0f), 6, 200);
|
|
|
|
|
|
|
|
|
|
const std::vector<ScrapInfo> info = ss.getAllScrapInfo();
|
|
|
|
|
const std::vector<DebrisInfo> info = ss.getAllDebrisInfo();
|
|
|
|
|
REQUIRE(info.size() == 2);
|
|
|
|
|
for (const ScrapInfo& i : info)
|
|
|
|
|
for (const DebrisInfo& i : info)
|
|
|
|
|
{
|
|
|
|
|
if (i.entity == a) { REQUIRE(i.amount == 3); }
|
|
|
|
|
else if (i.entity == b) { REQUIRE(i.amount == 6); }
|
|
|
|
|
else { FAIL("unexpected scrap entity"); }
|
|
|
|
|
else { FAIL("unexpected debris entity"); }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
// Selection hit-testing (REQ-UI-SCRAP-CLICK-SELECT, REQ-UI-SCRAP-MULTI-SELECT)
|
|
|
|
|
// Selection hit-testing (REQ-UI-DEBRIS-CLICK-SELECT, REQ-UI-DEBRIS-MULTI-SELECT)
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
TEST_CASE("scrapAtWorldPos returns the pile near a point and null when far", "[scrap]")
|
|
|
|
|
TEST_CASE("debrisAtWorldPos returns the debris near a point and null when far", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity e = ss.spawn(QVector2D(3.0f, 4.0f), 5, 100);
|
|
|
|
|
|
|
|
|
|
// Extra parens keep Catch from decomposing the comparison, which is ambiguous
|
|
|
|
|
// between Catch's expression templates and entt's entity operator==.
|
|
|
|
|
REQUIRE((scrapAtWorldPos(admin, QVector2D(3.1f, 4.0f)) == e));
|
|
|
|
|
REQUIRE((scrapAtWorldPos(admin, QVector2D(10.0f, 10.0f)) == entt::null));
|
|
|
|
|
REQUIRE((debrisAtWorldPos(admin, QVector2D(3.1f, 4.0f)) == e));
|
|
|
|
|
REQUIRE((debrisAtWorldPos(admin, QVector2D(10.0f, 10.0f)) == entt::null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("scrapAtWorldPos returns the nearest of several piles", "[scrap]")
|
|
|
|
|
TEST_CASE("debrisAtWorldPos returns the nearest of several debris", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity near = ss.spawn(QVector2D(2.0f, 2.0f), 1, 100);
|
|
|
|
|
ss.spawn(QVector2D(2.4f, 2.0f), 1, 100);
|
|
|
|
|
|
|
|
|
|
REQUIRE((scrapAtWorldPos(admin, QVector2D(2.05f, 2.0f)) == near));
|
|
|
|
|
REQUIRE((debrisAtWorldPos(admin, QVector2D(2.05f, 2.0f)) == near));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("entityAtWorldPos never returns a scrap pile", "[scrap]")
|
|
|
|
|
TEST_CASE("entityAtWorldPos never returns debris", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
ss.spawn(QVector2D(3.0f, 4.0f), 5, 100);
|
|
|
|
|
|
|
|
|
|
// Scrap has no HealthComponent, so the actor hit-test ignores it entirely.
|
|
|
|
|
// Debris has no HealthComponent, so the actor hit-test ignores it entirely.
|
|
|
|
|
REQUIRE((entityAtWorldPos(admin, QVector2D(3.0f, 4.0f)) == entt::null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("scrapInBox returns exactly the piles inside the tile rectangle", "[scrap]")
|
|
|
|
|
TEST_CASE("debrisInBox returns exactly the debris inside the tile rectangle", "[debris]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
ScrapSystem ss(admin);
|
|
|
|
|
DebrisSystem ss(admin);
|
|
|
|
|
|
|
|
|
|
const entt::entity inA = ss.spawn(QVector2D(1.2f, 2.7f), 1, 100); // tile (1,2)
|
|
|
|
|
const entt::entity inB = ss.spawn(QVector2D(4.9f, 5.1f), 1, 100); // tile (4,5)
|
|
|
|
|
const entt::entity outX = ss.spawn(QVector2D(10.0f, 10.0f), 1, 100);
|
|
|
|
|
|
|
|
|
|
// Box given in reversed corner order to confirm normalization.
|
|
|
|
|
const std::vector<entt::entity> hit = scrapInBox(admin, QPoint(5, 5), QPoint(0, 0));
|
|
|
|
|
const std::vector<entt::entity> hit = debrisInBox(admin, QPoint(5, 5), QPoint(0, 0));
|
|
|
|
|
|
|
|
|
|
REQUIRE(hit.size() == 2);
|
|
|
|
|
REQUIRE(contains(hit, inA));
|
|
|
|
|
@@ -228,7 +228,7 @@ TEST_CASE("scrapInBox returns exactly the piles inside the tile rectangle", "[sc
|
|
|
|
|
REQUIRE_FALSE(contains(hit, outX));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("actorsInBox returns living ships and stations, excluding scrap and dead actors",
|
|
|
|
|
TEST_CASE("actorsInBox returns living ships and stations, excluding debris and dead actors",
|
|
|
|
|
"[actor]")
|
|
|
|
|
{
|
|
|
|
|
EntityAdmin admin;
|
|
|
|
|
@@ -256,8 +256,8 @@ TEST_CASE("actorsInBox returns living ships and stations, excluding scrap and de
|
|
|
|
|
const entt::entity station = admin.spawnStation(
|
|
|
|
|
QPoint(2, 2), QSize(2, 1), stationCells, 200.0f, 200.0f, true);
|
|
|
|
|
|
|
|
|
|
// Scrap and the HQ proxy are never actors.
|
|
|
|
|
admin.spawnScrap(QVector2D(1.0f, 1.0f), 5, Tick(1000));
|
|
|
|
|
// Debris and the HQ proxy are never actors.
|
|
|
|
|
admin.spawnDebris(QVector2D(1.0f, 1.0f), 5, Tick(1000));
|
|
|
|
|
admin.spawnHqProxy(QVector2D(0.5f, 0.5f), 500.0f, 500.0f);
|
|
|
|
|
|
|
|
|
|
const std::vector<entt::entity> hit = actorsInBox(admin, QPoint(5, 5), QPoint(0, 0));
|