import unreal MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test" LANDMARK_PREFIX = "AGR_GZ_Landmark_Ruin_" EXPECTED_LABELS = { "AGR_GZ_Landmark_Ruin_Foundation_01", "AGR_GZ_Landmark_Ruin_Wall_01", "AGR_GZ_Landmark_Ruin_Wall_02", "AGR_GZ_Landmark_Ruin_Cairn_01", "AGR_GZ_Landmark_Ruin_Threshold_01", } PLACEHOLDER_MESH_PATH_PREFIX = "/Game/Agrarian/Environment/PlaceholderMeshes/" STONE_MATERIAL_PATH = "/Game/Agrarian/Materials/M_AGR_GZ_Stone_Sandstone" def get_actor_label(actor): try: return actor.get_actor_label() except Exception: return actor.get_name() def normalized_asset_path(asset): if not asset: return "" return asset.get_path_name().split(".", 1)[0] def main(): if not unreal.EditorLevelLibrary.load_level(MAP_PATH): raise RuntimeError(f"Could not load map: {MAP_PATH}") failures = [] actors = unreal.EditorLevelLibrary.get_all_level_actors() landmark_actors = { get_actor_label(actor): actor for actor in actors if get_actor_label(actor).startswith(LANDMARK_PREFIX) } missing = EXPECTED_LABELS.difference(landmark_actors) unexpected = set(landmark_actors).difference(EXPECTED_LABELS) if missing: failures.append(f"missing landmark placeholder actors: {sorted(missing)}") if unexpected: failures.append(f"unexpected landmark placeholder actors: {sorted(unexpected)}") mesh_paths = set() location_keys = set() for label, actor in landmark_actors.items(): if not isinstance(actor, unreal.StaticMeshActor): failures.append(f"{label} is not a StaticMeshActor") continue mesh_component = actor.static_mesh_component mesh_path = normalized_asset_path(mesh_component.static_mesh) mesh_paths.add(mesh_path) if not mesh_path.startswith(PLACEHOLDER_MESH_PATH_PREFIX): failures.append(f"{label} uses non-native mesh path {mesh_path}") material_path = normalized_asset_path(mesh_component.get_material(0)) if material_path != STONE_MATERIAL_PATH: failures.append(f"{label} expected stone material, got {material_path}") scale = actor.get_actor_scale3d() if min(scale.x, scale.y, scale.z) <= 0.0: failures.append(f"{label} has invalid scale {scale}") location = actor.get_actor_location() if location.z <= 0.0: failures.append(f"{label} appears below terrain/sea-level check threshold at {location}") location_keys.add((round(location.x, 0), round(location.y, 0))) if len(mesh_paths) < 3: failures.append(f"expected at least 3 landmark mesh silhouettes, got {len(mesh_paths)}") if len(location_keys) != len(EXPECTED_LABELS): failures.append("landmark placeholder actors should occupy distinct positions") roadmap = unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir()) + "AGRARIAN_DEVELOPMENT_ROADMAP.md" natural_environment_doc = ( unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir()) + "Docs/Terrain/GroundZeroNaturalEnvironmentPass.md" ) for path, snippet in [ (roadmap, "[x] Add landmark or ruin placeholder"), (natural_environment_doc, "ruin landmark placeholder"), ]: with open(path, "r", encoding="utf-8") as handle: text = handle.read() if snippet not in text: failures.append(f"{path} missing `{snippet}`") if failures: raise RuntimeError("Ground Zero landmark placeholder verification failed: " + "; ".join(failures)) unreal.log( "Ground Zero landmark placeholder verification complete: " f"{len(landmark_actors)} ruin actors, {len(mesh_paths)} mesh silhouettes." ) main()