class_name PlayerStateRecord extends RefCounted const SCHEMA_VERSION := 1 var data: Dictionary func _init(record_data: Dictionary = {}) -> void: data = record_data.duplicate(true) static func create_default() -> PlayerStateRecord: return ( PlayerStateRecord . new( { "schema_version": SCHEMA_VERSION, "hunger": 40.0, "energy": 100.0, "inventory": {}, } ) ) static func from_dictionary(record_data: Dictionary) -> PlayerStateRecord: if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION: return null if not record_data.has_all(["hunger", "energy", "inventory"]): return null if not record_data["inventory"] is Dictionary: return null var hunger := float(record_data["hunger"]) var energy := float(record_data["energy"]) if not is_finite(hunger) or not is_finite(energy): return null var normalized_inventory := {} for raw_item_id in record_data["inventory"]: var item_id := String(raw_item_id) var amount := float(record_data["inventory"][raw_item_id]) if ( item_id.is_empty() or normalized_inventory.has(item_id) or not is_finite(amount) or amount < 0.0 ): return null normalized_inventory[item_id] = amount return ( PlayerStateRecord . new( { "schema_version": SCHEMA_VERSION, "hunger": clampf(hunger, 0.0, 100.0), "energy": clampf(energy, 0.0, 100.0), "inventory": normalized_inventory, } ) ) func get_hunger() -> float: return clampf(float(data["hunger"]), 0.0, 100.0) func get_energy() -> float: return clampf(float(data["energy"]), 0.0, 100.0) func set_hunger(amount: float) -> void: data["hunger"] = clampf(amount, 0.0, 100.0) func set_energy(amount: float) -> void: data["energy"] = clampf(amount, 0.0, 100.0) func get_inventory_amount(item_id: StringName) -> float: return float(data["inventory"].get(String(item_id), 0.0)) func get_carried_total() -> float: var total := 0.0 for amount in data["inventory"].values(): total += float(amount) return total func add_inventory(item_id: StringName, amount: float) -> void: if item_id.is_empty() or not is_finite(amount) or amount <= 0.0: return data["inventory"][String(item_id)] = get_inventory_amount(item_id) + amount func remove_inventory(item_id: StringName, requested_amount: float) -> float: if item_id.is_empty() or not is_finite(requested_amount) or requested_amount <= 0.0: return 0.0 var removed := minf(requested_amount, get_inventory_amount(item_id)) if removed <= 0.0: return 0.0 data["inventory"][String(item_id)] = get_inventory_amount(item_id) - removed return removed func to_dictionary() -> Dictionary: return data.duplicate(true)