class_name InventoryReservation extends RefCounted enum State { ACTIVE, CONSUMED, RELEASED, EXPIRED, } var reservation_id: StringName = &"" var stack_id: StringName = &"" var owner_inventory_id: StringName = &"" var item_id: StringName = &"" var quantity := 0 var requester_id: StringName = &"" var purpose: StringName = &"" var created_at := 0 var expires_at := -1 var state: State = State.ACTIVE var terminal_at := -1 func configure( p_reservation_id: StringName, p_stack_id: StringName, p_owner_inventory_id: StringName, p_item_id: StringName, p_quantity: int, p_requester_id: StringName, p_purpose: StringName, p_created_at: int, p_expires_at: int = -1 ) -> InventoryReservation: reservation_id = p_reservation_id stack_id = p_stack_id owner_inventory_id = p_owner_inventory_id item_id = p_item_id quantity = maxi(p_quantity, 0) requester_id = p_requester_id purpose = p_purpose created_at = maxi(p_created_at, 0) expires_at = p_expires_at return self func is_active() -> bool: return state == State.ACTIVE func is_expired(absolute_minute: int) -> bool: return expires_at >= 0 and absolute_minute >= expires_at func mark_consumed(absolute_minute: int) -> bool: if state != State.ACTIVE: return false state = State.CONSUMED terminal_at = absolute_minute return true func mark_released(absolute_minute: int) -> bool: if state != State.ACTIVE: return false state = State.RELEASED terminal_at = absolute_minute return true func mark_expired(absolute_minute: int) -> bool: if state != State.ACTIVE: return false state = State.EXPIRED terminal_at = absolute_minute return true func create_snapshot() -> Dictionary: return { &"reservation_id": String(reservation_id), &"stack_id": String(stack_id), &"owner_inventory_id": String(owner_inventory_id), &"item_id": String(item_id), &"quantity": quantity, &"requester_id": String(requester_id), &"purpose": String(purpose), &"created_at": created_at, &"expires_at": expires_at, &"state": State.keys()[state], &"terminal_at": terminal_at, } static func from_snapshot(snapshot: Dictionary) -> InventoryReservation: if not _is_valid_snapshot(snapshot): return null var state_index := State.keys().find(String(snapshot.get(&"state", "ACTIVE"))) if state_index < 0: return null var reservation := InventoryReservation.new().configure( StringName(snapshot.get(&"reservation_id", "")), StringName(snapshot.get(&"stack_id", "")), StringName(snapshot.get(&"owner_inventory_id", "")), StringName(snapshot.get(&"item_id", "")), int(snapshot.get(&"quantity", 0)), StringName(snapshot.get(&"requester_id", "")), StringName(snapshot.get(&"purpose", "")), int(snapshot.get(&"created_at", 0)), int(snapshot.get(&"expires_at", -1)) ) reservation.state = state_index as State reservation.terminal_at = int(snapshot.get(&"terminal_at", -1)) return reservation static func _is_valid_snapshot(snapshot: Dictionary) -> bool: return ( not String(snapshot.get(&"reservation_id", "")).is_empty() and not String(snapshot.get(&"stack_id", "")).is_empty() and not String(snapshot.get(&"owner_inventory_id", "")).is_empty() and not String(snapshot.get(&"item_id", "")).is_empty() and int(snapshot.get(&"quantity", 0)) > 0 and int(snapshot.get(&"created_at", -1)) >= 0 )