170 lines
5.8 KiB
Python
170 lines
5.8 KiB
Python
import unreal
|
|
|
|
|
|
MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test"
|
|
|
|
EXPECTED_PLAYABLE_ACTORS = {
|
|
"AGR_DemoPlayerStart": {
|
|
"class": unreal.PlayerStart,
|
|
},
|
|
"AGR_DemoWoodResource_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode",
|
|
"properties": {
|
|
"remaining_harvests": 16,
|
|
"quantity_per_harvest": 2,
|
|
"persistence_node_id": "AGR_DemoWoodResource_01",
|
|
},
|
|
},
|
|
"AGR_DemoFiberResource_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode",
|
|
"properties": {
|
|
"remaining_harvests": 10,
|
|
"quantity_per_harvest": 3,
|
|
"persistence_node_id": "AGR_DemoFiberResource_01",
|
|
},
|
|
},
|
|
"AGR_DemoCampfire_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/Structures/BP_Campfire",
|
|
"properties": {
|
|
"fuel_seconds": 180.0,
|
|
"warmth_radius": 650.0,
|
|
},
|
|
},
|
|
"AGR_DemoPrimitiveShelter_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/Structures/BP_PrimitiveShelter",
|
|
"properties": {
|
|
"weather_protection": 0.7,
|
|
},
|
|
},
|
|
"AGR_DemoRabbitWildlife_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/Wildlife/BP_RabbitWildlife",
|
|
"properties": {
|
|
"wildlife_id": "rabbit",
|
|
"max_health": 12.0,
|
|
},
|
|
},
|
|
"AGR_GZ_FreshWaterSource_01": {
|
|
"class_path": "/Game/Agrarian/Blueprints/World/BP_FreshWaterSource",
|
|
},
|
|
"AGR_GroundZeroMapBoundary": {
|
|
"class": unreal.AgrarianMapBoundaryVolume,
|
|
"properties": {
|
|
"boundary_id": "ground_zero_mvp_tile",
|
|
"clamp_players_at_boundary": True,
|
|
},
|
|
},
|
|
"AGR_DemoSkyLightingController": {
|
|
"class": unreal.AgrarianSkyLightingController,
|
|
},
|
|
"AGR_DemoWeatherAudioController": {
|
|
"class": unreal.AgrarianWeatherAudioController,
|
|
},
|
|
"AGR_DemoNoticeActor": {
|
|
"class": unreal.AgrarianDemoNoticeActor,
|
|
},
|
|
}
|
|
|
|
LEGACY_FLAT_TEST_LABELS = {
|
|
"AGR_WoodResourceNode_01",
|
|
"AGR_FiberResourceNode_01",
|
|
"AGR_Campfire_01",
|
|
"AGR_PrimitiveShelter_01",
|
|
"AGR_RabbitWildlife_01",
|
|
}
|
|
|
|
NEAR_SPAWN_ACTORS = {
|
|
"AGR_DemoWoodResource_01": 12000.0,
|
|
"AGR_DemoFiberResource_01": 12000.0,
|
|
"AGR_DemoCampfire_01": 12000.0,
|
|
"AGR_DemoPrimitiveShelter_01": 12000.0,
|
|
"AGR_DemoRabbitWildlife_01": 12000.0,
|
|
"AGR_GZ_FreshWaterSource_01": 25000.0,
|
|
}
|
|
|
|
|
|
def nearly_equal(left, right):
|
|
return abs(float(left) - float(right)) < 0.001
|
|
|
|
|
|
def distance_2d(left, right):
|
|
return ((left.x - right.x) ** 2.0 + (left.y - right.y) ** 2.0) ** 0.5
|
|
|
|
|
|
def class_path(actor):
|
|
return actor.get_class().get_path_name()
|
|
|
|
|
|
def get_actor_label(actor):
|
|
try:
|
|
return actor.get_actor_label()
|
|
except Exception:
|
|
return actor.get_name()
|
|
|
|
|
|
def verify_class(label, actor, expected, failures):
|
|
expected_class = expected.get("class")
|
|
if expected_class and not isinstance(actor, expected_class):
|
|
failures.append(f"{label} expected class {expected_class.__name__}, got {actor.get_class().get_name()}")
|
|
|
|
expected_class_path = expected.get("class_path")
|
|
if expected_class_path:
|
|
actual_class_path = class_path(actor)
|
|
if not actual_class_path.startswith(expected_class_path + "."):
|
|
failures.append(f"{label} expected class under {expected_class_path}, got {actual_class_path}")
|
|
|
|
|
|
def main():
|
|
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
|
|
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
|
|
|
failures = []
|
|
actors_by_label = {get_actor_label(actor): actor for actor in unreal.EditorLevelLibrary.get_all_level_actors()}
|
|
|
|
for legacy_label in LEGACY_FLAT_TEST_LABELS:
|
|
if legacy_label in actors_by_label:
|
|
failures.append(f"legacy flat-test actor should not remain in Ground Zero map: {legacy_label}")
|
|
|
|
for label, expected in EXPECTED_PLAYABLE_ACTORS.items():
|
|
actor = actors_by_label.get(label)
|
|
if not actor:
|
|
failures.append(f"{label} missing")
|
|
continue
|
|
|
|
verify_class(label, actor, expected, failures)
|
|
|
|
for property_name, expected_value in expected.get("properties", {}).items():
|
|
actual_value = actor.get_editor_property(property_name)
|
|
if isinstance(expected_value, (int, float)):
|
|
if not nearly_equal(actual_value, expected_value):
|
|
failures.append(f"{label} {property_name} expected {expected_value}, got {actual_value}")
|
|
elif isinstance(expected_value, bool):
|
|
if bool(actual_value) != expected_value:
|
|
failures.append(f"{label} {property_name} expected {expected_value}, got {actual_value}")
|
|
elif str(actual_value) != expected_value:
|
|
failures.append(f"{label} {property_name} expected {expected_value}, got {actual_value}")
|
|
|
|
player_start = actors_by_label.get("AGR_DemoPlayerStart")
|
|
if player_start:
|
|
spawn_location = player_start.get_actor_location()
|
|
if spawn_location.z < 150.0:
|
|
failures.append(f"AGR_DemoPlayerStart expected safe above-terrain offset, got z {spawn_location.z}")
|
|
|
|
for label, max_distance in NEAR_SPAWN_ACTORS.items():
|
|
actor = actors_by_label.get(label)
|
|
if not actor:
|
|
continue
|
|
actual_distance = distance_2d(spawn_location, actor.get_actor_location())
|
|
if actual_distance > max_distance:
|
|
failures.append(f"{label} is {actual_distance:.0f}cm from spawn, above {max_distance:.0f}cm playable radius")
|
|
|
|
if failures:
|
|
raise RuntimeError("Test map placement verification failed: " + "; ".join(failures))
|
|
|
|
unreal.log(
|
|
"Agrarian Ground Zero playable test map verification complete: "
|
|
f"{len(EXPECTED_PLAYABLE_ACTORS)} critical actors checked."
|
|
)
|
|
|
|
|
|
main()
|