class_name ABGGuildPageController extends RefCounted ## UI-independent Guild view-data assembly. ## ## The controller receives a Company snapshot and describes the Guild desk's ## state and destination boundaries. It never loads, saves or mutates ## persistence and never reaches into Godot nodes or Entry Shell globals. const ACTIVE_CONTRACT_STATUSES: Array[String] = ["market", "battle", "result", "recovery"] func snapshot(company: Dictionary, locale := "zh_CN") -> Dictionary: if company.is_empty(): return {"ok": false, "code": "COMPANY_REQUIRED"} var raw_recruits = company.get("owned_recruits", []) if not raw_recruits is Array: return {"ok": false, "code": "COMPANY_INVALID"} var raw_contract = company.get("active_contract", {}) if not raw_contract is Dictionary: return {"ok": false, "code": "CONTRACT_INVALID"} var recruits := _copy_recruits(raw_recruits) var contract: Dictionary = Dictionary(raw_contract).duplicate(true) var status := String(contract.get("status", "")) var has_contract := not contract.is_empty() var is_active := status in ACTIVE_CONTRACT_STATUSES var is_returned := status == "returned" var state := "active" if is_active else "returned" if is_returned else "empty" if not has_contract else "blocked" var line_capacity := int(contract.get("line_capacity", 4)) var coin := int(contract.get("coin", 0)) var difficulty := String(contract.get("difficulty", "standard")) var company_data := { "company_id": String(company.get("company_id", "")), "owned_count": recruits.size(), "line_capacity": line_capacity, "recruits": recruits, "display_recruits": _copy_recruits(recruits.slice(0, mini(2, recruits.size()))), } var contract_data := { "present": has_contract, "active": is_active, "returned": is_returned, "state": state, "status": status, "contract_id": String(contract.get("contract_id", "")), "run_id": String(contract.get("run_id", "")), "route_id": String(contract.get("route_id", "windglass_verge")), "difficulty": difficulty, "coin": coin, "line_capacity": line_capacity, } return { "ok": true, "page_id": "guild", "company": company_data, "contract": contract_data, "destinations": _destinations(state), "locale": String(locale), } func destination_state(snapshot_data: Dictionary, destination_id: String) -> Dictionary: var destinations = snapshot_data.get("destinations", {}) if destinations is Dictionary and destinations.has(destination_id): return Dictionary(destinations.get(destination_id, {})).duplicate(true) return {"enabled": false, "visible": false, "reason": "unknown_destination"} func _destinations(state: String) -> Dictionary: var has_active := state == "active" var has_returned := state == "returned" return { "contract": { "enabled": state == "empty", "visible": state == "empty", "reason": "ready" if state == "empty" else "contract_active" if has_active else "contract_returned" if has_returned else "contract_invalid", }, "market": { "enabled": has_active, "visible": has_active, "reason": "ready" if has_active else "contract_returned" if has_returned else "contract_required", }, "equipment": { "enabled": has_active, "visible": true, "reason": "ready" if has_active else "contract_required" if not has_returned else "returned_contract", }, "party": { "enabled": has_active, "visible": true, "reason": "ready" if has_active else "contract_required" if not has_returned else "returned_contract", }, "risk": { "enabled": has_active, "visible": true, "reason": "ready" if has_active else "contract_required" if not has_returned else "returned_contract", }, } func _copy_recruits(values) -> Array[Dictionary]: var result: Array[Dictionary] = [] if not values is Array: return result for value in values: if value is Dictionary: result.append(Dictionary(value).duplicate(true)) return result