97 lines
6.3 KiB
GDScript
97 lines
6.3 KiB
GDScript
extends "/Users/korizatou114/Projects/とりにく工房ゲーム制作部/artifacts/original-completion-2026-10-02/p23-02-native-ready-route-local-r304-r02.gd"
|
|
# Only new conversion fallbacks and a timed script replacement; prior15+8 not rerun.
|
|
const FALLBACK_CASES := ["compact_int", "index_float", "cell_vector3"]
|
|
class ReplacementPath:
|
|
extends PathService
|
|
var dispatch_trace: Array[StringName] = []
|
|
func _guest_tree_reconstruct_path(tree: Dictionary, goal: Vector3i) -> Array[Vector3i]:
|
|
dispatch_trace.append(&"reconstruct")
|
|
return super._guest_tree_reconstruct_path(tree, goal)
|
|
func _copy_path(path: Array) -> Array[Vector3i]:
|
|
dispatch_trace.append(&"copy")
|
|
return super._copy_path(path)
|
|
var tick_calls := 0
|
|
var hook_records: Array = []
|
|
func route_setup(label: String) -> Dictionary:
|
|
var input: Dictionary=super.route_setup(label)
|
|
if input.is_empty(): return input
|
|
var tree: Dictionary=input["tree"]
|
|
if label=="compact_int": tree[&"compact"]=1
|
|
elif label=="index_float": tree[&"indices"][input["goal"]]=2.75
|
|
elif label=="cell_vector3":
|
|
var converted: Array=[]
|
|
for cell: Vector3i in tree[&"cells"]: converted.append(Vector3(cell))
|
|
tree[&"cells"]=converted
|
|
return input
|
|
func replace_path_script(p: PathService) -> void:
|
|
var before: PackedByteArray=var_to_bytes(state())
|
|
var properties: Dictionary={}
|
|
for row: Dictionary in p.get_property_list():
|
|
if int(row["usage"]) & PROPERTY_USAGE_SCRIPT_VARIABLE:
|
|
properties[StringName(row["name"])]=p.get(row["name"])
|
|
var prototype: PathService=ReplacementPath.new()
|
|
var replacement: Script=prototype.get_script()
|
|
prototype=null
|
|
p.set_script(replacement)
|
|
for key: StringName in properties: p.set(key,properties[key])
|
|
check(var_to_bytes(state())==before,"replacement preserves complete pre-dispatch Runtime and Path state")
|
|
func switching_ticks() -> int:
|
|
tick_calls+=1
|
|
if tick_calls==1: replace_path_script(runtime.path_service)
|
|
return Time.get_ticks_usec()
|
|
func replacement_case() -> void:
|
|
var input: Dictionary=route_setup("ordinary")
|
|
if input.is_empty(): return
|
|
var p: PathService=input["path"]
|
|
var tree_before: PackedByteArray=var_to_bytes(input["tree"])
|
|
tick_calls=0
|
|
var actual: Dictionary=core.nearest_guest_access(p,Vector3i.ZERO,input["goals"],input["goal"],input["layers"],input["access"],Callable(self,"switching_ticks"))
|
|
check(bool(actual.get(&"supported",false)),"mid-call replacement still resolves supported route")
|
|
check(tick_calls==2,"actual supplied ticks executed twice and switch occurs at first original tick position")
|
|
var actual_trace: Array=p.get(&"dispatch_trace").duplicate()
|
|
check(actual_trace==[&"reconstruct",&"copy"],"custom reconstruct and custom copy each dispatched at original positions")
|
|
check(var_to_bytes(input["tree"])==tree_before,"mid-call replacement leaves ready tree unchanged")
|
|
var actual_bytes: PackedByteArray=var_to_bytes(actual)
|
|
var after: PackedByteArray=var_to_bytes(state())
|
|
input=route_setup("ordinary")
|
|
if input.is_empty(): return
|
|
p=input["path"]
|
|
replace_path_script(p)
|
|
# Original resolver is the oracle for changed helpers after replacement.
|
|
# No claim that the original nearest entry accepts an initially custom script.
|
|
var expected_path: Array[Vector3i]=p._resolve_ready_guest_batch_point(Vector3i.ZERO,input["goal"],input["tree"])
|
|
p.path_query_measured.emit(0)
|
|
var expected: Dictionary={&"supported":true,&"reachable":true,&"path":expected_path,&"target_cell":input["goal"]}
|
|
check(var_to_bytes(expected)==actual_bytes,"mid-call route result equals original resolver ordered typed bytes")
|
|
check(var_to_bytes(state())==after,"mid-call original resolver Runtime cache counters errors and observer count equal")
|
|
check(p.get(&"dispatch_trace")==actual_trace,"mid-call custom dispatch order equals original resolver")
|
|
var returned: Array=actual[&"path"]
|
|
var key: String=p._cache_key(Vector3i.ZERO,input["goal"],input["layers"],input["access"])
|
|
var cached: Array=p._path_cache[key]
|
|
check(expected_path.is_typed() and expected_path.get_typed_builtin()==TYPE_VECTOR3I and not expected_path.is_read_only() and cached.is_typed() and cached.get_typed_builtin()==TYPE_VECTOR3I and not cached.is_read_only() and not is_same(expected_path,cached),"custom original resolver keeps writable typed independent cache ownership")
|
|
var cache_before: PackedByteArray=var_to_bytes(p._path_cache)
|
|
expected_path[0]=Vector3i(88,88,0)
|
|
check(var_to_bytes(p._path_cache)==cache_before,"custom returned route mutation leaves original cache unchanged")
|
|
var expected_before: PackedByteArray=var_to_bytes(expected_path)
|
|
cached[0]=Vector3i(66,66,0)
|
|
check(var_to_bytes(expected_path)==expected_before,"custom original cache mutation leaves returned route unchanged")
|
|
hook_records.append({"case":"midcall_script","actual":bytes_to_var(actual_bytes),"expected":expected,"dispatch_trace":actual_trace,"oracle_scope":"original ready resolver after identical replacement, not original nearest entry"})
|
|
func run() -> void:
|
|
output=OS.get_environment("THE_TREE_RUNTIME_MONITOR_OUTPUT")
|
|
runtime=root.get_node("SimulationRuntime");clock=root.get_node("GameClock")
|
|
var raw := FileAccess.get_file_as_bytes(OS.get_environment("THE_TREE_REPLAY_SNAPSHOT")).decompress(11411840,FileAccess.COMPRESSION_ZSTD)
|
|
var initial: Dictionary=bytes_to_var(raw)
|
|
runtime.initialize(clock,root.get_node("GameState"),int(initial[&"systems"][&"runtime"][&"world_seed"]))
|
|
check(runtime.restore_snapshot(initial),"fixed646 seed/context restore")
|
|
core=ClassDB.instantiate(&"TheTreeNumericCore")
|
|
for label: String in FALLBACK_CASES: route_case(label)
|
|
replacement_case()
|
|
var routes: Dictionary=typed("ready-route-fixtures",route_records)
|
|
var hooks: Dictionary=typed("fixtures",hook_records)
|
|
core=null
|
|
var report := {"passed":failures.is_empty(),"checks":checks,"failures":failures,"pid":OS.get_process_id(),"case_count":0,"ready_route_cases":FALLBACK_CASES.size(),"replacement_cases":1,"ready_route_fixtures":routes,"fixtures":hooks,"unit_accepted":false,"performance_accepted":false,"Windows_accepted":false,"scope":"3 conversion fallback cases vs original nearest and1 actual mid-call replacement vs original ready resolver; malformed shape/index and general reentry not covered"}
|
|
var file := FileAccess.open(output.path_join("report.json"),FileAccess.WRITE)
|
|
if file==null:quit(98);return
|
|
file.store_string(JSON.stringify(report,"\t"));file.close()
|
|
print("Ready route fallback: %d checks, %d failures"%[checks,failures.size()]);quit(0 if failures.is_empty() else 1)
|