4463e524aa
Auto-format all GDScript files using gdformat from gdtoolkit. This is a baseline formatting pass to ensure consistent style: - Normalizes indentation and spacing - Wraps long lines to 100 characters - Removes trailing whitespace - Standardizes blank lines between functions 68 files reformatted, 8 files left unchanged (3rd-party addon files with parse errors excluded).
195 lines
4.7 KiB
GDScript
195 lines
4.7 KiB
GDScript
class_name ResourceStateRecord
|
|
extends RefCounted
|
|
|
|
signal changed(state: ResourceStateRecord)
|
|
signal depleted(state: ResourceStateRecord)
|
|
|
|
const SCHEMA_VERSION := 2
|
|
const LEGACY_SCHEMA_VERSION := 1
|
|
|
|
var data: Dictionary
|
|
|
|
|
|
func _init(record_data: Dictionary = {}) -> void:
|
|
data = record_data.duplicate(true)
|
|
|
|
|
|
static func create_from_node(node: ResourceNode) -> ResourceStateRecord:
|
|
return ResourceStateRecord.new(
|
|
{
|
|
"schema_version": SCHEMA_VERSION,
|
|
"node_id": String(node.node_id),
|
|
"action_id": String(node.action_id),
|
|
"resource_id": String(node.resource_id),
|
|
"amount_remaining": node.initial_amount,
|
|
"yield_per_action": node.yield_per_action,
|
|
"reserved_by": -1,
|
|
"enabled": node.initial_enabled,
|
|
"can_npcs_use": node.can_npcs_use,
|
|
"can_player_use": node.can_player_use
|
|
}
|
|
)
|
|
|
|
|
|
static func from_dictionary(record_data: Dictionary) -> ResourceStateRecord:
|
|
var version := int(record_data.get("schema_version", -1))
|
|
if version == LEGACY_SCHEMA_VERSION:
|
|
record_data = _migrate_v1(record_data)
|
|
elif version != SCHEMA_VERSION:
|
|
return null
|
|
|
|
if not record_data.has_all(
|
|
[
|
|
"node_id",
|
|
"action_id",
|
|
"resource_id",
|
|
"amount_remaining",
|
|
"yield_per_action",
|
|
"reserved_by",
|
|
"enabled",
|
|
"can_npcs_use",
|
|
"can_player_use"
|
|
]
|
|
):
|
|
return null
|
|
if String(record_data["node_id"]).is_empty():
|
|
return null
|
|
var action_id := StringName(record_data["action_id"])
|
|
if not action_id.is_empty() and SimulationDefinitions.get_action(action_id) == null:
|
|
return null
|
|
return ResourceStateRecord.new(record_data)
|
|
|
|
|
|
static func _migrate_v1(legacy_data: Dictionary) -> Dictionary:
|
|
if not legacy_data.has_all(["node_id", "amount_remaining", "reserved_by", "enabled"]):
|
|
return {}
|
|
var migrated := legacy_data.duplicate(true)
|
|
migrated["schema_version"] = SCHEMA_VERSION
|
|
migrated["action_id"] = ""
|
|
migrated["resource_id"] = ""
|
|
migrated["yield_per_action"] = 0.0
|
|
migrated["can_npcs_use"] = false
|
|
migrated["can_player_use"] = false
|
|
return migrated
|
|
|
|
|
|
func apply_definition(node: ResourceNode) -> bool:
|
|
if node == null or node.node_id != get_node_id():
|
|
return false
|
|
|
|
var has_legacy_definition := get_action_id().is_empty()
|
|
if has_legacy_definition:
|
|
data["action_id"] = String(node.action_id)
|
|
data["resource_id"] = String(node.resource_id)
|
|
data["yield_per_action"] = node.yield_per_action
|
|
data["can_npcs_use"] = node.can_npcs_use
|
|
data["can_player_use"] = node.can_player_use
|
|
data["schema_version"] = SCHEMA_VERSION
|
|
return true
|
|
|
|
return (
|
|
get_action_id() == node.action_id
|
|
and get_resource_id() == node.resource_id
|
|
and is_equal_approx(get_yield_per_action(), node.yield_per_action)
|
|
and can_npc_use() == node.can_npcs_use
|
|
and can_player_use_resource() == node.can_player_use
|
|
)
|
|
|
|
|
|
func get_node_id() -> StringName:
|
|
return StringName(data["node_id"])
|
|
|
|
|
|
func get_action_id() -> StringName:
|
|
return StringName(data["action_id"])
|
|
|
|
|
|
func get_resource_id() -> StringName:
|
|
return StringName(data["resource_id"])
|
|
|
|
|
|
func get_amount_remaining() -> float:
|
|
return float(data["amount_remaining"])
|
|
|
|
|
|
func get_yield_per_action() -> float:
|
|
return float(data["yield_per_action"])
|
|
|
|
|
|
func get_reserved_by() -> int:
|
|
return int(data["reserved_by"])
|
|
|
|
|
|
func is_enabled() -> bool:
|
|
return bool(data["enabled"])
|
|
|
|
|
|
func can_npc_use() -> bool:
|
|
return bool(data["can_npcs_use"])
|
|
|
|
|
|
func can_player_use_resource() -> bool:
|
|
return bool(data["can_player_use"])
|
|
|
|
|
|
func is_depleted() -> bool:
|
|
return get_amount_remaining() <= 0.0
|
|
|
|
|
|
func can_extract() -> bool:
|
|
return is_enabled() and not is_depleted()
|
|
|
|
|
|
func is_available_for(agent_id: int) -> bool:
|
|
return can_extract() and (get_reserved_by() == -1 or get_reserved_by() == agent_id)
|
|
|
|
|
|
func reserve(agent_id: int) -> bool:
|
|
if not is_available_for(agent_id):
|
|
return false
|
|
data["reserved_by"] = agent_id
|
|
changed.emit(self)
|
|
return true
|
|
|
|
|
|
func release(agent_id: int) -> void:
|
|
if get_reserved_by() != agent_id:
|
|
return
|
|
data["reserved_by"] = -1
|
|
changed.emit(self)
|
|
|
|
|
|
func extract(requested_amount: float = -1.0) -> float:
|
|
if not can_extract():
|
|
return 0.0
|
|
var amount := requested_amount
|
|
if amount < 0.0:
|
|
amount = get_yield_per_action()
|
|
var extracted := minf(maxf(amount, 0.0), get_amount_remaining())
|
|
data["amount_remaining"] = get_amount_remaining() - extracted
|
|
if is_depleted():
|
|
data["reserved_by"] = -1
|
|
changed.emit(self)
|
|
if is_depleted():
|
|
depleted.emit(self)
|
|
return extracted
|
|
|
|
|
|
func set_amount_remaining(amount: float) -> void:
|
|
var was_depleted := is_depleted()
|
|
data["amount_remaining"] = maxf(amount, 0.0)
|
|
if is_depleted():
|
|
data["reserved_by"] = -1
|
|
changed.emit(self)
|
|
if not was_depleted and is_depleted():
|
|
depleted.emit(self)
|
|
|
|
|
|
func set_enabled(value: bool) -> void:
|
|
data["enabled"] = value
|
|
changed.emit(self)
|
|
|
|
|
|
func to_dictionary() -> Dictionary:
|
|
return data.duplicate(true)
|