146 lines
4.2 KiB
GDScript
146 lines
4.2 KiB
GDScript
extends SceneTree
|
|
|
|
const DEFAULT_EXTRACTED_DIR := "res://data/extracted"
|
|
const DEFAULT_MAP := "Azeroth"
|
|
const DEFAULT_TARGET_UID := 11785
|
|
|
|
var _failures := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
var args := OS.get_cmdline_user_args()
|
|
var extracted_dir := _arg(args, "--extracted", DEFAULT_EXTRACTED_DIR)
|
|
var map_name := _arg(args, "--map", DEFAULT_MAP)
|
|
var target_uid := int(_arg(args, "--uid", str(DEFAULT_TARGET_UID)))
|
|
var path_contains := _arg(args, "--path-contains", "waterfall").to_lower()
|
|
print("ADT M2 placement verification started. map=%s uid=%d path_contains=%s" % [
|
|
map_name,
|
|
target_uid,
|
|
path_contains,
|
|
])
|
|
|
|
var matches := _find_m2_placements(extracted_dir, map_name, target_uid, path_contains)
|
|
if matches.is_empty():
|
|
_fail("No matching ADT M2 placement found. map=%s uid=%d path_contains=%s" % [
|
|
map_name,
|
|
target_uid,
|
|
path_contains,
|
|
])
|
|
else:
|
|
print("ADT M2 placement verification matched %d placement(s)." % matches.size())
|
|
for match in matches:
|
|
print(_format_match(match))
|
|
|
|
if _failures > 0:
|
|
quit(1)
|
|
return
|
|
quit(0)
|
|
|
|
|
|
func _find_m2_placements(
|
|
extracted_dir: String,
|
|
map_name: String,
|
|
target_uid: int,
|
|
path_contains: String) -> Array:
|
|
if not ClassDB.class_exists("ADTLoader"):
|
|
_fail("ADTLoader is not registered. Rebuild the native GDExtension first.")
|
|
return []
|
|
|
|
var map_dir := ProjectSettings.globalize_path(
|
|
extracted_dir.path_join("World/Maps").path_join(map_name)
|
|
)
|
|
var dir := DirAccess.open(map_dir)
|
|
if dir == null:
|
|
_fail("Cannot open map directory: %s" % map_dir)
|
|
return []
|
|
|
|
var files := _collect_adt_files(dir, map_name)
|
|
if files.is_empty():
|
|
_fail("No ADT files found in %s" % map_dir)
|
|
return []
|
|
|
|
var loader = ClassDB.instantiate("ADTLoader")
|
|
if loader == null:
|
|
_fail("Cannot instantiate ADTLoader.")
|
|
return []
|
|
|
|
var matches := []
|
|
for file_name in files:
|
|
var tile := _tile_from_adt_filename(file_name)
|
|
var data: Dictionary = loader.call("load_adt", map_dir.path_join(file_name))
|
|
var names: PackedStringArray = data.get("m2_names", PackedStringArray())
|
|
var placements: Array = data.get("m2_placements", [])
|
|
for placement_variant in placements:
|
|
if not (placement_variant is Dictionary):
|
|
continue
|
|
var placement: Dictionary = placement_variant
|
|
var uid := int(placement.get("unique_id", -1))
|
|
if target_uid >= 0 and uid != target_uid:
|
|
continue
|
|
var name_id := int(placement.get("name_id", -1))
|
|
if name_id < 0 or name_id >= names.size():
|
|
continue
|
|
var rel_path := String(names[name_id]).replace("\\", "/")
|
|
if not path_contains.is_empty() and not rel_path.to_lower().contains(path_contains):
|
|
continue
|
|
matches.append({
|
|
"tile": tile,
|
|
"uid": uid,
|
|
"path": rel_path,
|
|
"pos": placement.get("pos", Vector3.ZERO),
|
|
"rot": placement.get("rot", Vector3.ZERO),
|
|
"scale": float(placement.get("scale", 1.0)),
|
|
})
|
|
return matches
|
|
|
|
|
|
func _collect_adt_files(dir: DirAccess, map_name: String) -> Array:
|
|
var result := []
|
|
dir.list_dir_begin()
|
|
while true:
|
|
var file_name := dir.get_next()
|
|
if file_name.is_empty():
|
|
break
|
|
if dir.current_is_dir():
|
|
continue
|
|
if not file_name.to_lower().ends_with(".adt"):
|
|
continue
|
|
if not file_name.begins_with("%s_" % map_name):
|
|
continue
|
|
result.append(file_name)
|
|
dir.list_dir_end()
|
|
result.sort()
|
|
return result
|
|
|
|
|
|
func _tile_from_adt_filename(file_name: String) -> Vector2i:
|
|
var parts := file_name.get_basename().split("_")
|
|
if parts.size() < 3:
|
|
return Vector2i(-1, -1)
|
|
return Vector2i(int(parts[parts.size() - 2]), int(parts[parts.size() - 1]))
|
|
|
|
|
|
func _format_match(match: Dictionary) -> String:
|
|
var rot: Vector3 = match.get("rot", Vector3.ZERO)
|
|
var rot_deg := Vector3(rad_to_deg(rot.x), rad_to_deg(rot.y), rad_to_deg(rot.z))
|
|
return "ADT_M2_PLACEMENT tile=%s uid=%d path=%s pos=%s rot_deg=%s scale=%.3f" % [
|
|
match.get("tile", Vector2i(-1, -1)),
|
|
int(match.get("uid", -1)),
|
|
String(match.get("path", "")),
|
|
match.get("pos", Vector3.ZERO),
|
|
rot_deg,
|
|
float(match.get("scale", 1.0)),
|
|
]
|
|
|
|
|
|
func _arg(args: PackedStringArray, name: String, default_value: String) -> String:
|
|
var idx := args.find(name)
|
|
if idx >= 0 and idx + 1 < args.size():
|
|
return args[idx + 1]
|
|
return default_value
|
|
|
|
|
|
func _fail(message: String) -> void:
|
|
_failures += 1
|
|
push_error(message)
|