// Isolated, uncompiled bridge prototype. No production registration or integration yet. #include "tree_core.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace godot; using the_tree_native::I; using the_tree_native::Edge; class TheTreeNumericCore : public RefCounted { GDCLASS(TheTreeNumericCore, RefCounted) protected: static void _bind_methods() { ClassDB::bind_method(D_METHOD("performance_record_sample", "owner", "metric_id", "duration_us"), &TheTreeNumericCore::performance_record_sample); ClassDB::bind_method(D_METHOD("guest_candidate_batch", "owner", "guest_id", "facilities", "context"), &TheTreeNumericCore::guest_candidate_batch); ClassDB::bind_method(D_METHOD("guest_tree_edge_rows", "path", "current", "layers", "access"), &TheTreeNumericCore::guest_tree_edge_rows); ClassDB::bind_method(D_METHOD("search", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search); ClassDB::bind_method(D_METHOD("search_cached", "cells", "indices", "start_index", "goals", "edge_provider"), &TheTreeNumericCore::search_cached); ClassDB::bind_method(D_METHOD("clear_edge_cache"), &TheTreeNumericCore::clear_edge_cache); ClassDB::bind_method(D_METHOD("nearest_guest_access", "path", "start", "goals", "fallback_target", "layers", "access", "ticks"), &TheTreeNumericCore::nearest_guest_access); ClassDB::bind_method(D_METHOD("project_guest_candidates", "runtime", "guest_id", "open_state", "degraded_state", "movement_scale", "stair_credit", "orthogonal_cost", "ticks"), &TheTreeNumericCore::project_guest_candidates); } private: // Cache belongs to this instance and one caller-owned graph workspace. // No reuse after cells, indices, filters or edge values change: the caller // must clear it or release this core. The original search never uses it. std::map> cached_edges; // Per-public-call immutable names. No static/global lifetime, cached // object values, script dispatch result or profile; recursive calls own // separate scopes. Destruction precedes leaving the engine call. struct ProjectionNames { const StringName k_ACCESS_LAYER_DENIED{"ACCESS_LAYER_DENIED",false}; const StringName k_CONNECTOR{"CONNECTOR",false}; const StringName k_GOAL_NOT_PASSABLE{"GOAL_NOT_PASSABLE",false}; const StringName k_GOAL_TEMPORARILY_BLOCKED{"GOAL_TEMPORARILY_BLOCKED",false}; const StringName k_GOAL_UNREACHABLE{"GOAL_UNREACHABLE",false}; const StringName k_OK{"OK",false}; const StringName k_START_NOT_PASSABLE{"START_NOT_PASSABLE",false}; const StringName k_START_TEMPORARILY_BLOCKED{"START_TEMPORARILY_BLOCKED",false}; const StringName k__build_guest_query_tree_compact{"_build_guest_query_tree_compact",false}; const StringName k__cache_key{"_cache_key",false}; const StringName k__cell_traffic{"_cell_traffic",false}; const StringName k__copy_path{"_copy_path",false}; const StringName k__diagnose_no_route_reason{"_diagnose_no_route_reason",false}; const StringName k__find_facility_access_path{"_find_facility_access_path",false}; const StringName k__find_path_internal{"_find_path_internal",false}; const StringName k__guest_access_batch_can_select{"_guest_access_batch_can_select",false}; const StringName k__guest_batch_has_permitted_layer_crossing{"_guest_batch_has_permitted_layer_crossing",false}; const StringName k__guest_has_checked_in{"_guest_has_checked_in",false}; const StringName k__guest_step_connector_memo{"_guest_step_connector_memo",false}; const StringName k__guest_tree_arithmetic_wrapped{"_guest_tree_arithmetic_wrapped",false}; const StringName k__guest_tree_reconstruct_path{"_guest_tree_reconstruct_path",false}; const StringName k__need_relief_for_facility_tags{"_need_relief_for_facility_tags",false}; const StringName k__passable_cells{"_passable_cells",false}; const StringName k__path_cache{"_path_cache",false}; const StringName k__query_batch{"_query_batch",false}; const StringName k__route_failure{"_route_failure",false}; const StringName k__service_category_for_tags{"_service_category_for_tags",false}; const StringName k__sorted_name_keys{"_sorted_name_keys",false}; const StringName k_arithmetic_wrapped{"arithmetic_wrapped",false}; const StringName k_available_quantity{"available_quantity",false}; const StringName k_base_quality{"base_quality",false}; const StringName k_base_service_minutes{"base_service_minutes",false}; const StringName k_begin_guest_path_query_batch{"begin_guest_path_query_batch",false}; const StringName k_cache_misses{"cache_misses",false}; const StringName k_calculate_guest_batch_path_cost{"calculate_guest_batch_path_cost",false}; const StringName k_candidates{"candidates",false}; const StringName k_capacity{"capacity",false}; const StringName k_compact{"compact",false}; const StringName k_cost{"cost",false}; const StringName k_cost_values{"cost_values",false}; const StringName k_costs{"costs",false}; const StringName k_current_cell{"current_cell",false}; const StringName k_definition_id{"definition_id",false}; const StringName k_definition_registry{"definition_registry",false}; const StringName k_elevators{"elevators",false}; const StringName k_end_guest_path_query_batch{"end_guest_path_query_batch",false}; const StringName k_entrance{"entrance",false}; const StringName k_estimated_total_gold{"estimated_total_gold",false}; const StringName k_expected_quality{"expected_quality",false}; const StringName k_expected_wait{"expected_wait",false}; const StringName k_facility_id{"facility_id",false}; const StringName k_facility_service{"facility_service",false}; const StringName k_facility_tags{"facility_tags",false}; const StringName k_get_connector{"get_connector",false}; const StringName k_get_facility{"get_facility",false}; const StringName k_get_facility_business_price{"get_facility_business_price",false}; const StringName k_get_guest{"get_guest",false}; const StringName k_get_instances{"get_instances",false}; const StringName k_get_step_connector{"get_step_connector",false}; const StringName k_graph_revision{"graph_revision",false}; const StringName k_group_fit{"group_fit",false}; const StringName k_guest_service{"guest_service",false}; const StringName k_illegal_level{"illegal_level",false}; const StringName k_indices{"indices",false}; const StringName k_inputs_available{"inputs_available",false}; const StringName k_instance_id{"instance_id",false}; const StringName k_inventory_inputs{"inventory_inputs",false}; const StringName k_inventory_service{"inventory_service",false}; const StringName k_is_open{"is_open",false}; const StringName k_last_error{"last_error",false}; const StringName k_last_no_route_reason{"last_no_route_reason",false}; const StringName k_last_path_cost{"last_path_cost",false}; const StringName k_local_inventory_id{"local_inventory_id",false}; const StringName k_movement_type{"movement_type",false}; const StringName k_need_relief{"need_relief",false}; const StringName k_occupied_cells{"occupied_cells",false}; const StringName k_origin{"origin",false}; const StringName k_owns_connector{"owns_connector",false}; const StringName k_path{"path",false}; const StringName k_path_handle{"path_handle",false}; const StringName k_path_query_measured{"path_query_measured",false}; const StringName k_path_service{"path_service",false}; const StringName k_queue_entries{"queue_entries",false}; const StringName k_reachable{"reachable",false}; const StringName k_ready{"ready",false}; const StringName k_resource_path{"resource_path",false}; const StringName k_risk_level{"risk_level",false}; const StringName k_service_category{"service_category",false}; const StringName k_settled{"settled",false}; const StringName k_staff_only{"staff_only",false}; const StringName k_start{"start",false}; const StringName k_state{"state",false}; const StringName k_supported{"supported",false}; const StringName k_tags{"tags",false}; const StringName k_tagproj_hunger{"hunger",false}; const StringName k_tagproj_sleep{"sleep",false}; const StringName k_tagproj_hygiene{"hygiene",false}; const StringName k_tagproj_medical{"medical",false}; const StringName k_tagproj_leisure{"leisure",false}; const StringName k_tagproj_intimacy{"intimacy",false}; const StringName k_tagproj_dining{"dining",false}; const StringName k_tagproj_lodging{"lodging",false}; const StringName k_tagproj_social{"social",false}; const StringName k_tagproj_bath{"bath",false}; const StringName k_tagproj_wellness{"wellness",false}; const StringName k_tagproj_adult_only{"adult_only",false}; const StringName k_tagproj_restricted_service{"restricted_service",false}; const StringName k_tagproj_food{"food",false}; const StringName k_tagproj_service{"service",false}; const StringName k_target_cell{"target_cell",false}; const StringName k_targets{"targets",false}; const StringName k_temporary_block{"temporary_block",false}; const StringName k_travel_minutes{"travel_minutes",false}; const StringName k_tree{"tree",false}; const StringName k_usable{"usable",false}; }; public: // Whole builtin integer record operation. No retained sample values or time // suppression. Unsupported data returns before any caller-owned mutation. Dictionary performance_record_sample(Object *owner, const StringName &metric, int64_t duration) { const StringName supported("supported",false), report_key("report",false); Dictionary unsupported; unsupported[supported]=false; Object *script=owner ? owner->get_script() : nullptr; if (!script || String(script->get(StringName("resource_path",false))) != "res://scripts/core/performance_budget.gd" || metric==StringName() || duration<0) return unsupported; const StringName samples_key("_samples",false), ordered_key("_ordered_samples",false), bytes_key("_ordered_sample_bytes",false), integer_key("_integer_window_bytes",false), totals_key("_totals",false), counts_key("_sample_counts",false), budgets_key("_budgets",false); const Variant sv=owner->get(samples_key), ov=owner->get(ordered_key), bv=owner->get(bytes_key), iv=owner->get(integer_key), tv=owner->get(totals_key), cv=owner->get(counts_key), uv=owner->get(budgets_key), capacityv=owner->get(StringName("sample_capacity",false)); if (sv.get_type()!=Variant::DICTIONARY || ov.get_type()!=Variant::DICTIONARY || bv.get_type()!=Variant::DICTIONARY || iv.get_type()!=Variant::DICTIONARY || tv.get_type()!=Variant::DICTIONARY || cv.get_type()!=Variant::DICTIONARY || uv.get_type()!=Variant::DICTIONARY || capacityv.get_type()!=Variant::INT) return unsupported; Dictionary samples=sv, orders=ov, rawbytes=bv, integers=iv, totals=tv, counts=cv, budgets=uv; if (samples.is_read_only() || orders.is_read_only() || rawbytes.is_read_only() || integers.is_read_only() || totals.is_read_only() || counts.is_read_only()) return unsupported; const std::array maps{samples,orders,rawbytes,integers,totals,counts,budgets}; for (size_t i=0;i ordered; Variant savedbytes=rawbytes.get(metric,PackedByteArray()); bool reuse=existing && orders.has(metric) && savedbytes.get_type()==Variant::PACKED_BYTE_ARRAY && PackedByteArray(savedbytes)==before; if (reuse) { Variant orderv=orders[metric]; if (orderv.get_type()!=Variant::ARRAY) return unsupported; Array prior=orderv; if (prior.is_read_only() || !prior.is_typed() || prior.get_typed_builtin()!=Variant::INT || prior.size()!=values.size()) return unsupported; ordered=prior; } else { for (int64_t i=0;iint64_t(capacityv)) { Variant removed=values.pop_front(); ordered.remove_at(ordered.bsearch(removed)); } PackedByteArray after=UtilityFunctions::var_to_bytes(values); rawbytes[metric]=after; integers[metric]=after; const int64_t lifetime_total=the_tree_native::signed_add(int64_t(totalv),duration); const int64_t lifetime_count=the_tree_native::signed_add(int64_t(countv),1); totals[metric]=lifetime_total; counts[metric]=lifetime_count; const int64_t average=lifetime_count>0 ? lifetime_total/lifetime_count : 0; const int64_t maximum=ordered.is_empty() ? 0 : std::max(0,int64_t(ordered[ordered.size()-1])); int64_t p95=0; if (!ordered.is_empty()) { const int64_t index=std::max(the_tree_native::signed_add(the_tree_native::signed_add(signed_product(95,ordered.size()),99)/100,-1),0); p95=ordered[std::min(index,ordered.size()-1)]; } const int64_t aggregation=aggregationv, limit=limitv; // Original default match is P95, including unknown aggregation values. const int64_t measured=aggregation==0 ? average : (aggregation==2 ? maximum : p95); Dictionary report; report[StringName("metric_id",false)]=metric; report[StringName("window_sample_count",false)]=values.size(); report[StringName("lifetime_sample_count",false)]=lifetime_count; report[StringName("average_us",false)]=average; report[StringName("p95_us",false)]=p95; report[StringName("maximum_us",false)]=maximum; report[aggregation_key]=aggregation; report[StringName("measured_us",false)]=measured; report[limit_key]=limit; report[StringName("budget_exceeded",false)]=limit>0 && measured>limit; Dictionary result; result[supported]=true; result[report_key]=report; return result; } #include "guest_candidate_batch.inc" void clear_edge_cache() { cached_edges.clear(); } Dictionary search(const Array &cells, const Dictionary &indices, I start_index, const Dictionary &goals, const Callable &edge_provider) { return search_impl(cells, indices, start_index, goals, edge_provider, false); } Dictionary search_cached(const Array &cells, const Dictionary &indices, I start_index, const Dictionary &goals, const Callable &edge_provider) { return search_impl(cells, indices, start_index, goals, edge_provider, true); } // One ordered projection, with no new persistent ownership/cache. Only // builtin pure getters and the already guarded sole budget observer qualify. Dictionary project_guest_candidates(Object *runtime, const StringName &guest_id, int64_t open_state, int64_t degraded_state, int64_t movement_scale, int64_t stair_credit, int64_t orthogonal_cost, const Callable &ticks) { const ProjectionNames n; Dictionary unsupported; unsupported[n.k_supported] = false; if (!builtin(n,runtime, "res://autoload/simulation_runtime.gd") || !ticks.is_valid()) return unsupported; Object *path = runtime->get(n.k_path_service); Object *elevators = runtime->get(n.k_elevators); Object *facilities = runtime->get(n.k_facility_service); Object *definitions = runtime->get(n.k_definition_registry); Object *inventory = runtime->get(n.k_inventory_service); Object *guests = runtime->get(n.k_guest_service); if (!builtin(n,path,"res://scripts/world/path_service.gd") || !builtin(n,elevators,"res://scripts/transport/elevator_service.gd") || !builtin(n,facilities,"res://scripts/facility/facility_service.gd") || !builtin(n,definitions,"res://scripts/core/definition_registry.gd") || !builtin(n,inventory,"res://scripts/inventory/inventory_service.gd") || !builtin(n,guests,"res://scripts/guest/guest_service.gd") || !static_cast(runtime->call(n.k__guest_access_batch_can_select))) return unsupported; Object *guest = guests->call(n.k_get_guest,guest_id); Array candidates; if (!guest) { Dictionary result; result[n.k_supported] = true; result[n.k_candidates] = candidates; return result; } if (!builtin(n,guest,"res://scripts/guest/guest_runtime.gd")) return unsupported; const Array initial = facilities->call(n.k_get_instances); // Preflight is read-only: default registry/get_instances have no public // error/counter effects. Custom resources retain the original whole loop. for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); if (definition && !builtin(n,definition,"res://scripts/data/facility_definition.gd")) return unsupported; } Array goals; for (int64_t i=0;iget(n.k_current_cell); path->call(n.k_begin_guest_path_query_batch,start,goals); const Array ordered = facilities->call(n.k_get_instances); TypedArray layers; layers.push_back(0); layers.push_back(1); TypedArray access_ids; for (int64_t i=0;icall(n.k_get_facility,facility->get(n.k_definition_id)); if (!definition) continue; const Array tags = definition->get(n.k_tags); if (tags.has(n.k_staff_only)) continue; if (tags.has(n.k_entrance) && static_cast(runtime->call(n.k__guest_has_checked_in,guest))) continue; bool has_inputs = true; const Dictionary inputs = definition->get(n.k_inventory_inputs); const Array items = sorted_builtin_input_names(n,runtime,inputs); for (int64_t j=0;jcall(n.k_available_quantity,facility->get(n.k_local_inventory_id),items[j]); if (quantity < static_cast(inputs[items[j]])) {has_inputs=false;break;} } if (!has_inputs) { Dictionary row;row[n.k_facility_id]=facility->get(n.k_instance_id); row[n.k_inputs_available]=false;candidates.push_back(row);continue; } const Array destinations = facility_access_cells(n,path,facility); Dictionary route = nearest_guest_access_impl(n,path,start,destinations,facility->get(n.k_origin),layers,access_ids,ticks); if (static_cast(route.get(n.k_supported,false))) route.erase(n.k_supported); else route = Dictionary(runtime->call(n.k__find_facility_access_path,start,facility)); const Array walk = route.get(n.k_path,Array()); const bool plain_tag_relief = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; const Dictionary relief = plain_tag_relief ? builtin_tag_relief(n,tags) : Dictionary(runtime->call(n.k__need_relief_for_facility_tags,tags)); Dictionary row; row[n.k_facility_id]=facility->get(n.k_instance_id); row[n.k_facility_tags]=tags.duplicate(); const int64_t state = facility->get(n.k_state); row[n.k_is_open]=(state==open_state || state==degraded_state); row[n.k_reachable]=route.get(n.k_reachable,false); row[n.k_travel_minutes]=guest_path_minutes(n,path,elevators,walk,movement_scale,stair_credit,orthogonal_cost); const Array queue = facility->get(n.k_queue_entries); const int64_t capacity = facility->get(n.k_capacity); row[n.k_expected_wait]=signed_product(queue.size(),facility->get(n.k_base_service_minutes))/std::max(capacity,1); row[n.k_estimated_total_gold]=runtime->call(n.k_get_facility_business_price,facility); const int64_t quality = facility->get(n.k_base_quality); row[n.k_expected_quality]=std::max(0,std::min(quality,100)); row[n.k_need_relief]=relief; row[n.k_risk_level]=int64_t(0);row[n.k_illegal_level]=int64_t(0); row[n.k_group_fit]=signed_product(std::min(capacity,4),5); // Recheck at the original call position: preceding price/observer // callbacks must retain a replaced/custom runtime's original call. const bool plain_tag_category = builtin(n,runtime,"res://autoload/simulation_runtime.gd") && tags.is_typed() && tags.get_typed_builtin()==Variant::STRING_NAME; row[n.k_service_category]=plain_tag_category ? Variant(builtin_tag_category(n,tags)) : runtime->call(n.k__service_category_for_tags,tags); Dictionary handle;handle[n.k_target_cell]=route.get(n.k_target_cell,guest->get(n.k_current_cell)); handle[n.k_graph_revision]=path->get(n.k_graph_revision); row[n.k_path_handle]=handle;candidates.push_back(row); } path->call(n.k_end_guest_path_query_batch); Dictionary result;result[n.k_supported]=true;result[n.k_candidates]=candidates;return result; } private: // Direct translation of the two pure builtin tag methods. Fresh result, // original insertion/branch order, no retained definition/tag memo. static Dictionary builtin_tag_relief(const ProjectionNames &n,const Array &tags) { Dictionary relief; relief[n.k_tagproj_hunger]=int64_t(0);relief[n.k_tagproj_sleep]=int64_t(0); relief[n.k_tagproj_hygiene]=int64_t(0);relief[n.k_tagproj_medical]=int64_t(0); relief[n.k_tagproj_leisure]=int64_t(0);relief[n.k_tagproj_intimacy]=int64_t(0); if(tags.has(n.k_tagproj_dining)) {relief[n.k_tagproj_hunger]=int64_t(80);relief[n.k_tagproj_leisure]=int64_t(10);} if(tags.has(n.k_tagproj_lodging)) {relief[n.k_tagproj_sleep]=int64_t(90);relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),10);} if(tags.has(n.k_tagproj_social)||tags.has(n.k_tagproj_leisure)) relief[n.k_tagproj_leisure]=std::max(int64_t(relief[n.k_tagproj_leisure]),40); if(tags.has(n.k_tagproj_hygiene)||tags.has(n.k_tagproj_bath)) relief[n.k_tagproj_hygiene]=std::max(int64_t(relief[n.k_tagproj_hygiene]),80); if(tags.has(n.k_tagproj_medical)) relief[n.k_tagproj_medical]=int64_t(90); else if(tags.has(n.k_tagproj_wellness)) relief[n.k_tagproj_medical]=std::max(int64_t(relief[n.k_tagproj_medical]),20); if(tags.has(n.k_tagproj_adult_only)||tags.has(n.k_tagproj_restricted_service)) relief[n.k_tagproj_intimacy]=int64_t(80); return relief; } static StringName builtin_tag_category(const ProjectionNames &n,const Array &tags) { if(tags.has(n.k_tagproj_dining))return n.k_tagproj_food; if(tags.has(n.k_tagproj_lodging))return n.k_tagproj_lodging; if(tags.has(n.k_tagproj_social))return n.k_tagproj_leisure; return n.k_tagproj_service; } static bool builtin(const ProjectionNames &n,Object *object,const char *resource) { if (!object) return false;Object *script=object->get_script(); return script && String(script->get(n.k_resource_path))==resource; } // Exact builtin cache-key spelling. No normalized/reordered profile and no // persistent cache; String lengths count Unicode codepoints as GDScript does. static String cache_key_suffix(const ProjectionNames &n,Object *path, const TypedArray &layers, const TypedArray &access) { String layer_text, access_text; for (int64_t i=0; i(layers[i])); } for (int64_t i=0; i(access[i])); access_text += String::num_int64(value.length()) + ":" + value; } return String("|L:") + layer_text + "|A:" + access_text + "|R:" + String::num_int64(static_cast(path->get(n.k_graph_revision))); } static String cache_key_with_suffix(const Vector3i &start, const Vector3i &goal, const String &suffix) { return String::num_int64(start.x) + "," + String::num_int64(start.y) + "," + String::num_int64(start.z) + ">" + String::num_int64(goal.x) + "," + String::num_int64(goal.y) + "," + String::num_int64(goal.z) + suffix; } static int64_t signed_product(int64_t a,int64_t b) { const uint64_t product=static_cast(a)*static_cast(b); if (product<=static_cast(std::numeric_limits::max())) return static_cast(product); return std::numeric_limits::min()+static_cast(product-(uint64_t(1)<<63)); } static Array facility_access_cells(const ProjectionNames &n,Object *path,Object *facility) { const Dictionary passable=path->get(n.k__passable_cells); Array occupied=Array(facility->get(n.k_occupied_cells)).duplicate(); if (occupied.is_empty()) occupied.push_back(facility->get(n.k_origin)); Dictionary unique; for (int64_t i=0;iget(n.k_origin);if(passable.has(origin)) unique[origin]=true; const Array keys=unique.keys();std::vector sorted;sorted.reserve(keys.size()); for (int64_t i=0;iget(n.k__guest_step_connector_memo); // Route-local only. Reuse an ownership result only after an actual // BOOL return and a typed cached step; no script callback occurs on a // repeated typed memo hit. A miss/conversion/custom script keeps calls. const bool builtin_pair = builtin(n,path,"res://scripts/world/path_service.gd") && builtin(n,elevators,"res://scripts/transport/elevator_service.gd"); bool ownership_valid = false; bool ownership_value = false; StringName ownership_connector; for(int64_t i=1;i access;connector=path->call(n.k_get_step_connector,from,to,access);} bool special; if (builtin_pair && typed_memo_hit && ownership_valid && connector == ownership_connector) { special = ownership_value; } else { const Variant owned = elevators->call(n.k_owns_connector,connector); special = static_cast(owned); ownership_valid = builtin_pair && typed_memo_hit && owned.get_type() == Variant::BOOL; ownership_value = special; ownership_connector = connector; } if(!special && String(connector).begins_with("infra.connector:") && from.x==to.x && from.z==to.z && std::abs(int64_t(from.y)-int64_t(to.y))==1) { const Dictionary detail=path->call(n.k_get_connector,connector); special=detail.get(n.k_movement_type,StringName())==Variant(n.k_CONNECTOR) && static_cast(detail.get(n.k_cost,int64_t(0)))==150 && stair_credit>movement_scale; } if(special) { const int64_t cost=path->call(n.k_calculate_guest_batch_path_cost,route[0],route[route.size()-1],route); return static_cast(std::ceil(static_cast(cost)/static_cast(orthogonal_cost))); } } return std::max(route.size()-1,0); } public: // Stateless translation of the builtin nearest access query. The caller // supplies the existing typed default profile and the real Time callable. // Public cache publication, failure diagnostics and fallback stay ordered. Dictionary nearest_guest_access(Object *path, const Vector3i &start, const Array &goals, const Vector3i &fallback_target, const TypedArray &layers, const TypedArray &access, const Callable &ticks) { const ProjectionNames n; return nearest_guest_access_impl(n,path,start,goals,fallback_target,layers,access,ticks); } private: Dictionary nearest_guest_access_impl(const ProjectionNames &n,Object *path, const Vector3i &start, const Array &goals, const Vector3i &fallback_target, const TypedArray &layers, const TypedArray &access, const Callable &ticks) { Dictionary unsupported; unsupported[n.k_supported] = false; if (!path || !ticks.is_valid() || goals.is_empty()) return unsupported; Object *script = path->get_script(); if (!script || String(script->get(n.k_resource_path)) != "res://scripts/world/path_service.gd") return unsupported; Dictionary batch = path->get(n.k__query_batch); if (batch.is_empty() || start != static_cast(batch[n.k_start])) return unsupported; const Dictionary passable = path->get(n.k__passable_cells); if (!passable.has(start) || blocked(n,path, start) || !layers.has(start.z)) return unsupported; const Dictionary targets = batch[n.k_targets]; Dictionary cache = path->get(n.k__path_cache); // Exact builtin validation loop has no callback before ticks.call(). // Build the unchanged profile/revision suffix lazily at the first key. String key_suffix; bool key_suffix_ready = false; for (int64_t j = 0; j < goals.size(); ++j) { if (goals[j].get_type() != Variant::VECTOR3I) return unsupported; const Vector3i cell = goals[j]; if (!targets.has(cell)) { const bool searchable = passable.has(cell) && layers.has(cell.z) && !blocked(n,path, cell); if (searchable && (start.z == cell.z || static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, cell, layers, access)))) return unsupported; } if (!key_suffix_ready) { key_suffix = cache_key_suffix(n,path, layers, access); key_suffix_ready = true; } const String key = cache_key_with_suffix(start, cell, key_suffix); if (cache.has(key)) return unsupported; } const int64_t started = ticks.call(); if (!static_cast(batch[n.k_ready])) { batch[n.k_tree] = path->call(n.k__build_guest_query_tree_compact, start, targets, layers, access); batch[n.k_arithmetic_wrapped] = path->get(n.k__guest_tree_arithmetic_wrapped); batch[n.k_ready] = true; } const Dictionary tree = batch[n.k_tree]; if (!static_cast(tree.get(n.k_usable, false)) || static_cast(batch.get(n.k_arithmetic_wrapped, false))) return unsupported; Vector3i best_cell = fallback_target; bool found = false; int64_t best_cost = 0; const Dictionary settled = tree[n.k_settled]; bool cost_view_ready=false,compact_cost_view=false; Dictionary cost_indices,cost_dictionary; PackedInt64Array cost_values; for (int64_t j = 0; j < goals.size(); ++j) { const Vector3i cell = goals[j]; if (!targets.has(cell) || !settled.has(cell)) continue; // No callback occurs between these original numeric cost reads. // Initialize lazily at the first eligible goal, and retain nothing // past this call or reuse after the subsequent route callbacks. if (!cost_view_ready) { compact_cost_view=tree.get(n.k_compact,false); if(compact_cost_view) {cost_indices=tree[n.k_indices];cost_values=tree[n.k_cost_values];} else cost_dictionary=tree[n.k_costs]; cost_view_ready=true; } int64_t cost=0; if(compact_cost_view) { if(!cost_indices.has(cell)) return unsupported; const int64_t index=cost_indices[cell]; if(index<0 || index>=cost_values.size()) return unsupported; cost=cost_values[index]; } else { if(!cost_dictionary.has(cell)) return unsupported; cost=cost_dictionary[cell]; } if (!found || cost < best_cost) { found = true; best_cost = cost; best_cell = cell; } } TypedArray best_path; if (found) { best_path = resolve_ready_guest_point(n,path, start, best_cell, tree, layers, access); if (best_path.is_empty()) return unsupported; } if (!goals.is_empty() && (!found || goals[goals.size() - 1] != Variant(best_cell))) { resolve_ready_guest_point(n,path, start, goals[goals.size() - 1], tree, layers, access); } const int64_t elapsed = the_tree_native::signed_add(static_cast(ticks.call()), the_tree_native::signed_add(~started, 1)); path->emit_signal(n.k_path_query_measured, std::max(elapsed, 0)); Dictionary result; result[n.k_supported] = true; result[n.k_reachable] = found; result[n.k_path] = best_path; result[n.k_target_cell] = best_cell; return result; } private: // Only StringName keys qualify. Conversion-sensitive and custom runtime // cases retain the original script sorter. No owner values are retained. static Array sorted_builtin_input_names(const ProjectionNames &n,Object *runtime,const Dictionary &inputs) { auto original=[&]() -> Array {return runtime->call(n.k__sorted_name_keys,inputs);}; if(!builtin(n,runtime,"res://autoload/simulation_runtime.gd")) return original(); const Array keys=inputs.keys(); std::vector> rows; rows.reserve(keys.size()); for(int64_t i=0;i result; for(const auto &row:rows) result.push_back(row.second); return result; } // Fresh writable typed output, matching the builtin append loop. Check // the script at this original call position, after any route callbacks. static Variant copy_builtin_guest_route(const ProjectionNames &n,Object *path,const TypedArray &route) { if(!builtin(n,path,"res://scripts/world/path_service.gd")) return path->call(n.k__copy_path,route); TypedArray copied; for(int64_t i=0;iget(n.k__cell_traffic); const Dictionary traffic = traffic_map.get(cell, Dictionary()); return !traffic.is_empty() && static_cast(traffic[n.k_temporary_block]); } static bool tree_has_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { if (!static_cast(tree.get(n.k_compact, false))) { const Dictionary values = tree[n.k_costs]; return values.has(cell); } const Dictionary indices = tree[n.k_indices]; if (!indices.has(cell)) return false; const int64_t index = indices[cell]; const PackedInt64Array values = tree[n.k_cost_values]; return index >= 0 && index < values.size(); } static int64_t tree_cost(const ProjectionNames &n,const Dictionary &tree, const Vector3i &cell) { if (!static_cast(tree.get(n.k_compact, false))) { const Dictionary values = tree[n.k_costs]; return static_cast(values[cell]); } const Dictionary indices = tree[n.k_indices]; const PackedInt64Array values = tree[n.k_cost_values]; return values[static_cast(indices[cell])]; } static TypedArray resolve_ready_guest_point(const ProjectionNames &n,Object *path, const Vector3i &start, const Vector3i &goal, const Dictionary &tree, const TypedArray &layers, const TypedArray &access) { const Dictionary passable = path->get(n.k__passable_cells); if (!passable.has(start)) return path->call(n.k__route_failure, n.k_START_NOT_PASSABLE); if (!passable.has(goal)) return path->call(n.k__route_failure, n.k_GOAL_NOT_PASSABLE); if (!layers.has(start.z) || !layers.has(goal.z)) return path->call(n.k__route_failure, n.k_ACCESS_LAYER_DENIED); if (blocked(n,path, start)) return path->call(n.k__route_failure, n.k_START_TEMPORARILY_BLOCKED); if (blocked(n,path, goal)) return path->call(n.k__route_failure, n.k_GOAL_TEMPORARILY_BLOCKED); // ticks/tree callbacks may have changed the script or revision. Recheck // at this original call position and never reuse the pre-tick suffix. const String key = builtin(n,path,"res://scripts/world/path_service.gd") ? cache_key_with_suffix(start, goal, cache_key_suffix(n,path, layers, access)) : String(path->call(n.k__cache_key, start, goal, layers, access)); Dictionary cache = path->get(n.k__path_cache); const Dictionary batch = path->get(n.k__query_batch); const Dictionary targets = batch[n.k_targets]; if (cache.has(key) || !targets.has(goal)) return path->call(n.k__find_path_internal, start, goal); path->set(n.k_cache_misses, the_tree_native::signed_add(static_cast(path->get(n.k_cache_misses)), 1)); if (start.z != goal.z && !static_cast(path->call(n.k__guest_batch_has_permitted_layer_crossing, start, goal, layers, access))) return path->call(n.k__route_failure, n.k_GOAL_UNREACHABLE); TypedArray route; const Dictionary settled = tree[n.k_settled]; if (start == goal) route.push_back(start); else if (settled.has(goal)) route = Array(path->call(n.k__guest_tree_reconstruct_path, tree, goal)); if (route.is_empty()) return path->call(n.k__route_failure, path->call(n.k__diagnose_no_route_reason, start, goal, layers, access)); cache[key] = copy_builtin_guest_route(n,path,route); path->set(n.k_last_no_route_reason, n.k_OK); path->set(n.k_last_path_cost, tree_cost(n,tree, goal)); path->set(n.k_last_error, String("")); return route; } public: private: // One existing builtin provider operation, with no new value cache. Only // connector-free WALK rows qualify; unsupported cases call the old provider. // All work stays private until the original final shared[current] assignment. struct WalkEdgeNames { const StringName resource_path{"resource_path",false}, constants_method{"get_script_constant_map",false}; const StringName front{"FRONT",false}, back{"BACK",false}, walk{"MOVEMENT_WALK",false}; const StringName base{"ORTHOGONAL_MOVE_COST",false}, congestion{"CONGESTION_COST_PER_EXCESS",false}; const StringName workspace{"_guest_tree_workspace",false}, edges{"edges",false}, indices{"indices",false}; const StringName adjacency{"_adjacency",false}, traffic{"_cell_traffic",false}, vertical{"_vertical_walk_requires_connector",false}; const StringName to{"to",false}, connector{"connector_id",false}, access{"access_id",false}, movement{"movement_type",false}; const StringName base_cost{"base_cost",false}, cost{"cost",false}, temporary{"temporary_block",false}; const StringName dynamic{"dynamic_cost",false}, density{"current_density",false}, capacity{"base_capacity",false}; const StringName provider{"_guest_tree_shared_edges",false}; }; struct WalkEdgeContext { Object *path=nullptr; int64_t front=0, back=0, base=0, congestion=0; StringName walk; }; static bool walk_edge_context(const WalkEdgeNames &n,Object *path,const Array &layers, const Array &access,WalkEdgeContext &context) { if (!path || layers.size()!=2 || !access.is_empty() || layers[0].get_type()!=Variant::INT || layers[1].get_type()!=Variant::INT) return false; Object *script=path->get_script(); if (!script || String(script->get(n.resource_path))!="res://scripts/world/path_service.gd" || !script->has_method(n.constants_method)) return false; const Variant value=script->call(n.constants_method); if (value.get_type()!=Variant::DICTIONARY) return false; const Dictionary constants=value; for (const StringName &key : {n.front,n.back,n.base,n.congestion}) if (constants.get(key,Variant()).get_type()!=Variant::INT) return false; if (constants.get(n.walk,Variant()).get_type()!=Variant::STRING_NAME || int64_t(layers[0])!=int64_t(constants[n.front]) || int64_t(layers[1])!=int64_t(constants[n.back])) return false; context.path=path;context.front=constants[n.front];context.back=constants[n.back]; context.base=constants[n.base];context.congestion=constants[n.congestion];context.walk=constants[n.walk]; return true; } static bool builtin_walk_edge_rows(const WalkEdgeNames &n,const WalkEdgeContext &context, const Vector3i ¤t,Array &rows) { if (!context.path) return false; const Variant workspace_value=context.path->get(n.workspace); if (workspace_value.get_type()!=Variant::DICTIONARY) return false; const Dictionary workspace=workspace_value; const Variant shared_value=workspace.get(n.edges,Variant()); if (shared_value.get_type()!=Variant::DICTIONARY) return false; Dictionary shared=shared_value; // Original cached-row branch precedes readonly and all other state reads. if (shared.has(current)) { const Variant cached=shared[current]; if (cached.get_type()!=Variant::ARRAY) return false; rows=cached;return true; } if (shared.is_read_only()) return false; const Variant indices_value=workspace.get(n.indices,Variant()), adjacency_value=context.path->get(n.adjacency); const Variant traffic_value=context.path->get(n.traffic), vertical_value=context.path->get(n.vertical); if (indices_value.get_type()!=Variant::DICTIONARY || adjacency_value.get_type()!=Variant::DICTIONARY || traffic_value.get_type()!=Variant::DICTIONARY || vertical_value.get_type()!=Variant::BOOL) return false; const Dictionary indices=indices_value, adjacency=adjacency_value, traffic=traffic_value; const Variant raw_value=adjacency.get(current,Array()); if (raw_value.get_type()!=Variant::ARRAY) return false; const Array raw=raw_value;Array result; for (int64_t i=0;i0?excess:0,context.congestion)); } const int64_t cost=the_tree_native::signed_add(int64_t(base),dynamic); Array pair;pair.push_back(neighbor);pair.push_back(cost);result.push_back(pair); // Same short circuit and first invalid prefix as the original method. if (cost<=0 || !indices.has(neighbor)) break; } shared[current]=result;rows=result;return true; } public: Dictionary guest_tree_edge_rows(Object *path,const Vector3i ¤t,const Array &layers,const Array &access) { const WalkEdgeNames names;WalkEdgeContext context;Array rows; Dictionary result;const StringName supported{"supported",false}, row_key{"rows",false}; result[supported]=false; if (!walk_edge_context(names,path,layers,access,context) || !builtin_walk_edge_rows(names,context,current,rows)) return result; result[supported]=true;result[row_key]=rows;return result; } private: Dictionary search_impl(const Array &cells, const Dictionary &indices, I start_index, const Dictionary &goals, const Callable &edge_provider, bool use_edge_cache) { Dictionary output; output[StringName("status")] = String("unusable"); if (start_index < 0 || start_index >= cells.size() || !edge_provider.is_valid()) return output; try { std::vector goal_indices; const Array goal_keys = goals.keys(); for (I j = 0; j < goal_keys.size(); ++j) goal_indices.push_back(static_cast(indices.get(goal_keys[j], I(-1)))); Array arguments; arguments.resize(1); const WalkEdgeNames walk_names;WalkEdgeContext walk_context; if (edge_provider.get_method()==walk_names.provider && edge_provider.get_argument_count()==1 && edge_provider.get_bound_arguments_count()==2 && edge_provider.get_unbound_arguments_count()==0) { const Array bound=edge_provider.get_bound_arguments(); if (bound.size()==2 && bound[0].get_type()==Variant::ARRAY && bound[1].get_type()==Variant::ARRAY) walk_edge_context(walk_names,edge_provider.get_object(),bound[0],bound[1],walk_context); } // Call the original bound Godot edge method only when the search expands a node. // Preserve its lazy cache population, filter ordering and first invalid row. auto original_edges = [&](I current) { arguments[0] = cells[current]; Array fused;bool fused_supported=false; if (cells[current].get_type()==Variant::VECTOR3I) { const Vector3i cell=cells[current]; fused_supported=builtin_walk_edge_rows(walk_names,walk_context,cell,fused); } const Variant value = fused_supported ? Variant(fused) : edge_provider.callv(arguments); if (value.get_type() != Variant::ARRAY) return std::vector{{-1, 0}}; const Array rows = value; std::vector result; result.reserve(rows.size()); for (I j = 0; j < rows.size(); ++j) { if (rows[j].get_type() != Variant::ARRAY) { result.push_back({-1, 0}); break; } const Array row = rows[j]; if (row.size() != 2 || row[1].get_type() != Variant::INT) { result.push_back({-1, 0}); break; } const I cost = static_cast(row[1]); // Nonpositive cost is rejected before requesting the neighbor index. if (cost <= 0) { result.push_back({-1, cost}); break; } const I neighbor = static_cast(indices.get(row[0], I(-1))); result.push_back({neighbor, cost}); if (neighbor < 0) break; } return result; }; // Borrow cached rows only during the pure numeric edge loop. // No engine callback runs while that borrowed vector is traversed. std::vector converted; auto edges = [&](I current) -> const std::vector& { if (use_edge_cache) { const auto found = cached_edges.find(current); if (found != cached_edges.end()) return found->second; } converted = original_edges(current); // Preserve the returned conversion even if a reentrant provider // populated this cache key first. Never substitute its row here. if (use_edge_cache) cached_edges.emplace(current, converted); return converted; }; const auto result = the_tree_native::search(cells.size(), start_index, goal_indices, edges); output[StringName("status")] = String(result.status.c_str()); if (result.status != "usable") return output; PackedInt64Array costs, parents; if (costs.resize(result.costs.size()) != OK || parents.resize(result.parents.size()) != OK) { output[StringName("status")] = String("unusable"); return output; } // Newly resized, private packed arrays own their writable storage. // A provider may shrink caller cells. Preserve the old written // prefix and resize-created zero tail, not the whole native vector. const I written_count=cells.size(); if(written_count<=static_cast(result.costs.size())) { std::copy_n(result.costs.begin(),written_count,costs.ptrw()); std::copy_n(result.parents.begin(),written_count,parents.ptrw()); } else { // Keep the original unsupported-growth path unchanged. for (I j=0;j discovered, parent_discovered; for (I j : result.discovered) discovered.push_back(j); for (I j : result.parent_discovered) parent_discovered.push_back(j); Dictionary settled; for (I j : result.settled) settled[cells[j]] = true; output[StringName("cost_values")] = costs; output[StringName("parent_indices")] = parents; output[StringName("discovered")] = discovered; output[StringName("parent_discovered")] = parent_discovered; output[StringName("settled")] = settled; return output; } catch (const std::exception &) { output = Dictionary(); output[StringName("status")] = String("unusable"); return output; } } }; void initialize_tree_numeric_core(ModuleInitializationLevel level) { if (level == MODULE_INITIALIZATION_LEVEL_SCENE) GDREGISTER_CLASS(TheTreeNumericCore); } void uninitialize_tree_numeric_core(ModuleInitializationLevel) {} extern "C" { GDExtensionBool GDE_EXPORT tree_numeric_core_init(GDExtensionInterfaceGetProcAddress get_proc, GDExtensionClassLibraryPtr library, GDExtensionInitialization *initialization) { GDExtensionBinding::InitObject init(get_proc, library, initialization); init.register_initializer(initialize_tree_numeric_core); init.register_terminator(uninitialize_tree_numeric_core); init.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); return init.init(); } }