Files
EVEngine/test/definition_runtime_weapon.cpp

107 lines
4.4 KiB
C++

#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
#include "common/definitions/RuntimeSnapshot.h"
#include "definitions/Definitions.h"
#include "weapon/WeaponDefinitionRuntime.h"
#include <cstdint>
#include <string_view>
#include <utility>
namespace {
eve::PersistentId testId() {
const auto parsed = eve::PersistentId::parse("33333333-3333-7333-8333-333333333333");
return *parsed;
}
eve::SnapshotHashProvider testHash() {
return [](std::string_view input) -> eve::Result<eve::ContentId> {
eve::ContentId::Bytes bytes{};
std::uint8_t value = 41;
for (std::size_t index = 0; index < bytes.size(); ++index) {
for (const unsigned char byte : input) value = static_cast<std::uint8_t>(value * 33u + byte + index);
bytes[index] = static_cast<std::uint8_t>(value + index);
}
return eve::Result<eve::ContentId>::success(eve::ContentId(bytes));
};
}
eve::DefinitionRef weaponRef() {
auto result = eve::DefinitionRef::parse("weapon:rifle");
if (!result.ok()) return {};
return std::move(result).takeValue();
}
} // namespace
TEST_CASE("definitionRuntime.weaponTypedStateSnapshotReloadAndStale") {
eve::definitions::DefinitionRegistry registry;
const std::string original = R"JSON({
"id":"rifle", "kind":"ranged", "logic":"hitscan", "damage":25,
"range":500, "spreadMin":1, "spreadMax":8,
"ammo":{"mag":30,"reserve":90,"reload":2},
"resource":{"kind":"ammo","max":30,"cost":1,"infinite":false},
"projectile":{"type":"bullet","speed":800,"pelletCount":1}
})JSON";
auto inserted = registry.insert("weapon", "rifle", 1, original);
REQUIRE(inserted.ok());
auto created = eve::weapon::WeaponDefinitionRuntime::create(registry, weaponRef(), testId(),
eve::definition::ReloadPolicy::RebuildInstance);
REQUIRE(created.ok());
auto runtime = std::move(created).takeValue();
const auto oldHandle = runtime.definitionHandle();
auto typed = runtime.definition();
REQUIRE(typed.ok());
CHECK_EQ(typed.value().damage, 25.f);
CHECK_EQ(typed.value().projectile.type, std::string("bullet"));
CHECK_EQ(runtime.state().resource.value, 30.f);
runtime.state().resource.value = 7.f;
runtime.state().currentSpread = 4.f;
auto snapshot = runtime.snapshot(eve::Revision(2), eve::SimulationTick(17), testHash());
REQUIRE(snapshot.ok());
runtime.state().resource.value = 1.f;
runtime.state().currentSpread = 0.f;
auto restored = runtime.restore(snapshot.value(), testHash());
REQUIRE(restored.ok());
CHECK_EQ(runtime.state().resource.value, 7.f);
CHECK_EQ(runtime.state().currentSpread, 4.f);
const std::string replacement = R"JSON({
"id":"rifle", "kind":"ranged", "logic":"hitscan", "damage":40,
"range":700, "spreadMin":2, "spreadMax":3,
"ammo":{"mag":10,"reserve":20,"reload":1}
})JSON";
auto replaced = registry.replace("weapon", "rifle", 1, replacement);
REQUIRE(replaced.ok());
auto reloaded = runtime.reload(eve::definition::ReloadPolicy::RebuildInstance);
REQUIRE(reloaded.ok());
CHECK(runtime.definitionHandle().generation != oldHandle.generation);
CHECK_EQ(runtime.state().resource.value, 7.f);
CHECK_EQ(runtime.state().currentSpread, 3.f);
auto stale = runtime.restore(snapshot.value(), testHash());
CHECK(!stale.ok());
CHECK_EQ(runtime.state().resource.value, 7.f);
}
TEST_CASE("definitionRuntime.weaponRejectWhileActiveIsAtomic") {
eve::definitions::DefinitionRegistry registry;
const auto first =
registry.insert("weapon", "rifle", 1, R"JSON({"id":"rifle","kind":"ranged","ammo":{"mag":4}})JSON");
REQUIRE(first.ok());
auto created = eve::weapon::WeaponDefinitionRuntime::create(registry, weaponRef(), testId());
REQUIRE(created.ok());
auto runtime = std::move(created).takeValue();
runtime.setActive(true);
const auto before = runtime.definitionHandle();
const auto replacement =
registry.replace("weapon", "rifle", 1, R"JSON({"id":"rifle","kind":"ranged","ammo":{"mag":8}})JSON");
REQUIRE(replacement.ok());
auto rejected = runtime.reload(eve::definition::ReloadPolicy::RejectWhileActive);
CHECK(!rejected.ok());
CHECK_EQ(runtime.definitionHandle().generation, before.generation);
}