Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
This commit is contained in:
@@ -23,6 +23,8 @@ var _transaction_ids: Dictionary = {}
|
||||
var _idempotency_keys: Dictionary = {}
|
||||
var _next_transaction_sequence := 1
|
||||
var _pending_transaction_notifications: Dictionary = {}
|
||||
# Transient nested observer boundary; never serialized as gameplay state.
|
||||
var _notification_scopes: Array[Array] = []
|
||||
|
||||
|
||||
func _init(account_definitions: Dictionary = {}) -> void:
|
||||
@@ -308,7 +310,10 @@ func post(
|
||||
_next_transaction_sequence = generated_sequence + 1
|
||||
var posted_entries := get_transaction_entries(effective_id)
|
||||
if emit_notification:
|
||||
transaction_posted.emit(effective_id, posted_entries)
|
||||
if _notification_scopes.is_empty():
|
||||
transaction_posted.emit(effective_id, posted_entries)
|
||||
else:
|
||||
_notification_scopes.back().append(effective_id)
|
||||
else:
|
||||
_pending_transaction_notifications[effective_id] = true
|
||||
return CommandResultType.succeeded(0, {
|
||||
@@ -318,6 +323,36 @@ func post(
|
||||
})
|
||||
|
||||
|
||||
## Retain ordinary post semantics while postponing observer delivery through a
|
||||
## complete event effect/cost boundary. Explicit emit_notification=false remains
|
||||
## owned by its existing caller, including Operations and supply transactions.
|
||||
func notification_scope_depth() -> int:
|
||||
return _notification_scopes.size()
|
||||
|
||||
|
||||
func begin_notification_scope() -> void:
|
||||
_notification_scopes.append([])
|
||||
|
||||
|
||||
func end_notification_scope() -> void:
|
||||
assert(not _notification_scopes.is_empty(), "Balanced notification scope required.")
|
||||
if _notification_scopes.is_empty():
|
||||
return
|
||||
var queued: Array = _notification_scopes.pop_back()
|
||||
if not _notification_scopes.is_empty():
|
||||
_notification_scopes.back().append_array(queued)
|
||||
return
|
||||
var seen: Dictionary = {}
|
||||
for raw_id: Variant in queued:
|
||||
var transaction_id := StringName(raw_id)
|
||||
# Restoring a ledger removes rolled-back IDs. A failure branch can reuse
|
||||
# an ID; deliver the surviving final receipt once in insertion order.
|
||||
if seen.has(transaction_id) or not _transaction_ids.has(transaction_id):
|
||||
continue
|
||||
seen[transaction_id] = true
|
||||
transaction_posted.emit(transaction_id, get_transaction_entries(transaction_id))
|
||||
|
||||
|
||||
func has_pending_transaction_notification(transaction_id: StringName) -> bool:
|
||||
return _pending_transaction_notifications.has(transaction_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user