Files
gamedev-the-steward/world/presentation/PresentationNavRequestBudget.gd
T
2026-08-12 21:22:10 +02:00

78 lines
2.2 KiB
GDScript

class_name PresentationNavRequestBudget
extends RefCounted
const MAX_NEW_REQUESTS_PER_FRAME := 2
var _pending_by_id: Dictionary = {}
var _in_flight_ids: Dictionary = {}
var _last_drained_frame := -1
func enqueue(stable_id: StringName, priority: int = 0, reason_trace: Array[String] = []) -> bool:
if stable_id.is_empty() or _pending_by_id.has(stable_id) or _in_flight_ids.has(stable_id):
return false
var normalized_trace := reason_trace.duplicate()
normalized_trace.sort()
_pending_by_id[stable_id] = {
"stable_id": stable_id,
"priority": priority,
"reason_trace": normalized_trace,
}
return true
func take_new_requests(frame_index: int) -> Array[Dictionary]:
var result: Array[Dictionary] = []
if frame_index < 0 or frame_index <= _last_drained_frame:
return result
_last_drained_frame = frame_index
var pending: Array[Dictionary] = []
for request in _pending_by_id.values():
pending.append((request as Dictionary).duplicate(true))
pending.sort_custom(_request_before)
for index in mini(MAX_NEW_REQUESTS_PER_FRAME, pending.size()):
var request: Dictionary = pending[index]
var stable_id: StringName = request["stable_id"]
_pending_by_id.erase(stable_id)
_in_flight_ids[stable_id] = true
request["reason_trace"].append("granted_frame_%d" % frame_index)
result.append(request)
return result
func complete(stable_id: StringName) -> bool:
return _in_flight_ids.erase(stable_id)
func cancel(stable_id: StringName) -> bool:
var changed := _pending_by_id.erase(stable_id)
return _in_flight_ids.erase(stable_id) or changed
func get_pending_ids() -> Array[StringName]:
var result: Array[StringName] = []
for stable_id in _pending_by_id:
result.append(StringName(stable_id))
result.sort()
return result
func get_in_flight_ids() -> Array[StringName]:
var result: Array[StringName] = []
for stable_id in _in_flight_ids:
result.append(StringName(stable_id))
result.sort()
return result
func clear() -> void:
_pending_by_id.clear()
_in_flight_ids.clear()
_last_drained_frame = -1
func _request_before(first: Dictionary, second: Dictionary) -> bool:
if int(first["priority"]) != int(second["priority"]):
return int(first["priority"]) > int(second["priority"])
return String(first["stable_id"]) < String(second["stable_id"])