// Opt-in request-algorithm guard. It never changes ticket-source configuration. import function PD_RequestLease(milliseconds : int) : bool; import function PD_RequestLeaseAlive() : bool; // Trusted diagnostic subclasses may override ONLY this pure literal accessor. // It declares provenance; it is not an engine resource/class identity getter. @addMethod(CTicketAlgorithmApproach) public function PDRequestBindingTag() : string { return ""; } @addField(CR4Player) var pdRAArmed : bool; @addField(CR4Player) var pdRAWindow : int; @addField(CR4Player) var pdRAGeneration : int; @addField(CR4Player) var pdRAActors : array; @addField(CR4Player) var pdRAIds : array; @addField(CR4Player) var pdRAScores : array; @addField(CR4Player) var pdRAMode : string; @addField(CR4Player) var pdRADeadlineTick : int; @addField(CR4Player) var pdRARecords : array; @addField(CR4Player) var pdRADropped : int; @addField(CR4Player) var pdRAReason : string; @addField(CR4Player) var pdRANextInstance : int; @addField(CTicketAlgorithmApproach) var pdRASeenWindow : int; @addField(CTicketAlgorithmApproach) var pdRASeenGeneration : int; @addField(CTicketAlgorithmApproach) var pdRAInstance : int; @addMethod(CR4Player) function PDRequestEnd(reason : string) { if(!pdRAArmed) return; pdRAArmed = false; PD_RequestLease(0); pdRAReason = reason; pdRAActors.Clear(); // No request-instance or source fields are ever written by this facility. } @addMethod(CR4Player) function PDRequestTick() { var i : int; if(!pdRAArmed) return; if(!PD_RequestLeaseAlive()) { PDRequestEnd("wall_budget"); return; } if(pdGeneration != pdRAGeneration) { PDRequestEnd("generation_changed"); return; } if(theGame.pdTicks >= pdRADeadlineTick) { PDRequestEnd("tick_budget"); return; } for(i = 0; i < pdRAActors.Size(); i += 1) if(!pdRAActors[i] || !pdRAActors[i].IsAlive() || pdRAIds[i] >= pdActors.Size() || pdActors[pdRAIds[i]] != pdRAActors[i] || !PDTeleportOwns(pdRAActors[i])) { PDRequestEnd("actor_lost"); return; } if(!IsAlive()) PDRequestEnd("player_death"); } @addMethod(CR4Player) function PDRequestStatus() : string { var effective : bool; var reason : string; effective = pdRAArmed && PD_RequestLeaseAlive() && pdGeneration == pdRAGeneration && theGame.pdTicks < pdRADeadlineTick; reason = pdRAReason; if(pdRAArmed && !PD_RequestLeaseAlive()) reason = "wall_budget"; return "{\"window_id\":" + pdRAWindow + ",\"generation\":" + pdRAGeneration + ",\"active\":" + PDBool(effective) + ",\"armed\":" + PDBool(pdRAArmed) + ",\"algorithm\":\"approach\",\"instrumented_class\":\"CTicketAlgorithmApproach\"" + ",\"concrete_class\":null,\"runtime_node_id\":null,\"count_mode_available\":false" + ",\"mode\":" + PDQuote(pdRAMode) + ",\"actor_ids\":[" + PDRequestIds() + "],\"scores\":[" + PDRequestScores() + "],\"deadline_tick\":" + pdRADeadlineTick + ",\"records\":" + pdRARecords.Size() + ",\"dropped\":" + pdRADropped + ",\"reason\":" + PDQuote(reason) + ",\"instance_count_fields_modified\":false" + ",\"ticket_sources_modified\":false}"; } @addMethod(CR4Player) function PDRequestIds() : string { var i : int; var result : string; for(i = 0; i < pdRAIds.Size(); i += 1) { if(i > 0) result += ","; result += pdRAIds[i]; } return result; } @addMethod(CR4Player) function PDRequestScores() : string { var i : int; var result : string; for(i = 0; i < pdRAScores.Size(); i += 1) { if(i > 0) result += ","; result += pdRAScores[i]; } return result; } @addMethod(CR4Player) function PDRequestDispatch(command : string, values : array, out error : string) : string { var id, ticks, milliseconds, i, j, start : int; var score : float; var mode, result : string; var ids, scores : array; if(command == "request_algorithm_status") return PDRequestStatus(); if((command == "request_algorithm_arm" && values.Size() != 6) || (command == "request_algorithm_stop" && values.Size() != 2) || (command == "request_algorithm_page" && values.Size() != 3)) { error = "request_argument_count"; return "null"; } if(StringToInt(values[0]) != pdGeneration) { error = "stale_world_generation"; return "null"; } if(command != "request_algorithm_arm") { if(StringToInt(values[1]) != pdRAWindow || pdRAGeneration != pdGeneration) { error = "request_window_identity_mismatch"; return "null"; } if(command == "request_algorithm_stop") { PDRequestEnd("host_stop"); return PDRequestStatus(); } start = StringToInt(values[2]); if(start < 0 || start > pdRARecords.Size()) { error = "request_page_out_of_range"; return "null"; } result = "{\"window_id\":" + pdRAWindow + ",\"generation\":" + pdRAGeneration + ",\"start\":" + start + ",\"records\":["; for(i = start; i < pdRARecords.Size() && i < start + 4; i += 1) { if(i > start) result += ","; result += pdRARecords[i]; } return result + "],\"total\":" + pdRARecords.Size() + ",\"dropped\":" + pdRADropped + "}"; } PDRequestTick(); if(pdRAArmed) { error = "request_window_already_active"; return "null"; } if(!theGame.IsPausedForReason("PathDevkit") || !theGame.AreSavesLocked() || !IsAlive()) { error = "request_requires_alive_paused_nosave"; return "null"; } ids = StrSplit(values[1], ","); scores = StrSplit(values[5], ","); ticks = StringToInt(values[2]); milliseconds = StringToInt(values[3]); mode = values[4]; if(ids.Size() < 1 || ids.Size() > 8 || scores.Size() != ids.Size()) { error = "request_actor_score_count"; return "null"; } if(ticks < 1 || ticks > 600 || milliseconds < 1 || milliseconds > 60000 || theGame.pdTicks > 2147483046 || pdRAWindow >= 2147483646) { error = "request_budget_or_identity_exhausted"; return "null"; } if(mode != "observe" && mode != "score") { error = "invalid_request_mode_or_scores"; return "null"; } // Validate the entire ordered selection before touching session state/lease. for(i = 0; i < ids.Size(); i += 1) { id = StringToInt(ids[i]); score = StringToFloat(scores[i]); if(id < 0 || id >= pdActors.Size() || !PDTeleportOwns(pdActors[id]) || !pdActors[id].IsAlive()) { error = "distinct_alive_owned_actors_required"; return "null"; } for(j = 0; j < i; j += 1) if(id == StringToInt(ids[j])) { error = "duplicate_request_actor"; return "null"; } if(score != score || score < 0 || score > 1000000 || (mode == "score" && score < 0.000001) || (mode == "observe" && score != 0)) { error = "invalid_request_mode_or_scores"; return "null"; } } if(!PD_RequestLease(milliseconds)) { error = "request_wall_lease_rejected"; return "null"; } pdRAWindow += 1; pdRAGeneration = pdGeneration; pdRAIds.Clear(); pdRAActors.Clear(); pdRAScores.Clear(); for(i = 0; i < ids.Size(); i += 1) { id = StringToInt(ids[i]); pdRAIds.PushBack(id); pdRAActors.PushBack(pdActors[id]); pdRAScores.PushBack(StringToFloat(scores[i])); } pdRAMode = mode; pdRADeadlineTick = theGame.pdTicks + ticks; pdRARecords.Clear(); pdRADropped = 0; pdRANextInstance = 0; pdRAReason = "active"; pdRAArmed = true; return PDRequestStatus(); } @addMethod(CR4Player) function PDRequestOutput(algorithm : CTicketAlgorithmApproach, actor : CActor, target : CActor, original : float, countBefore : int, countAfter : int, active : bool, hasTicket : bool) : float { var index : int; var returned : float; var record, rawTag, quotedTag : string; var tagOversized : bool; PDRequestTick(); if(!pdRAArmed) return original; index = pdRAActors.FindFirst(actor); if(index < 0) return original; // On overflow fail closed to original behavior, not unrecorded intervention. if(pdRARecords.Size() >= 128 || original != original || original < -100000000 || original > 100000000) { pdRADropped += 1; PDRequestEnd("record_budget_or_invalid_score"); return original; } returned = original; if(pdRAMode == "score" && original > 0) returned = pdRAScores[index]; // Original score/count handling is already complete. No additional scoring, // eligibility, acquisition or RNG call is made to inspect the instance. rawTag = algorithm.PDRequestBindingTag(); // Keep native string input/output storage distinct. Fixed JSON enum labels // need no additional native string conversion. quotedTag = PDQuote(rawTag); tagOversized = StrLen(quotedTag) > 66; if(tagOversized) quotedTag = "null"; if(algorithm.pdRASeenWindow != pdRAWindow || algorithm.pdRASeenGeneration != pdGeneration) { pdRANextInstance += 1; algorithm.pdRAInstance = pdRANextInstance; algorithm.pdRASeenWindow = pdRAWindow; algorithm.pdRASeenGeneration = pdGeneration; } record = "{\"sequence\":" + (pdRARecords.Size() + 1) + ",\"window_id\":" + pdRAWindow + ",\"generation\":" + pdGeneration + ",\"tick\":" + theGame.pdTicks + ",\"engine_time\":" + theGame.GetEngineTimeAsSeconds() + ",\"actor_id\":" + pdRAIds[index] + ",\"target_id\":" + PathDevkitActorId(target) + ",\"algorithm_instance\":" + algorithm.pdRAInstance + ",\"instrumented_class\":\"CTicketAlgorithmApproach\",\"concrete_class\":null,\"runtime_node_id\":null" + ",\"original_score\":" + original + ",\"returned_score\":" + returned + ",\"count_field_before\":" + countBefore + ",\"count_field_after\":" + countAfter + ",\"binding_tag\":" + quotedTag; if(tagOversized) record += ",\"binding_tag_status\":\"invalid_size\""; else if(rawTag == "") record += ",\"binding_tag_status\":\"untagged\""; else record += ",\"binding_tag_status\":\"declared\""; record += ",\"effective_requested_count\":null,\"active\":" + PDBool(active) + ",\"has_ticket\":" + PDBool(hasTicket) + "}"; if(StrLen(record) > 1024) { pdRADropped += 1; PDRequestEnd("record_size"); return original; } if(!PD_RequestLeaseAlive()) { pdRADropped += 1; PDRequestEnd("wall_budget"); return original; } pdRARecords.PushBack(record); return returned; } @wrapMethod(CTicketAlgorithmApproach) function CalculateTicketImportance() : float { var original : float; var countBefore : int; countBefore = overrideTicketsCount; original = wrappedMethod(); if(thePlayer && thePlayer.pdRAArmed) return thePlayer.PDRequestOutput(this, GetActor(), GetCombatTarget(), original, countBefore, overrideTicketsCount, IsActive(), HasTicket()); return original; }