extends RefCounted ## Local mirror for GET [code]/game/players/{id}/cooldown-snapshot[/code] (NEO-32). ## Uses [code]serverTimeUtc[/code] + receive tick to approximate server "now" between polls. const SLOT_COUNT: int = 8 ## Reject bogus [method Time.get_unix_time_from_datetime_string] results (failed parse → 0). const MIN_VALID_UNIX_ANCHOR: float = 1_000_000_000.0 var _slot_end_unix: PackedFloat64Array = PackedFloat64Array() var _server_unix_at_receive: float = 0.0 var _ticks_msec_at_receive: int = 0 func _init() -> void: _slot_end_unix.resize(SLOT_COUNT) for i in range(SLOT_COUNT): _slot_end_unix[i] = 0.0 func apply_snapshot(snapshot: Dictionary) -> void: for i in range(SLOT_COUNT): _slot_end_unix[i] = 0.0 var st: Variant = snapshot.get("serverTimeUtc", null) var anchor: float = 0.0 if st is String: var su: String = (st as String).strip_edges() if not su.is_empty(): anchor = Time.get_unix_time_from_datetime_string(su) elif st is float: anchor = st as float elif st is int: anchor = float(st as int) if anchor < MIN_VALID_UNIX_ANCHOR: anchor = Time.get_unix_time_from_system() _server_unix_at_receive = anchor _ticks_msec_at_receive = Time.get_ticks_msec() var slots: Variant = snapshot.get("slots", []) if slots is Array: for item in slots as Array: if not item is Dictionary: continue var d: Dictionary = item var idx: int = int(d.get("slotIndex", -1)) if idx < 0 or idx >= SLOT_COUNT: continue var end_v: Variant = d.get("cooldownEndsAtUtc", null) if end_v is String and not (end_v as String).is_empty(): var end_s: String = (end_v as String).strip_edges() var end_unix: float = Time.get_unix_time_from_datetime_string(end_s) if end_unix >= MIN_VALID_UNIX_ANCHOR: _slot_end_unix[idx] = end_unix func _effective_server_unix() -> float: return _server_unix_at_receive + (Time.get_ticks_msec() - _ticks_msec_at_receive) * 0.001 func remaining_for_slot(slot_index: int) -> float: if slot_index < 0 or slot_index >= _slot_end_unix.size(): return 0.0 var end_u: float = _slot_end_unix[slot_index] if end_u <= 0.0: return 0.0 return maxf(0.0, end_u - _effective_server_unix()) func is_slot_cooling(slot_index: int) -> bool: return remaining_for_slot(slot_index) > 0.0 func any_slot_cooling() -> bool: for i in range(_slot_end_unix.size()): if remaining_for_slot(i) > 0.0: return true return false func build_hud_line() -> String: var parts: PackedStringArray = PackedStringArray() for i in range(_slot_end_unix.size()): var rem: float = remaining_for_slot(i) if rem > 0.0: parts.append("slot %d: %.1fs" % [i, rem]) if parts.is_empty(): return "Cooldowns: (ready)" return "Cooldowns: " + ", ".join(parts)