Improve AdventureBot recruitment, world presence and performance

Manage Arthoran as a persistent level-60 tank profile, add Worgen forms and mounts, enable PvP and recruit through native LFG with preparation actions and player invitations.

Reduce repeated route and flight-planning work, bound failed-travel retries and add runtime timing diagnostics. Include 86 passing tests and measurements with 110 online bots.
This commit is contained in:
Nico committed 2026-10-29 01:36:35 +01:00
1 parent cac4142ec1
commit 0173a434f4
39 files changed
+1958 -74

No files matched your search

+272 -1
View File
@@ -1,3 +1,271 @@
# Aktuell: Performance-Verbesserungen implementiert und mit110Bots gemessen
Nutzer beauftragte geringere Last/bessere Mehrkernnutzung im Hinblick auf spätere
Produktion. Branch feature/clientless-player-core, letzter Commit cac4142ec1.
Sämtliche vorherigen Arthoran/Worgen/PvP/nativer-LFG-Änderungen enthalten.
Dieser Stand wird auf ausdrücklichen Nutzerauftrag lokal committet; kein Push.
Doku doc/clientless/performance.md, Nachweise checkpoints/2026-10-29-performance/.
Aktuelle Installation: letzter erfolgreicher Build /tmp/vcore-performance-retry-build.log,
Install /tmp/vcore-performance-retry-install.log. Testserver PID214924 in tmux
vcore-worldserver, frischer Start /tmp/vcore-performance-retry-start1.log; aktuelle
ready-Meldung, Prozess und TCP8085 LISTEN bestätigt. Keine Produktion berührt.
Aktive Config MapUpdate.Threads=4 (vorher1), Network.Threads=1, Loader weiter
50 persistent+5 temporär pro Fraktion. ALLE110 online, pending0, error leer.
Gruppenfindungstest-Deadline01:00 abgelaufen; kein Setup-Helfer aktiv. Normale
persistente Tagespläne werden nach Neustart verfolgt, Test nicht heimlich verlängert.
Letzte /proc-Messung10.069s bei110Bots: Hauptthread26.2% eines logischen Kerns,
vier Mapworker38.6/37.6/38.1/38.5%. Vorherige Beobachtung95.1% Hauptthread,
9.9% einzelner Mapworker. Verschiedene laufende Situationen, KEIN deterministischer
Benchmark/keine garantierte Prozentverbesserung. CPU-Datei im Checkpoint.
Letztes30.011s CPC-Fenster110Bots: Actions7.762s, Controllers1.612s. Baseline
16Bots/31.923s: Actions24.381s, Controllers1.032s. Zeiten sind Wandzeiten,
keine CPU-Prozente. Debug-CMake unverändert -g OHNE Optimierung; Produktion
benötigt gesonderten optimierten Build/Lasttest, keine1,000Bot-Freigabe behaupten.
Hauptursache gemessen: Flugkostenbewertung im Graphen (21,456Calls,292.767ms
von355.109ms warmer Suche). Scoped Flight-Planning-Snapshot reduziert wiederholte
Config-/Profilabfragen auf einmal pro Suche; exakte binäre Gebietsschlüssel
statt float-Textformatierung. Native tatsächliche Start-/Lizenz-/Gebietsregeln
bleiben wirksam. Spätere ähnliche20k-Calls-Suchen34..37ms Flugbewertung, ca100ms
Gesamtsuche. Kalte Terrain-/Loginvorgänge können weiterhin Einzelspitzen erzeugen.
Weitere Änderungen: ClientlessGraphProbeCache erfolgreiche statische feste MMAP-
Verbindungen (Map/Instanz/Richtung/exakteKoordinaten), max32768, Graph-Reload leert;
max4096 feste Graphnachbarschaften als Würfel-Superset mit allen bisherigen
Radius/Sperrlisten/Wegeprüfungen. Nur innerhalb EINER Suche Startpfade teilen,
auch über Suchtiers; keine globalen Playerpfade/negativen/transienten Proben.
Reisefehlerbackoff2..30s mit Jitter, neuer Intent setzt Retry zurück, Zeitblock-
Deadline unverändert, Kampf und Benachrichtigungen nicht verzögert. Verhindert
beobachtete heiße Schleifen mit>50Fehlzielen innerhalb weniger Minuten.
CPC_PERF alle30s + CPC_ROUTE für Suchanfragen>=50ms bleiben als Diagnose.
Alle86 Clientless-Tests bestanden, /tmp/vcore-performance-retry-tests.log,
inklusive neuer Cache-/Retry-/Scoped-Planning-/Koordinaten-/Routenregressionen,
16parallel schreibenden Mapworker-Notifications und native Masterpfade. Gameplay-
Abnahme und produktionsnaher optimierter Lasttest bleiben getrennt offen.
Bot/Lua/Player-Manager bleiben Worldthread-eigen; native Mapjobs parallel, einzelne
Map weiterhin seriell. Kein blindes Parallelisieren geteilter Zustände.
---
# Performance-Fortschritt: Cache/Mapworker bereit, Vergleich noch offen
Interne Baseline-CPC_PERF bestätigt Actions als Engpass:16Bots/31.923s Fenster
24.381s Actions,1.032s Controllers,27ms Perception. Bei20Bots nur10Ticks/31.537s,
27.872s Actions. Bei59Bots12Ticks/32.301s,26.331s Actions. Baseline-Logs
/tmp/vcore-perf-baseline-start1.log und derzeitiges Server.log (vor Neustart sichern).
Implementiert: ClientlessGraphProbeCache.h, maximal32768 erfolgreiche statische
MMAP-Proben, genaue Floatbits/direktional/Map-/Instanzschlüssel. Keine Playerpfade,
Detour-Pointer, negativen/unvollständigen/transienten Ergebnisse speichern.
In PlanAdaptiveRoute nur zukünftige feste Graphpunkte. Aktuelle Einstiegswege
und alle ausführenden Wegprüfungen bleiben nativ. Reload leert Cache.
Zusätzlich maximal4096 Graph-Nachbarschaften nach Ausgangsknoten/Radius; Würfel-
Superset, ursprüngliche genaue Radius-/Sperrlisten-/Pfadregeln bleiben aktiv.
CPC_ROUTE-Trace für Suchanfragen>=50ms mit Gesamt-/Navzeit/Probezahl/Cachehits.
Cache-Unit, Produktionsplaner (kalte/warme identische Route, weniger Proben,
Sperrlisten und Cacheleerung), 16-Thread-Damage-Handoff erfolgreich. Social-Handoff
und Gruppenreise zielgerichtet laufen/Ergebnisse prüfen. Baseline-Build cache1
war erfolgreich; aktueller abschließender cache2-Build enthält zusätzliche
Routenzeiten: /tmp/vcore-performance-cache-build2.log, Session65518, vorher
pgrep ninja vor weiterem Build! Native Baseline-Server204663 vollständig beendet.
Testconfig MapUpdate.Threads=4 gesetzt (vorher1), Netzwerk unverändert1; nur
Testserver, Produktion unverändert. Noch NICHT installiert/neu gestartet.
Nächster Schritt: Build/Tests fertig prüfen, installieren, frisch starten,
Ready/Port/4Mapworker prüfen. CPC_PERF/CPC_ROUTE und CPU-Deltas nach Cache-Warmup
bei dokumentierter Botzahl vergleichen. Noch KEINE Verbesserung behaupten;
falls Navigation nicht dominant im CPC_ROUTE-Trace, weiteren Engpass messen.
Alle früheren WIP erhalten, kein Commit/Push, keine Subagents.
---
# Aktuell: Performance/Mehrkern-Optimierung in Arbeit
Nutzer beauftragt Verbesserung der Last/CPU-Verteilung für spätere Produktion.
Alle vorherigen uncommitteten Arthoran/Worgen/PvP/LFG-Änderungen bewahren.
Branch feature/clientless-player-core geprüft. Keine Subagents erlaubt; kein Push.
Baseline vor Änderungen PID201380: Hauptthread95.1% eines logischen Kerns,
Mapworker9.9%,12logische CPUs. MapUpdate.Threads=1,Network.Threads=1.
CMake Debug mit -g OHNE -O; Produktionslast dadurch nicht direkt ableitbar.
perf und gdb attach durch OS-Rechte gesperrt, sudo -n ebenfalls nicht verfügbar.
Keine OS-Rechte geändert. Stattdessen gezielte Laufzeitmessung eingeführt.
ClientlessPlayerMgr.cpp Update misst Travel/Perception/Transport/Flight/Actions/
Controllers inklusive Online-Initialisierung, protokolliert CPC_PERF alle30s
mit Fensterdauer, Tickzahl, Botzahl und langsamstem Einzelcontroller.
Build /tmp/vcore-performance-instrument-build.log erfolgreich und installiert.
Alter Server201380 vollständig beendet. Aktueller Baseline-Start läuft unter
tmux vcore-worldserver, /tmp/vcore-perf-baseline-start1.log. Readiness/Port und
erste CPC_PERF-Fenster jetzt prüfen; noch keine Optimierung/Mehrkern-Config geändert.
Loader bleibt50/5/50/5;110 gespeicherte Bots. Frühere Gruppenfindung bis01:00,
Helfer war zuletzt nicht mehr aktiv; Vergleichslast sorgfältig dokumentieren.
Nächste Schritte: Messfenster auswerten, gezielt teuerste Arbeit verbessern,
sichere Mapworker-Konfiguration prüfen. Bot/Lua/Player-Manager nicht blind parallel
aufrufen! Welt-/Mapthread-Grenzen beibehalten. TravelGraph-Routing enthält sehr
teure zukünftige Punkt-zu-Punkt-MMAP-Brücken und ForwardEntry-Probes; Cache bisher
nur pro einzelner Suchanfrage (validBridgeLengths/rejectedBridges). Falls Messung
Actions bestätigt, positiver geometrischer Cache über Anfragen mit Graph-Reload-
Invalidierung/Instanzschlüssel sinnvoll; keine transienten negativen Ergebnisse
unbegrenzt speichern. Noch NICHT implementiert. Nach Änderungen sinnvoll testen,
bauen/installieren/neustarten und Last mit Botzahl/Fenster/Debug-Einschränkung
vergleichen. Keine ungemessenen Prozentverbesserungen behaupten.
---
# Aktuell: Korrektur auf nativen SucheNachGruppe-Kanal
Nutzer korrigiert: SucheNachGruppe ist eingebauter automatisch betretenener
Hauptstadtkanal; vorheriger /join-Hinweis und Ersatzkanal waren falsch.
Lokale deDE ChatChannels.dbc bestätigt ID26, NameSucheNachGruppe, Flags262201.
AdventureGroupMgr.Speak jetzt Lookup26 + native Zonenberechtigung und
GetJoinChannel(entry->ID,"",zone), tatsächlichen Beitritt vor Say überprüfen.
Kein benutzerdefinierter reservierter Kanal mehr. Bestehende Limits erhalten.
Aktive Testconfig Channel.RestrictedLfg von1 auf0 gesetzt und reload config
bereits ausgeführt; bisheriger NativeCode wies gruppierte normale Accounts
beim LFG-Beitritt ab (GM/RBAC-Ausnahmen beachten). Keine Änderung allgemeiner
Player-/Client-Joinlogik. Clientanzeige nach Stadtwechsel/Relog noch abnehmen.
Doku worgen-recruitment.md korrigiert, frühere Customkanal-Angaben historisch.
Neuer echter Speak-Adaptertest test_adventure_native_lfg.py besteht: ID26,
Zonenberechtigung, Joinbestätigung, Cooldown. test_adventure_groups.py ebenfalls
bestanden. Abschließender Build2 /tmp/vcore-native-lfg-build2.log erfolgreich und installiert.
Vorheriger Testworldserver197361 vollständig beendet. Neuer Server PID201380,
/tmp/vcore-native-lfg-start1.log; frische ready-Meldung in aktuellem Server.log,
Port8085 LISTEN, Prozess stabil bestätigt. Config RestrictedLfg=0 bestätigt.
Gruppenfindungs-Helfer mit vorhandener01:00 Deadline wieder gestartet, Log
/tmp/vcore-groupfinding-native-lfg.log; Arthoran26 bereits vorbereitet.
Clientanzeige/echter Nachrichtenempfang noch nicht visuell abgenommen. Kein
Commit/Push; alle vorigen Arthoran/Worgen/PvP-WIP erhalten. Branch geprüft.
---
# Aktuell: Worgen, aktive Gruppenfindung und PvP implementiert
Nutzer beauftragte Worgengestalten/Reittiere, Vorbereitungs-Mikroaktionen,
Kapital-Suchchat und aktive Spielereinladungen mit vorheriger Zielinfo sowie
permanentes freiwilliges PvP. Schiffspositionen ausdrücklich unverändert lassen.
Vorherige uncommittete Arthoran-Änderungen vollständig erhalten. Kein Commit/Push.
Branch feature/clientless-player-core, letzter Commit cac4142ec1.
Doku doc/clientless/worgen-recruitment.md.
ClientlessLuaEngine.UpdateWorldPresence pflegt native PvP-Wunsch-/Playerflags,
Worgen nach Intent/Kampf/Instanz und zufälliger ruhiger Ankunft, sichere verzögerte
Wechsel mit5s Retry, Zustand bei Logout gelöscht. PrepareGroundMount verwendet
native Wilde Hatz87840 bei Worgengestalt, Pferd2404/Zauber458 in Menschengestalt;
Dismount entfernt Aura. Neue generierte Worgenprofile Pferde statt Volkspferde;
alte leere Mount-Dictionaries bekommen funktionierenden Lauf-/Pferdefallback.
Gruppenfindung beendet nicht länger Mikroaktionen vorzeitig; zusätzliche SQL-
Migration2026_10_29_01_adventure_group_preparation.sql bereits in Test-WorldDB
angewendet (SQL-Pfad ignoriert, per git add -N -f zur Nachverfolgung aufgenommen).
Vorbereitung/Suchwege lokal mit18Y Pathbudget, auch innen. GroupMgr announciert
nächsten Intent + tatsächliches Ziel im vorhandenen sucheNachGruppe-Kanal,
max1 Nachricht/15s populationsweit und3..5min pro Werber. Spieler müssen Kanal
beitreten. Nahe passende Menschen werden mit vorherigem Whisper eingeladen;
10min Cooldown pro Mensch populationsweit. Native Gruppe/Einladung/Kapazität,
Fraktion/Sicht/AFK/Kampf/Reiseschutz und bisherige Spielerführung beibehalten.
Build4 /tmp/vcore-worgen-recruitment-build4.log erfolgreich, installiert;
Testserver nach vollständigem Stopp frisch gestartet. PID197361, tmux
vcore-worldserver, /tmp/vcore-worgen-recruitment-start1.log. Frische ready-Meldung,
Port8085 LISTEN und Prozess stabil bestätigt. Loader aktiv50/5/50/5;110 gespeicherte
Bots vorhanden, Online-Aufbau läuft. Native gespeicherte PvP-Wunschflags bei
Arthoran26/Aelion29/Zanzan30/Lenara31 jeweils1. Worgen31/38 Pferd458+ZweiGestalten68996
in Spellbook bestätigt; native Script-Zuordnung87840/68996 überprüft.
Regression /tmp/vcore-worgen-recruitment-tests.log:82/83 erfolgreich, einzig alter
intent_state-Adapter fehlte neuer Lua-Ankunftsaufruf. Adapter ergänzt, Einzeltest
anschließend bestanden. Neues world_presence und erweiterte groups/leisure Tests
anschließend bestanden, einschließlich begrenzter Innenraum-Suchwege, menschlicher
Einladung/Zieltext/Abklingzeit, Gestalt in Kampf/Mischinstanzen und Mount-Aura-Cleanup.
Keine visuelle Abnahme von Chat/Morph/Einladung behaupten; native Kanal-/Micro-
Logs waren in erster Ramp-up-Stichprobe noch nicht aufgetreten (Bots reisen).
Vorherige Gruppenfindungs-Deadline00:00 war abgelaufen. Für fortgesetzten Test nach
Neustart gemeinsame Deadline auf01:00 Europe/Berlin (1793232000) gesetzt. Helfer
/tmp/vcore-groupfinding-setup.py läuft weiter, Log /tmp/vcore-groupfinding-worgen.log,
Manifest /tmp/vcore-groupfinding-test.json. Neue online Bots automatisch vorbereiten,
bei110 online stoppt Helfer; DB-Transienten werden erneut versucht. Nicht parallel
starten! Früheres Manifest /tmp/vcore-groupfinding-test-first-block.json gesichert.
Native performative Instanzaufenthalte können sichere Übergabe noch verzögern.
Kein Push/Commit beauftragt. Gameplay-Tankverhalten/Schiffe bleiben gesondert offen.
---
# Aktuell: Arthoran in normale persistente Verwaltung übernommen
Auftrag: Arthoran normaler AdventureBot, Krieger60, Gruppenrolle Tank,
Tavernen/Geselligkeit stärker gewichten als Abenteuer, keinem Kampf ausweichen.
Branch feature/clientless-player-core; Ausgangscommit cac4142ec1. Bereits
vorhandene Änderung dieses Dokuments gehört zum Lasttest und wurde bewahrt.
arthoran.lua jetzt ProfileVersion2, Level60/Class1, SchutzSpec2/Tank, SoloArms0,
Tagesplan aktiv, Elwynn/Sturmwind Heimat, verstärkte Tavernen-/Sozialgewichte,
Aggression1/DangerTolerance1, behavior.allow_retreat=false. Neue optionale
AllowRetreat-Eigenschaft (Defaulttrue) beendet Flucht bei ausdrücklicher Ablehnung;
Gruppenflucht weiterhin aus. Normale CPC-Infrastruktur unverändert.
Generator Reconcile/ProtectedEquipment/PrepareCombat und Population.Online lassen
vollständige v2-Dateiprofile wie generierte Profile verwalten; Legacy-Profile
bleiben unverändert. Arthoran26 explizit in CharacterDB-Registry übernommen,
persistent/ready/warrior/seed26, eigener Lua-Profiltext ebenfalls gesichert.
Kein neuer Charakter, keine Level-/Klassenumwandlung. Backup des Zustands/Inventars
vorher /tmp/vcore-arthoran-before-adoption.tsv. 26 zählt zur Allianz-Persistentquote.
PvP-Frage geprüft: kein erzwungenes PvP in Adventure-Lifecycle; zuletzt0/96
Registry-Bots CHARACTER_FLAG_PVP_DESIRED gesetzt, ebenso Arthoran nicht. Native
Kampf-/Gebietsflagging bleibt. Globale PvP-Einstellung NICHT verändert.
Build /tmp/vcore-arthoran-managed-build.log erfolgreich und installiert. Betroffene
Tests combat_reactions (zusätzlich ausdrückliches Fluchtverbot), population
(zusätzlich benanntes v2-Profil vs Legacy/unvollständig), combat_preparation,
profile_selection, profession_profile erfolgreich. Bisheriger Server183811
vollständig beendet; Neustart /tmp/vcore-arthoran-managed-start1.log.
Startbereitschaft bestätigt (frische ready-Meldung, PID191926, Port8085 LISTEN).
Arthoran26 online/persistent/ready, Level60/Class1, SoloArms-Talentbaum746,
103 Zauber,14 gelernte Talentzauber, Zweihandwaffe31134. Tankrolle/SchutzSpec2
im Profil; tatsächlicher Gruppen-Tankwechsel noch nicht im Spiel abgenommen.
Erste Reconcile-Prüfung scheiterte am alten Mining-Lehrzauber ohne Fertigkeit.
26 nativ ausgeloggt, ausschließlich fehlende Skills186/164 mit375/375 im Offline-
Zustand ergänzt, nativ neu eingeloggt; danach Reconcile ohne neue Fehlermeldung.
Mining nativ auf450 erhöht, Blacksmith375; bestehende Nebenskills erhalten.
Gruppenfindung für26 erneut bis00:00 angefordert; sichere Übergabe aus Social
kann noch laufen. Kein Gameplay-Tanktest behaupten.
Gruppenfindungs-Setup hatte wegen temporärem DB-TLS-Reset angehalten. Native
DB-Query-Retry ergänzt, nach Neustart Manifest prepared zurückgesetzt und Setup
wieder gestartet: /tmp/vcore-groupfinding-resume.log; ursprüngliche Deadline
00:00 beibehalten. Laufenden Setup-Prozess nicht doppelt starten! Loader aktiv
50/5/50/5; keine anderen Nutzercharaktere übernommen. Kein Commit/Push beauftragt.
---
# Aktiver Test: Gruppenfindung für Lasttestpopulation
Nutzer fordert alle Bots zunächst in Gruppenfindung, danach Instanz/Raid;
keine C++-Änderung. Vorhandenes natives `clientless adventure prepare` verwendet,
keine Lua-/Profiländerung nötig. Aufruf pro online Bot: prepare <guid> <next>
<meeting> <seconds>. Allianz poi_guard_22 (Sturmwind), Horde poi_guard_179
(Orgrimmar), Level>=60 raid, darunter instance. Gemeinsame Deadline nächste
volle Stunde: 2026-10-29 00:00 Europe/Berlin (epoch1793228400), danach1h Folgeintent.
Bestehende Kampf-/Tod-/Reiseübergaben bleiben aktiv. Test überschreibt den
aktiven Ablauf (schedule=0), gespeicherte normale Tagespläne/Profilwerte bleiben
erhalten. Nach Test mit `clientless adventure schedule <guid> on` zurückstellen.
Setup /tmp/vcore-groupfinding-setup.py, Log /tmp/vcore-groupfinding-setup.log,
Manifest /tmp/vcore-groupfinding-test.json. Pollt neue online generierte Bots
alle10s bis mindestens110 online, höchstens30min bzw. vor Deadline. Nicht doppelt
starten oder Manifest überschreiben. Bisher80 native prepare-Erfolgsbestätigungen; Aelion29, Lenara31 und Karggan35
melden groupformation + next=raid. Zuletzt80 online (35/5/35/5),
Loader noch busy beim weiteren Erzeugen, kein Loaderfehler. Setup läuft weiter;
110er Abschluss noch nicht bestätigt. Finales Manifest/Bestätigungen prüfen. Kein Push/Commit beauftragt.
---
# Aktuell: Gemeinsame Gruppenreisen implementiert
Auftrag: Spieler- und Botgruppen mit sicheren Formationen, Reittieren, freiem
@@ -22,7 +290,10 @@ mit bestehender CMake-Konfiguration erfolgreich; vorheriger Server vollständig
beendet. Neuer Start läuft: /tmp/vcore-group-travel-start1.log, PID183811,
tmux vcore-worldserver. Startbereitschaft bestätigt: frische ready-Meldung, Prozess stabil, Port8085
LISTEN. Loader24 online,10/2/10/2, pending0, error leer.
Loader muss weiterhin aktiv mit10 persistent+2 temporär je Fraktion bleiben.
Aktueller Lasttestauftrag: Loader aktiv mit50 persistent+5 temporär je Fraktion
(Soll110). Aktive worldserver.conf angepasst und reload config sowie
clientless population reload ausgeführt; Zielwerte50/5/50/5 bestätigt.
Population wird schrittweise aufgefüllt; frühere24er Angaben sind historisch.
Native Spielerreisen und visuelle Formation sind noch nicht im Spiel abgenommen.
Unbekannte/scriptgesteuerte Portale oder fehlende Serviceaufzeichnungen werden
@@ -0,0 +1,13 @@
CPC_PERF windowMs=31708 ticks=879 players=7 travelMs=0.484 perceptionMs=4.428 transportMs=0.144 flightMs=2.252 actionsMs=16067.435 controllersMs=269.654 slowGuid=26 slowMs=121.738
CPC_PERF windowMs=31923 ticks=313 players=16 travelMs=11.469 perceptionMs=27.059 transportMs=0.140 flightMs=0.126 actionsMs=24381.331 controllersMs=1032.270 slowGuid=42 slowMs=397.391
CPC_PERF windowMs=31537 ticks=10 players=20 travelMs=17.874 perceptionMs=13.710 transportMs=0.028 flightMs=0.027 actionsMs=27872.181 controllersMs=294.503 slowGuid=44 slowMs=58.861
CPC_PERF windowMs=30370 ticks=170 players=32 travelMs=29.956 perceptionMs=75.262 transportMs=0.130 flightMs=0.141 actionsMs=20011.291 controllersMs=1036.558 slowGuid=50 slowMs=75.739
CPC_PERF windowMs=32064 ticks=207 players=43 travelMs=29.812 perceptionMs=120.900 transportMs=0.254 flightMs=0.286 actionsMs=21126.712 controllersMs=1134.949 slowGuid=70 slowMs=44.644
CPC_PERF windowMs=32397 ticks=22 players=54 travelMs=35.146 perceptionMs=107.803 transportMs=0.055 flightMs=0.056 actionsMs=25415.937 controllersMs=1086.701 slowGuid=75 slowMs=150.957
CPC_PERF windowMs=32301 ticks=12 players=59 travelMs=25.198 perceptionMs=76.121 transportMs=0.030 flightMs=0.040 actionsMs=26331.046 controllersMs=697.158 slowGuid=40 slowMs=62.984
CPC_PERF windowMs=31515 ticks=8 players=66 travelMs=31.520 perceptionMs=702.414 transportMs=0.501 flightMs=0.235 actionsMs=17198.952 controllersMs=2651.010 slowGuid=43 slowMs=349.990
CPC_PERF windowMs=31835 ticks=4 players=68 travelMs=89.253 perceptionMs=265.259 transportMs=0.011 flightMs=0.013 actionsMs=15172.937 controllersMs=1872.802 slowGuid=93 slowMs=267.053
CPC_PERF windowMs=33394 ticks=7 players=72 travelMs=21.174 perceptionMs=203.776 transportMs=0.423 flightMs=0.019 actionsMs=24499.114 controllersMs=867.084 slowGuid=96 slowMs=73.350
CPC_PERF windowMs=31643 ticks=9 players=80 travelMs=38.652 perceptionMs=120.948 transportMs=0.135 flightMs=0.383 actionsMs=20782.250 controllersMs=2069.232 slowGuid=100 slowMs=707.549
CPC_PERF windowMs=34049 ticks=5 players=81 travelMs=24.132 perceptionMs=73.970 transportMs=0.129 flightMs=0.015 actionsMs=26621.404 controllersMs=894.816 slowGuid=106 slowMs=53.148
CPC_PERF windowMs=34358 ticks=6 players=86 travelMs=24.375 perceptionMs=82.137 transportMs=0.501 flightMs=0.017 actionsMs=24773.949 controllersMs=2714.716 slowGuid=80 slowMs=595.751
@@ -0,0 +1,28 @@
[1/16] cd /home/wow_admin/wow_cata_server/source/TrinityCore && /usr/bin/cmake -DBUILDDIR="/home/wow_admin/wow_cata_server/build/debug" -P /home/wow_admin/wow_cata_server/source/TrinityCore/cmake/genrev.cmake /home/wow_admin/wow_cata_server/build/debug
[2/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureLocationMgr.cpp.o
[3/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureEncounterMgr.cpp.o
[4/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureInteractionMgr.cpp.o
[5/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureGroupMgr.cpp.o
[6/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventurePopulationMgr.cpp.o
[7/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureSocialActions.cpp.o
[8/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureSupplyMgr.cpp.o
[9/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureCombatMgr.cpp.o
[10/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureGeneratorMgr.cpp.o
[11/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/AdventureBehaviorMgr.cpp.o
[12/16] Building CXX object src/server/game/CMakeFiles/game.dir/World/ClientlessLuaEngine.cpp.o
[13/16] Building CXX object src/server/scripts/CMakeFiles/scripts.dir/Custom/viano_bot_commands.cpp.o
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationAdd(ChatHandler*, const char*)’:
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2352:20: warning: unused variable ‘loaded’ [-Wunused-variable]
2352 | bool const loaded = sClientlessWorldPointMgr->Reload();
| ^~~~~~
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationMove(ChatHandler*, const char*)’:
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2389:20: warning: unused variable ‘loaded’ [-Wunused-variable]
2389 | bool const loaded = sClientlessWorldPointMgr->Reload();
| ^~~~~~
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp: In function ‘bool VianoBotCommands::HandleClientlessLocationRemove(ChatHandler*, const char*)’:
/home/wow_admin/wow_cata_server/source/TrinityCore/src/server/scripts/Custom/viano_bot_commands.cpp:2413:20: warning: unused variable ‘loaded’ [-Wunused-variable]
2413 | bool const loaded = sClientlessWorldPointMgr->Reload();
| ^~~~~~
[14/16] Linking CXX static library src/server/game/libgame.a
[15/16] Linking CXX static library src/server/scripts/libscripts.a
[16/16] Linking CXX executable src/server/worldserver/worldserver
@@ -0,0 +1,19 @@
{
"pid": 214924,
"window_seconds": 10.068513992999215,
"logical_cpus": 12,
"threads_percent_of_one_cpu": {
"214924": 26.2,
"214927": 0.0,
"214928": 0.0,
"214929": 0.0,
"214933": 0.9,
"214936": 0.0,
"215050": 38.6,
"215051": 37.6,
"215052": 38.1,
"215053": 38.5,
"215054": 1.4,
"215055": 0.0
}
}
@@ -0,0 +1,20 @@
TrinityCore rev. cac4142ec1f9+ 2026-10-28 23:30:28 +0100 (feature/clientless-player-core branch) (Unix, Debug, Static) (worldserver-daemon)
World initialized in 0 minutes 11 seconds
TrinityCore rev. cac4142ec1f9+ 2026-10-28 23:30:28 +0100 (feature/clientless-player-core branch) (Unix, Debug, Static) (worldserver-daemon) ready...
Adventure loader enabled=1 schema=1 busy=0 pools=50/5/50/5 known=110 rotations=0 manager=50 error=''
pool=0 faction=alliance persistent=1 target=50 online=21 pending=0 saved=50
pool=1 faction=alliance persistent=0 target=5 online=5 pending=0 saved=5
pool=2 faction=horde persistent=1 target=50 online=20 pending=0 saved=50
pool=3 faction=horde persistent=0 target=5 online=5 pending=0 saved=5
TC>Adventure loader enabled=1 schema=1 busy=0 pools=50/5/50/5 known=110 rotations=0 manager=94 error=''
pool=0 faction=alliance persistent=1 target=50 online=42 pending=0 saved=50
pool=1 faction=alliance persistent=0 target=5 online=5 pending=0 saved=5
pool=2 faction=horde persistent=1 target=50 online=42 pending=0 saved=50
pool=3 faction=horde persistent=0 target=5 online=5 pending=0 saved=5
TC>Adventure loader enabled=1 schema=1 busy=0 pools=50/5/50/5 known=110 rotations=0 manager=110 error=''
pool=0 faction=alliance persistent=1 target=50 online=50 pending=0 saved=50
pool=1 faction=alliance persistent=0 target=5 online=5 pending=0 saved=5
pool=2 faction=horde persistent=1 target=50 online=50 pending=0 saved=50
pool=3 faction=horde persistent=0 target=5 online=5 pending=0 saved=5
PID214924 remains running, TCP8085 LISTEN.
MapUpdate.Threads=4, Network.Threads=1.
@@ -0,0 +1,560 @@
CPC_ROUTE target='taxi_456' totalMs=2105.169 navMs=1.184 probes=41 cacheHits=2 cacheSize=34 startMs=0.655 startCalls=2 flightMs=2030.334 flightCalls=21457
CPC_ROUTE target='taxi_456' totalMs=107.186 navMs=0.374 probes=7 cacheHits=36 cacheSize=34 startMs=0.613 startCalls=2 flightMs=36.226 flightCalls=21456
CPC_ROUTE target='taxi_456' totalMs=106.400 navMs=0.353 probes=7 cacheHits=35 cacheSize=34 startMs=0.760 startCalls=2 flightMs=35.953 flightCalls=21079
CPC_ROUTE target='taxi_456' totalMs=110.871 navMs=1.564 probes=27 cacheHits=35 cacheSize=46 startMs=0.587 startCalls=2 flightMs=36.327 flightCalls=22018
CPC_ROUTE target='taxi_456' totalMs=113.010 navMs=1.690 probes=19 cacheHits=47 cacheSize=67 startMs=0.577 startCalls=2 flightMs=35.992 flightCalls=22582
CPC_ROUTE target='taxi_456' totalMs=112.903 navMs=1.734 probes=19 cacheHits=47 cacheSize=67 startMs=0.585 startCalls=2 flightMs=35.525 flightCalls=22581
CPC_ROUTE target='portal_at_2530_target' totalMs=104.526 navMs=0.371 probes=7 cacheHits=37 cacheSize=67 startMs=0.537 startCalls=1 flightMs=36.092 flightCalls=20893
CPC_ROUTE target='goldshire_center' totalMs=3187.008 navMs=4.050 probes=66 cacheHits=64 cacheSize=94 startMs=55.222 startCalls=7 flightMs=2969.975 flightCalls=52524
CPC_ROUTE target='taxi_181' totalMs=110.979 navMs=0.493 probes=11 cacheHits=41 cacheSize=98 startMs=0.619 startCalls=2 flightMs=36.173 flightCalls=22329
CPC_ROUTE target='taxi_181' totalMs=263.941 navMs=7.715 probes=154 cacheHits=121 cacheSize=139 startMs=0.710 startCalls=2 flightMs=65.081 flightCalls=64572
CPC_ROUTE target='taxi_181' totalMs=262.019 navMs=6.961 probes=113 cacheHits=162 cacheSize=141 startMs=0.602 startCalls=2 flightMs=62.437 flightCalls=64571
CPC_ROUTE target='taxi_181' totalMs=128.702 navMs=2.860 probes=41 cacheHits=72 cacheSize=141 startMs=0.735 startCalls=2 flightMs=35.746 flightCalls=26996
CPC_ROUTE target='taxi_181' totalMs=266.560 navMs=6.929 probes=113 cacheHits=162 cacheSize=141 startMs=0.722 startCalls=2 flightMs=63.395 flightCalls=64381
CPC_ROUTE target='taxi_181' totalMs=267.246 navMs=6.971 probes=114 cacheHits=162 cacheSize=142 startMs=0.722 startCalls=2 flightMs=62.364 flightCalls=64756
CPC_ROUTE target='portal_at_5379_source' totalMs=964.010 navMs=25.702 probes=2206 cacheHits=444 cacheSize=227 startMs=0.980 startCalls=3 flightMs=295.552 flightCalls=205764
CPC_ROUTE target='goldshire_center' totalMs=227.882 navMs=2.788 probes=37 cacheHits=90 cacheSize=227 startMs=5.959 startCalls=16 flightMs=63.046 flightCalls=52277
CPC_ROUTE target='taxi_388' totalMs=106.705 navMs=0.351 probes=7 cacheHits=36 cacheSize=227 startMs=0.588 startCalls=2 flightMs=35.332 flightCalls=21457
CPC_ROUTE target='taxi_388' totalMs=105.893 navMs=0.360 probes=7 cacheHits=36 cacheSize=227 startMs=0.589 startCalls=2 flightMs=34.586 flightCalls=21456
CPC_ROUTE target='taxi_388' totalMs=106.071 navMs=0.351 probes=7 cacheHits=35 cacheSize=227 startMs=0.713 startCalls=2 flightMs=34.931 flightCalls=21079
CPC_ROUTE target='taxi_388' totalMs=111.333 navMs=1.514 probes=15 cacheHits=47 cacheSize=227 startMs=0.699 startCalls=2 flightMs=34.963 flightCalls=22017
CPC_ROUTE target='taxi_388' totalMs=113.074 navMs=1.713 probes=19 cacheHits=47 cacheSize=227 startMs=0.709 startCalls=2 flightMs=34.564 flightCalls=22581
CPC_ROUTE target='taxi_395' totalMs=538.346 navMs=10.513 probes=856 cacheHits=251 cacheSize=227 startMs=0.000 startCalls=0 flightMs=248.340 flightCalls=89377
CPC_PERF windowMs=30296 ticks=2534 players=9 travelMs=2.539 perceptionMs=8.129 transportMs=0.198 flightMs=3.132 actionsMs=9829.145 controllersMs=438.308 slowGuid=26 slowMs=122.949
CPC_ROUTE target='goldshire_center' totalMs=246.250 navMs=3.272 probes=39 cacheHits=91 cacheSize=227 startMs=2.939 startCalls=7 flightMs=80.862 flightCalls=52524
CPC_ROUTE target='taxi_128' totalMs=621.379 navMs=12.087 probes=920 cacheHits=454 cacheSize=227 startMs=2.841 startCalls=16 flightMs=271.062 flightCalls=102683
CPC_ROUTE target='taxi_388' totalMs=103.128 navMs=0.372 probes=7 cacheHits=36 cacheSize=227 startMs=0.743 startCalls=2 flightMs=34.677 flightCalls=20329
CPC_ROUTE target='taxi_388' totalMs=103.549 navMs=0.352 probes=7 cacheHits=36 cacheSize=227 startMs=0.744 startCalls=2 flightMs=34.605 flightCalls=20328
CPC_ROUTE target='taxi_388' totalMs=102.574 navMs=0.362 probes=7 cacheHits=35 cacheSize=227 startMs=0.704 startCalls=2 flightMs=34.226 flightCalls=19951
CPC_ROUTE target='taxi_388' totalMs=103.285 navMs=0.688 probes=8 cacheHits=38 cacheSize=227 startMs=0.713 startCalls=2 flightMs=34.058 flightCalls=19950
CPC_ROUTE target='taxi_388' totalMs=106.172 navMs=0.977 probes=9 cacheHits=41 cacheSize=227 startMs=0.729 startCalls=2 flightMs=34.820 flightCalls=20325
CPC_ROUTE target='taxi_388' totalMs=109.921 navMs=1.778 probes=18 cacheHits=47 cacheSize=227 startMs=0.610 startCalls=2 flightMs=34.559 flightCalls=21452
CPC_ROUTE target='goldshire_center' totalMs=2274.889 navMs=2.838 probes=35 cacheHits=90 cacheSize=227 startMs=184.012 startCalls=16 flightMs=1931.143 flightCalls=52028
CPC_ROUTE target='taxi_128' totalMs=2140.725 navMs=11.794 probes=920 cacheHits=444 cacheSize=229 startMs=1.435 startCalls=15 flightMs=1798.710 flightCalls=102683
CPC_ROUTE target='portal_at_4367_target' totalMs=602.221 navMs=12.423 probes=937 cacheHits=264 cacheSize=229 startMs=1.837 startCalls=3 flightMs=256.800 flightCalls=97847
CPC_ROUTE target='taxi_128' totalMs=623.249 navMs=12.523 probes=920 cacheHits=444 cacheSize=229 startMs=1.065 startCalls=15 flightMs=267.029 flightCalls=102683
CPC_ROUTE target='taxi_388' totalMs=126.011 navMs=2.660 probes=40 cacheHits=70 cacheSize=229 startMs=0.596 startCalls=2 flightMs=35.603 flightCalls=26999
CPC_ROUTE target='taxi_388' totalMs=128.763 navMs=3.002 probes=41 cacheHits=73 cacheSize=229 startMs=0.576 startCalls=2 flightMs=36.126 flightCalls=27186
CPC_ROUTE target='taxi_388' totalMs=118.621 navMs=1.516 probes=26 cacheHits=63 cacheSize=229 startMs=0.732 startCalls=2 flightMs=36.762 flightCalls=23837
CPC_ROUTE target='taxi_388' totalMs=127.143 navMs=2.823 probes=41 cacheHits=72 cacheSize=229 startMs=0.727 startCalls=2 flightMs=35.044 flightCalls=26808
CPC_ROUTE target='taxi_388' totalMs=131.725 navMs=3.246 probes=45 cacheHits=73 cacheSize=229 startMs=0.707 startCalls=2 flightMs=35.744 flightCalls=27748
CPC_ROUTE target='taxi_388' totalMs=118.326 navMs=1.764 probes=21 cacheHits=58 cacheSize=229 startMs=0.727 startCalls=2 flightMs=34.913 flightCalls=24018
CPC_PERF windowMs=30023 ticks=709 players=18 travelMs=17.383 perceptionMs=19.454 transportMs=0.106 flightMs=0.134 actionsMs=8078.631 controllersMs=871.467 slowGuid=42 slowMs=357.761
CPC_ROUTE target='goldshire_center' totalMs=240.435 navMs=3.141 probes=39 cacheHits=91 cacheSize=229 startMs=2.640 startCalls=7 flightMs=78.815 flightCalls=52524
CPC_ROUTE target='goldshire_center' totalMs=226.239 navMs=2.762 probes=36 cacheHits=91 cacheSize=229 startMs=2.272 startCalls=6 flightMs=64.598 flightCalls=52275
CPC_ROUTE target='goldshire_center' totalMs=226.588 navMs=2.109 probes=34 cacheHits=90 cacheSize=229 startMs=1.972 startCalls=5 flightMs=65.070 flightCalls=52026
CPC_ROUTE target='goldshire_center' totalMs=228.640 navMs=2.101 probes=28 cacheHits=90 cacheSize=229 startMs=1.735 startCalls=4 flightMs=67.339 flightCalls=51775
CPC_ROUTE target='goldshire_center' totalMs=232.947 navMs=1.625 probes=23 cacheHits=89 cacheSize=229 startMs=5.000 startCalls=12 flightMs=65.604 flightCalls=51088
CPC_ROUTE target='portal_at_4367_target' totalMs=593.838 navMs=11.612 probes=937 cacheHits=264 cacheSize=229 startMs=0.985 startCalls=2 flightMs=269.939 flightCalls=97846
CPC_ROUTE target='taxi_36' totalMs=240.035 navMs=2.449 probes=52 cacheHits=130 cacheSize=231 startMs=2.905 startCalls=20 flightMs=67.022 flightCalls=56337
CPC_ROUTE target='portal_at_4367_target' totalMs=605.861 navMs=11.408 probes=937 cacheHits=264 cacheSize=231 startMs=37.511 startCalls=80 flightMs=237.635 flightCalls=97846
CPC_ROUTE target='taxi_36' totalMs=246.040 navMs=2.470 probes=50 cacheHits=135 cacheSize=231 startMs=1.912 startCalls=20 flightMs=71.316 flightCalls=56834
CPC_ROUTE target='taxi_36' totalMs=247.221 navMs=2.455 probes=50 cacheHits=138 cacheSize=231 startMs=2.084 startCalls=20 flightMs=68.534 flightCalls=58327
CPC_ROUTE target='taxi_128' totalMs=633.342 navMs=12.916 probes=920 cacheHits=360 cacheSize=231 startMs=2.727 startCalls=18 flightMs=278.827 flightCalls=102683
CPC_ROUTE target='portal_at_2530_target' totalMs=59.325 navMs=3.073 probes=82 cacheHits=354 cacheSize=231 startMs=3.873 startCalls=17 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=268.470 navMs=2.914 probes=49 cacheHits=132 cacheSize=231 startMs=7.712 startCalls=20 flightMs=85.262 flightCalls=56585
CPC_ROUTE target='portal_at_2530_target' totalMs=51.727 navMs=3.528 probes=87 cacheHits=262 cacheSize=231 startMs=1.734 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=253.735 navMs=2.874 probes=49 cacheHits=132 cacheSize=231 startMs=7.561 startCalls=20 flightMs=69.640 flightCalls=56584
CPC_ROUTE target='taxi_36' totalMs=62.127 navMs=1.555 probes=23 cacheHits=94 cacheSize=231 startMs=35.083 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.383 navMs=1.486 probes=23 cacheHits=94 cacheSize=231 startMs=34.498 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.144 navMs=1.550 probes=23 cacheHits=94 cacheSize=231 startMs=34.727 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=61.085 navMs=1.519 probes=23 cacheHits=94 cacheSize=231 startMs=34.272 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=611.292 navMs=12.282 probes=938 cacheHits=265 cacheSize=231 startMs=2.841 startCalls=4 flightMs=278.524 flightCalls=98342
CPC_ROUTE target='taxi_388' totalMs=138.736 navMs=3.234 probes=65 cacheHits=95 cacheSize=231 startMs=0.618 startCalls=2 flightMs=37.301 flightCalls=29804
CPC_ROUTE target='taxi_388' totalMs=259.508 navMs=6.922 probes=113 cacheHits=162 cacheSize=231 startMs=0.590 startCalls=2 flightMs=62.689 flightCalls=64384
CPC_ROUTE target='taxi_388' totalMs=263.249 navMs=7.041 probes=113 cacheHits=162 cacheSize=231 startMs=0.716 startCalls=2 flightMs=63.342 flightCalls=64383
CPC_ROUTE target='taxi_388' totalMs=265.017 navMs=6.924 probes=113 cacheHits=162 cacheSize=231 startMs=0.593 startCalls=2 flightMs=64.416 flightCalls=64382
CPC_ROUTE target='taxi_388' totalMs=266.288 navMs=6.941 probes=113 cacheHits=163 cacheSize=231 startMs=0.610 startCalls=2 flightMs=63.447 flightCalls=64757
CPC_PERF windowMs=30118 ticks=1418 players=29 travelMs=24.794 perceptionMs=62.862 transportMs=0.237 flightMs=0.344 actionsMs=6960.956 controllersMs=762.444 slowGuid=50 slowMs=73.912
CPC_ROUTE target='taxi_388' totalMs=145.412 navMs=3.532 probes=69 cacheHits=97 cacheSize=231 startMs=0.731 startCalls=2 flightMs=37.331 flightCalls=30929
CPC_ROUTE target='taxi_170' totalMs=615.412 navMs=12.344 probes=1023 cacheHits=264 cacheSize=231 startMs=0.000 startCalls=0 flightMs=267.805 flightCalls=100414
CPC_ROUTE target='taxi_170' totalMs=591.513 navMs=12.174 probes=1023 cacheHits=264 cacheSize=231 startMs=0.000 startCalls=0 flightMs=256.635 flightCalls=100413
CPC_ROUTE target='portal_at_2530_target' totalMs=53.104 navMs=3.413 probes=87 cacheHits=262 cacheSize=231 startMs=2.684 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_170' totalMs=603.082 navMs=12.224 probes=1023 cacheHits=264 cacheSize=231 startMs=0.000 startCalls=0 flightMs=265.445 flightCalls=100412
CPC_ROUTE target='taxi_395' totalMs=63.738 navMs=1.508 probes=41 cacheHits=131 cacheSize=231 startMs=35.349 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=62.178 navMs=1.455 probes=41 cacheHits=131 cacheSize=231 startMs=34.409 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=61.587 navMs=1.387 probes=41 cacheHits=131 cacheSize=231 startMs=34.215 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=64.652 navMs=1.557 probes=23 cacheHits=108 cacheSize=231 startMs=35.797 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.805 navMs=1.442 probes=23 cacheHits=108 cacheSize=231 startMs=35.385 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.519 navMs=1.469 probes=23 cacheHits=108 cacheSize=231 startMs=35.011 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.521 navMs=1.406 probes=23 cacheHits=108 cacheSize=231 startMs=34.715 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=63.872 navMs=1.610 probes=23 cacheHits=108 cacheSize=231 startMs=36.603 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.326 navMs=1.533 probes=23 cacheHits=108 cacheSize=231 startMs=35.314 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.435 navMs=1.384 probes=23 cacheHits=108 cacheSize=231 startMs=35.265 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=511.222 navMs=10.570 probes=856 cacheHits=324 cacheSize=248 startMs=2.238 startCalls=16 flightMs=237.005 flightCalls=91970
CPC_ROUTE target='taxi_310' totalMs=714.972 navMs=35.584 probes=2002 cacheHits=740 cacheSize=326 startMs=2.184 startCalls=14 flightMs=22.116 flightCalls=219968
CPC_ROUTE target='taxi_601' totalMs=160.111 navMs=1.623 probes=18 cacheHits=95 cacheSize=326 startMs=2.760 startCalls=13 flightMs=9.161 flightCalls=54638
CPC_ROUTE target='portal_at_322_target' totalMs=581.553 navMs=1.044 probes=36 cacheHits=136 cacheSize=326 startMs=550.483 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=68.901 navMs=0.949 probes=36 cacheHits=136 cacheSize=326 startMs=39.146 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=68.291 navMs=1.078 probes=36 cacheHits=136 cacheSize=326 startMs=38.211 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=66.096 navMs=1.073 probes=18 cacheHits=102 cacheSize=326 startMs=37.569 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=65.862 navMs=0.810 probes=18 cacheHits=102 cacheSize=326 startMs=37.875 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=63.775 navMs=0.929 probes=18 cacheHits=102 cacheSize=326 startMs=36.774 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=65.413 navMs=0.885 probes=18 cacheHits=102 cacheSize=326 startMs=38.072 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=1808.266 navMs=10.286 probes=839 cacheHits=341 cacheSize=326 startMs=2.632 startCalls=16 flightMs=1519.821 flightCalls=91970
CPC_ROUTE target='taxi_23' totalMs=55.219 navMs=3.549 probes=77 cacheHits=272 cacheSize=326 startMs=1.996 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=76.275 navMs=1.728 probes=36 cacheHits=136 cacheSize=326 startMs=39.016 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=69.649 navMs=1.759 probes=36 cacheHits=136 cacheSize=326 startMs=38.589 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=65.728 navMs=1.711 probes=36 cacheHits=136 cacheSize=326 startMs=36.765 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=63.469 navMs=1.531 probes=36 cacheHits=136 cacheSize=326 startMs=34.879 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_627' totalMs=67.697 navMs=1.632 probes=18 cacheHits=97 cacheSize=326 startMs=39.189 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_503_target' totalMs=1750.862 navMs=1.717 probes=22 cacheHits=113 cacheSize=326 startMs=0.000 startCalls=0 flightMs=1597.391 flightCalls=56075
CPC_PERF windowMs=30001 ticks=4260 players=44 travelMs=42.846 perceptionMs=131.690 transportMs=0.353 flightMs=3.459 actionsMs=10288.297 controllersMs=1106.764 slowGuid=53 slowMs=47.618
CPC_ROUTE target='taxi_23' totalMs=57.022 navMs=3.378 probes=72 cacheHits=272 cacheSize=326 startMs=1.886 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=84.171 navMs=2.019 probes=23 cacheHits=68 cacheSize=326 startMs=0.627 startCalls=2 flightMs=6.628 flightCalls=24975
CPC_ROUTE target='taxi_181' totalMs=84.098 navMs=2.086 probes=23 cacheHits=68 cacheSize=326 startMs=0.603 startCalls=2 flightMs=6.949 flightCalls=24974
CPC_ROUTE target='taxi_181' totalMs=84.063 navMs=2.239 probes=28 cacheHits=70 cacheSize=326 startMs=0.822 startCalls=2 flightMs=6.190 flightCalls=24973
CPC_ROUTE target='taxi_181' totalMs=76.840 navMs=1.423 probes=11 cacheHits=55 cacheSize=326 startMs=0.606 startCalls=2 flightMs=6.739 flightCalls=22642
CPC_ROUTE target='taxi_181' totalMs=88.911 navMs=2.885 probes=32 cacheHits=70 cacheSize=326 startMs=0.656 startCalls=2 flightMs=6.906 flightCalls=25536
CPC_ROUTE target='taxi_181' totalMs=83.413 navMs=1.980 probes=17 cacheHits=62 cacheSize=326 startMs=0.754 startCalls=2 flightMs=6.832 flightCalls=24394
CPC_ROUTE target='taxi_457' totalMs=162.984 navMs=1.599 probes=18 cacheHits=135 cacheSize=326 startMs=2.242 startCalls=14 flightMs=7.647 flightCalls=56805
CPC_ROUTE target='portal_at_324_source' totalMs=62.977 navMs=1.531 probes=36 cacheHits=136 cacheSize=326 startMs=35.213 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=61.999 navMs=1.451 probes=36 cacheHits=136 cacheSize=326 startMs=34.720 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=61.927 navMs=1.440 probes=36 cacheHits=136 cacheSize=326 startMs=34.442 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=61.652 navMs=1.309 probes=36 cacheHits=136 cacheSize=326 startMs=34.297 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.957 navMs=1.350 probes=18 cacheHits=102 cacheSize=326 startMs=35.193 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.204 navMs=1.366 probes=18 cacheHits=102 cacheSize=326 startMs=34.712 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=59.730 navMs=1.328 probes=18 cacheHits=102 cacheSize=326 startMs=34.265 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=59.389 navMs=1.284 probes=18 cacheHits=102 cacheSize=326 startMs=33.867 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=59.603 navMs=3.131 probes=72 cacheHits=364 cacheSize=326 startMs=4.767 startCalls=17 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=302.005 navMs=11.610 probes=909 cacheHits=283 cacheSize=326 startMs=2.750 startCalls=5 flightMs=13.884 flightCalls=97240
CPC_ROUTE target='taxi_23' totalMs=51.635 navMs=3.335 probes=77 cacheHits=272 cacheSize=326 startMs=2.619 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=299.534 navMs=11.445 probes=909 cacheHits=283 cacheSize=326 startMs=2.976 startCalls=5 flightMs=13.134 flightCalls=97240
CPC_ROUTE target='portal_at_523_source' totalMs=63.511 navMs=1.561 probes=36 cacheHits=136 cacheSize=326 startMs=35.406 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=61.961 navMs=1.483 probes=36 cacheHits=136 cacheSize=326 startMs=34.653 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=63.486 navMs=1.551 probes=36 cacheHits=136 cacheSize=326 startMs=35.175 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=61.548 navMs=1.528 probes=36 cacheHits=136 cacheSize=326 startMs=34.065 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_601' totalMs=158.980 navMs=1.612 probes=18 cacheHits=95 cacheSize=326 startMs=2.677 startCalls=13 flightMs=10.054 flightCalls=54638
CPC_ROUTE target='taxi_457' totalMs=59.900 navMs=2.976 probes=72 cacheHits=412 cacheSize=326 startMs=4.139 startCalls=13 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_569' totalMs=142.079 navMs=1.643 probes=18 cacheHits=97 cacheSize=326 startMs=0.000 startCalls=0 flightMs=6.609 flightCalls=49785
CPC_PERF windowMs=30005 ticks=3897 players=57 travelMs=48.734 perceptionMs=188.265 transportMs=2.207 flightMs=1.015 actionsMs=3331.908 controllersMs=1349.896 slowGuid=75 slowMs=75.810
CPC_ROUTE target='taxi_388' totalMs=82.773 navMs=2.863 probes=37 cacheHits=77 cacheSize=326 startMs=0.601 startCalls=2 flightMs=3.579 flightCalls=27187
CPC_ROUTE target='taxi_388' totalMs=83.809 navMs=2.873 probes=37 cacheHits=77 cacheSize=326 startMs=0.743 startCalls=2 flightMs=4.016 flightCalls=27186
CPC_ROUTE target='taxi_388' totalMs=82.816 navMs=2.907 probes=37 cacheHits=76 cacheSize=326 startMs=0.605 startCalls=2 flightMs=3.216 flightCalls=26809
CPC_ROUTE target='taxi_388' totalMs=83.805 navMs=2.995 probes=37 cacheHits=76 cacheSize=326 startMs=0.587 startCalls=2 flightMs=3.532 flightCalls=26808
CPC_ROUTE target='taxi_388' totalMs=87.505 navMs=3.185 probes=41 cacheHits=77 cacheSize=326 startMs=0.723 startCalls=2 flightMs=3.626 flightCalls=27748
CPC_ROUTE target='taxi_388' totalMs=75.330 navMs=1.810 probes=17 cacheHits=62 cacheSize=326 startMs=0.745 startCalls=2 flightMs=3.157 flightCalls=24206
CPC_ROUTE target='ironforge_gate' totalMs=61.640 navMs=1.562 probes=18 cacheHits=102 cacheSize=326 startMs=35.584 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.067 navMs=1.467 probes=18 cacheHits=102 cacheSize=326 startMs=35.051 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.773 navMs=1.433 probes=18 cacheHits=102 cacheSize=326 startMs=34.794 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=61.458 navMs=1.643 probes=18 cacheHits=97 cacheSize=326 startMs=35.247 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=61.203 navMs=1.506 probes=18 cacheHits=97 cacheSize=326 startMs=35.105 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=60.349 navMs=1.546 probes=18 cacheHits=97 cacheSize=326 startMs=34.630 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=59.658 navMs=1.442 probes=18 cacheHits=97 cacheSize=326 startMs=34.020 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_23' totalMs=51.803 navMs=3.138 probes=72 cacheHits=272 cacheSize=326 startMs=1.717 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=59.814 navMs=3.052 probes=72 cacheHits=364 cacheSize=326 startMs=5.270 startCalls=17 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_457' totalMs=64.249 navMs=1.562 probes=36 cacheHits=136 cacheSize=326 startMs=36.392 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=457.065 navMs=9.277 probes=839 cacheHits=341 cacheSize=326 startMs=2.999 startCalls=18 flightMs=185.216 flightCalls=91970
CPC_ROUTE target='portal_at_4520_target' totalMs=252.372 navMs=7.596 probes=770 cacheHits=205 cacheSize=326 startMs=0.977 startCalls=2 flightMs=27.641 flightCalls=75718
CPC_ROUTE target='portal_at_4367_target' totalMs=301.114 navMs=11.537 probes=909 cacheHits=283 cacheSize=326 startMs=0.991 startCalls=2 flightMs=12.511 flightCalls=97239
CPC_ROUTE target='portal_at_4367_target' totalMs=345.522 navMs=11.622 probes=909 cacheHits=283 cacheSize=326 startMs=38.337 startCalls=80 flightMs=12.538 flightCalls=97239
CPC_ROUTE target='portal_at_1466_source' totalMs=62.813 navMs=1.509 probes=36 cacheHits=136 cacheSize=326 startMs=35.237 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=61.793 navMs=1.480 probes=36 cacheHits=136 cacheSize=326 startMs=34.599 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=62.160 navMs=1.547 probes=36 cacheHits=136 cacheSize=326 startMs=34.721 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=61.649 navMs=1.476 probes=36 cacheHits=136 cacheSize=326 startMs=34.135 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_601' totalMs=160.181 navMs=1.569 probes=18 cacheHits=95 cacheSize=326 startMs=3.227 startCalls=13 flightMs=10.878 flightCalls=54638
CPC_ROUTE target='portal_at_2530_target' totalMs=60.817 navMs=0.375 probes=3 cacheHits=41 cacheSize=326 startMs=0.948 startCalls=1 flightMs=2.596 flightCalls=20893
CPC_ROUTE target='taxi_82' totalMs=57.350 navMs=3.033 probes=72 cacheHits=364 cacheSize=326 startMs=3.568 startCalls=17 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4320_source' totalMs=199.564 navMs=6.240 probes=93 cacheHits=210 cacheSize=326 startMs=0.905 startCalls=1 flightMs=14.995 flightCalls=64180
CPC_ROUTE target='taxi_128' totalMs=283.110 navMs=9.254 probes=839 cacheHits=397 cacheSize=326 startMs=3.008 startCalls=18 flightMs=11.083 flightCalls=91970
CPC_ROUTE target='portal_at_2530_target' totalMs=59.184 navMs=3.016 probes=72 cacheHits=364 cacheSize=326 startMs=5.067 startCalls=17 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_17' totalMs=1732.652 navMs=8.839 probes=836 cacheHits=292 cacheSize=326 startMs=1.959 startCalls=17 flightMs=1466.805 flightCalls=90943
CPC_ROUTE target='portal_at_4404_source' totalMs=1413.896 navMs=15.480 probes=951 cacheHits=381 cacheSize=326 startMs=2.136 startCalls=14 flightMs=1088.904 flightCalls=107177
CPC_ROUTE target='taxi_23' totalMs=51.567 navMs=3.376 probes=77 cacheHits=272 cacheSize=326 startMs=2.627 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.072 navMs=1.345 probes=18 cacheHits=113 cacheSize=326 startMs=35.942 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.702 navMs=1.418 probes=18 cacheHits=113 cacheSize=326 startMs=35.189 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.693 navMs=1.346 probes=18 cacheHits=113 cacheSize=326 startMs=34.550 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_82' totalMs=189.461 navMs=7.137 probes=115 cacheHits=167 cacheSize=326 startMs=0.000 startCalls=0 flightMs=8.191 flightCalls=64435
CPC_ROUTE target='taxi_601' totalMs=159.470 navMs=1.639 probes=18 cacheHits=95 cacheSize=326 startMs=2.971 startCalls=13 flightMs=9.588 flightCalls=54638
CPC_ROUTE target='portal_at_4367_target' totalMs=307.886 navMs=11.460 probes=910 cacheHits=284 cacheSize=326 startMs=2.836 startCalls=4 flightMs=13.414 flightCalls=97735
CPC_PERF windowMs=30007 ticks=2107 players=72 travelMs=42.527 perceptionMs=213.655 transportMs=9.568 flightMs=0.850 actionsMs=8387.918 controllersMs=1317.407 slowGuid=96 slowMs=61.970
CPC_ROUTE target='taxi_388' totalMs=78.247 navMs=1.976 probes=25 cacheHits=68 cacheSize=326 startMs=0.646 startCalls=2 flightMs=3.575 flightCalls=24987
CPC_ROUTE target='taxi_388' totalMs=77.146 navMs=1.864 probes=25 cacheHits=68 cacheSize=326 startMs=0.584 startCalls=2 flightMs=3.811 flightCalls=24986
CPC_ROUTE target='taxi_388' totalMs=78.583 navMs=2.119 probes=30 cacheHits=70 cacheSize=326 startMs=0.745 startCalls=2 flightMs=3.745 flightCalls=24985
CPC_ROUTE target='taxi_388' totalMs=70.869 navMs=1.476 probes=11 cacheHits=60 cacheSize=326 startMs=0.738 startCalls=2 flightMs=3.492 flightCalls=22702
CPC_ROUTE target='taxi_388' totalMs=81.475 navMs=2.434 probes=34 cacheHits=70 cacheSize=326 startMs=0.738 startCalls=2 flightMs=3.983 flightCalls=25548
CPC_ROUTE target='taxi_388' totalMs=84.263 navMs=2.503 probes=34 cacheHits=72 cacheSize=326 startMs=0.710 startCalls=2 flightMs=4.071 flightCalls=26299
CPC_ROUTE target='portal_at_1468_source' totalMs=63.530 navMs=1.540 probes=36 cacheHits=136 cacheSize=326 startMs=35.452 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=63.117 navMs=1.494 probes=36 cacheHits=136 cacheSize=326 startMs=35.101 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=62.731 navMs=1.541 probes=36 cacheHits=136 cacheSize=326 startMs=34.742 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=62.575 navMs=1.484 probes=36 cacheHits=136 cacheSize=326 startMs=34.595 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=288.189 navMs=9.567 probes=842 cacheHits=438 cacheSize=326 startMs=3.143 startCalls=18 flightMs=13.936 flightCalls=92467
CPC_ROUTE target='stormwind_gate_inner' totalMs=172.309 navMs=1.586 probes=18 cacheHits=195 cacheSize=326 startMs=3.813 startCalls=16 flightMs=11.824 flightCalls=58124
CPC_ROUTE target='taxi_310' totalMs=348.251 navMs=15.614 probes=962 cacheHits=364 cacheSize=326 startMs=1.505 startCalls=5 flightMs=14.372 flightCalls=104280
CPC_ROUTE target='portal_at_2530_target' totalMs=52.085 navMs=3.468 probes=77 cacheHits=272 cacheSize=326 startMs=2.018 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_310' totalMs=332.564 navMs=15.730 probes=963 cacheHits=363 cacheSize=326 startMs=1.440 startCalls=5 flightMs=13.691 flightCalls=104280
CPC_ROUTE target='taxi_395' totalMs=63.915 navMs=1.652 probes=36 cacheHits=136 cacheSize=326 startMs=35.394 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=63.033 navMs=1.558 probes=36 cacheHits=136 cacheSize=326 startMs=35.209 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=62.876 navMs=1.597 probes=36 cacheHits=136 cacheSize=326 startMs=34.602 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=63.494 navMs=1.657 probes=36 cacheHits=136 cacheSize=326 startMs=34.928 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=66.091 navMs=1.626 probes=36 cacheHits=126 cacheSize=326 startMs=36.771 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=63.290 navMs=1.552 probes=36 cacheHits=126 cacheSize=326 startMs=35.573 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=62.396 navMs=1.579 probes=36 cacheHits=126 cacheSize=326 startMs=34.701 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=62.925 navMs=1.594 probes=36 cacheHits=126 cacheSize=326 startMs=34.798 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.461 navMs=1.499 probes=18 cacheHits=102 cacheSize=326 startMs=35.444 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.868 navMs=1.353 probes=18 cacheHits=102 cacheSize=326 startMs=35.006 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.368 navMs=1.506 probes=18 cacheHits=102 cacheSize=326 startMs=34.840 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_310' totalMs=335.712 navMs=15.754 probes=962 cacheHits=364 cacheSize=326 startMs=1.401 startCalls=5 flightMs=15.682 flightCalls=104280
CPC_ROUTE target='taxi_310' totalMs=340.001 navMs=15.991 probes=963 cacheHits=363 cacheSize=326 startMs=1.393 startCalls=5 flightMs=17.465 flightCalls=104280
CPC_ROUTE target='taxi_310' totalMs=334.287 navMs=15.959 probes=962 cacheHits=364 cacheSize=326 startMs=1.418 startCalls=5 flightMs=15.534 flightCalls=104280
CPC_ROUTE target='taxi_310' totalMs=334.042 navMs=16.013 probes=962 cacheHits=364 cacheSize=326 startMs=1.078 startCalls=4 flightMs=13.264 flightCalls=104280
CPC_ROUTE target='taxi_310' totalMs=375.173 navMs=15.817 probes=962 cacheHits=363 cacheSize=326 startMs=36.101 startCalls=80 flightMs=13.463 flightCalls=104032
CPC_ROUTE target='taxi_310' totalMs=378.398 navMs=15.963 probes=962 cacheHits=363 cacheSize=326 startMs=35.369 startCalls=79 flightMs=13.756 flightCalls=104032
CPC_ROUTE target='taxi_310' totalMs=382.018 navMs=15.861 probes=962 cacheHits=363 cacheSize=326 startMs=35.677 startCalls=78 flightMs=14.178 flightCalls=104032
CPC_ROUTE target='taxi_310' totalMs=382.199 navMs=15.886 probes=962 cacheHits=363 cacheSize=326 startMs=34.674 startCalls=77 flightMs=13.939 flightCalls=104032
CPC_ROUTE target='portal_at_2530_target' totalMs=50.156 navMs=2.952 probes=72 cacheHits=272 cacheSize=326 startMs=1.737 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=163.280 navMs=1.577 probes=19 cacheHits=117 cacheSize=326 startMs=1.592 startCalls=5 flightMs=11.459 flightCalls=56819
CPC_ROUTE target='taxi_601' totalMs=159.280 navMs=1.622 probes=18 cacheHits=95 cacheSize=326 startMs=2.655 startCalls=13 flightMs=10.420 flightCalls=54638
CPC_ROUTE target='ironforge_gate' totalMs=163.392 navMs=1.599 probes=21 cacheHits=101 cacheSize=326 startMs=1.440 startCalls=5 flightMs=12.448 flightCalls=56072
CPC_ROUTE target='ironforge_gate' totalMs=164.849 navMs=1.640 probes=19 cacheHits=117 cacheSize=326 startMs=1.442 startCalls=5 flightMs=11.163 flightCalls=56819
CPC_ROUTE target='ironforge_gate' totalMs=160.798 navMs=1.611 probes=21 cacheHits=101 cacheSize=326 startMs=1.464 startCalls=5 flightMs=10.069 flightCalls=56072
CPC_PERF windowMs=30006 ticks=1625 players=84 travelMs=36.768 perceptionMs=245.261 transportMs=8.367 flightMs=73.778 actionsMs=7113.584 controllersMs=1847.963 slowGuid=104 slowMs=175.814
CPC_ROUTE target='portal_at_5505_source' totalMs=663.380 navMs=31.453 probes=1924 cacheHits=726 cacheSize=326 startMs=0.000 startCalls=0 flightMs=20.814 flightCalls=208064
CPC_ROUTE target='ironforge_gate' totalMs=163.624 navMs=1.610 probes=19 cacheHits=117 cacheSize=326 startMs=1.393 startCalls=5 flightMs=10.603 flightCalls=56819
CPC_ROUTE target='ironforge_gate' totalMs=164.798 navMs=1.641 probes=19 cacheHits=116 cacheSize=326 startMs=1.090 startCalls=4 flightMs=12.364 flightCalls=56570
CPC_ROUTE target='ironforge_gate' totalMs=201.248 navMs=1.581 probes=18 cacheHits=113 cacheSize=326 startMs=35.334 startCalls=80 flightMs=10.761 flightCalls=56070
CPC_ROUTE target='ironforge_gate' totalMs=202.325 navMs=1.533 probes=18 cacheHits=113 cacheSize=326 startMs=35.098 startCalls=79 flightMs=10.375 flightCalls=56070
CPC_ROUTE target='ironforge_gate' totalMs=204.303 navMs=1.582 probes=18 cacheHits=113 cacheSize=326 startMs=34.855 startCalls=78 flightMs=10.306 flightCalls=56070
CPC_ROUTE target='ironforge_gate' totalMs=205.083 navMs=1.593 probes=18 cacheHits=113 cacheSize=326 startMs=34.600 startCalls=77 flightMs=10.395 flightCalls=56070
CPC_ROUTE target='kharanos' totalMs=60.970 navMs=1.552 probes=18 cacheHits=97 cacheSize=326 startMs=35.172 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=59.625 navMs=1.475 probes=18 cacheHits=97 cacheSize=326 startMs=34.401 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=59.722 navMs=1.445 probes=18 cacheHits=97 cacheSize=326 startMs=34.136 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=59.715 navMs=1.468 probes=18 cacheHits=97 cacheSize=326 startMs=34.176 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=289.580 navMs=9.694 probes=842 cacheHits=438 cacheSize=326 startMs=3.317 startCalls=18 flightMs=14.219 flightCalls=92467
CPC_ROUTE target='taxi_55' totalMs=69.456 navMs=0.983 probes=11 cacheHits=57 cacheSize=326 startMs=0.640 startCalls=2 flightMs=3.734 flightCalls=22897
CPC_ROUTE target='taxi_55' totalMs=69.418 navMs=0.978 probes=11 cacheHits=57 cacheSize=326 startMs=0.688 startCalls=2 flightMs=3.542 flightCalls=22896
CPC_ROUTE target='taxi_55' totalMs=70.920 navMs=1.516 probes=17 cacheHits=62 cacheSize=326 startMs=0.785 startCalls=2 flightMs=3.351 flightCalls=23083
CPC_ROUTE target='taxi_55' totalMs=71.000 navMs=1.505 probes=12 cacheHits=60 cacheSize=326 startMs=0.740 startCalls=2 flightMs=3.313 flightCalls=23078
CPC_ROUTE target='taxi_55' totalMs=74.738 navMs=1.991 probes=21 cacheHits=62 cacheSize=326 startMs=0.723 startCalls=2 flightMs=3.419 flightCalls=23646
CPC_ROUTE target='taxi_55' totalMs=76.242 navMs=1.848 probes=21 cacheHits=64 cacheSize=326 startMs=0.582 startCalls=2 flightMs=3.190 flightCalls=24397
CPC_ROUTE target='portal_at_2530_target' totalMs=51.710 navMs=3.310 probes=77 cacheHits=272 cacheSize=326 startMs=2.630 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=170.757 navMs=1.649 probes=19 cacheHits=106 cacheSize=326 startMs=1.684 startCalls=5 flightMs=19.547 flightCalls=56072
CPC_ROUTE target='ironforge_gate' totalMs=162.505 navMs=1.639 probes=21 cacheHits=101 cacheSize=326 startMs=1.688 startCalls=5 flightMs=11.230 flightCalls=56072
CPC_ROUTE target='taxi_601' totalMs=160.423 navMs=1.577 probes=18 cacheHits=95 cacheSize=326 startMs=2.711 startCalls=13 flightMs=10.070 flightCalls=54638
CPC_ROUTE target='ironforge_gate' totalMs=62.481 navMs=1.558 probes=18 cacheHits=102 cacheSize=326 startMs=36.480 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.975 navMs=1.467 probes=18 cacheHits=102 cacheSize=326 startMs=34.648 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.321 navMs=1.363 probes=18 cacheHits=102 cacheSize=326 startMs=34.482 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=160.029 navMs=1.508 probes=19 cacheHits=106 cacheSize=326 startMs=1.410 startCalls=5 flightMs=10.265 flightCalls=56072
CPC_ROUTE target='taxi_38' totalMs=150.391 navMs=1.584 probes=20 cacheHits=99 cacheSize=326 startMs=1.834 startCalls=3 flightMs=6.330 flightCalls=53148
CPC_ROUTE target='ironforge_gate' totalMs=162.662 navMs=1.619 probes=21 cacheHits=101 cacheSize=326 startMs=1.435 startCalls=5 flightMs=11.579 flightCalls=56072
CPC_ROUTE target='taxi_82' totalMs=50.425 navMs=3.179 probes=72 cacheHits=272 cacheSize=326 startMs=0.431 startCalls=1 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=165.774 navMs=1.644 probes=19 cacheHits=106 cacheSize=326 startMs=1.561 startCalls=5 flightMs=13.405 flightCalls=56072
CPC_ROUTE target='ironforge_gate' totalMs=178.453 navMs=1.655 probes=19 cacheHits=105 cacheSize=326 startMs=1.353 startCalls=4 flightMs=20.378 flightCalls=55823
CPC_ROUTE target='ironforge_gate' totalMs=222.283 navMs=1.705 probes=18 cacheHits=102 cacheSize=326 startMs=39.135 startCalls=80 flightMs=20.722 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=210.050 navMs=1.836 probes=18 cacheHits=102 cacheSize=326 startMs=39.007 startCalls=79 flightMs=13.799 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=209.872 navMs=1.651 probes=18 cacheHits=102 cacheSize=326 startMs=35.244 startCalls=78 flightMs=16.559 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=221.756 navMs=1.647 probes=18 cacheHits=102 cacheSize=326 startMs=35.951 startCalls=77 flightMs=18.490 flightCalls=55323
CPC_ROUTE target='portal_at_6108_source' totalMs=69.821 navMs=1.722 probes=36 cacheHits=136 cacheSize=326 startMs=38.893 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=69.058 navMs=1.656 probes=36 cacheHits=136 cacheSize=326 startMs=39.161 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=66.841 navMs=1.715 probes=36 cacheHits=136 cacheSize=326 startMs=36.776 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=66.447 navMs=1.588 probes=36 cacheHits=136 cacheSize=326 startMs=36.895 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=68.278 navMs=1.719 probes=18 cacheHits=102 cacheSize=326 startMs=39.121 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=67.314 navMs=1.689 probes=18 cacheHits=102 cacheSize=326 startMs=38.173 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=65.352 navMs=1.685 probes=18 cacheHits=102 cacheSize=326 startMs=37.548 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=1828.142 navMs=11.845 probes=909 cacheHits=283 cacheSize=326 startMs=2.853 startCalls=5 flightMs=1537.222 flightCalls=97240
CPC_ROUTE target='taxi_601' totalMs=1277.671 navMs=1.654 probes=18 cacheHits=95 cacheSize=326 startMs=2.810 startCalls=13 flightMs=1125.724 flightCalls=54638
CPC_ROUTE target='portal_at_2171_target' totalMs=63.181 navMs=1.590 probes=36 cacheHits=126 cacheSize=326 startMs=35.175 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=61.586 navMs=1.440 probes=36 cacheHits=126 cacheSize=326 startMs=34.551 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=61.758 navMs=1.429 probes=36 cacheHits=126 cacheSize=326 startMs=34.333 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=61.472 navMs=1.456 probes=36 cacheHits=126 cacheSize=326 startMs=33.974 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=162.249 navMs=1.580 probes=19 cacheHits=106 cacheSize=326 startMs=1.435 startCalls=5 flightMs=12.506 flightCalls=56072
CPC_ROUTE target='portal_at_2530_target' totalMs=50.369 navMs=3.062 probes=72 cacheHits=272 cacheSize=326 startMs=1.735 startCalls=4 flightMs=0.000 flightCalls=0
CPC_PERF windowMs=30013 ticks=1248 players=99 travelMs=38.541 perceptionMs=261.382 transportMs=7.342 flightMs=73.418 actionsMs=10444.503 controllersMs=1917.755 slowGuid=120 slowMs=147.087
CPC_ROUTE target='ironforge_gate' totalMs=162.546 navMs=1.611 probes=21 cacheHits=104 cacheSize=326 startMs=1.420 startCalls=5 flightMs=11.205 flightCalls=56321
CPC_ROUTE target='kharanos' totalMs=61.551 navMs=1.623 probes=18 cacheHits=94 cacheSize=326 startMs=35.470 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=60.460 navMs=1.490 probes=18 cacheHits=94 cacheSize=326 startMs=35.151 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=60.044 navMs=1.469 probes=18 cacheHits=94 cacheSize=326 startMs=34.569 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='kharanos' totalMs=60.124 navMs=1.467 probes=18 cacheHits=94 cacheSize=326 startMs=34.429 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_521' totalMs=295.569 navMs=10.298 probes=848 cacheHits=302 cacheSize=326 startMs=2.630 startCalls=15 flightMs=22.254 flightCalls=93305
CPC_ROUTE target='ironforge_gate' totalMs=163.084 navMs=1.604 probes=19 cacheHits=106 cacheSize=326 startMs=1.729 startCalls=5 flightMs=11.891 flightCalls=56072
CPC_ROUTE target='portal_at_2530_target' totalMs=83.741 navMs=2.673 probes=32 cacheHits=73 cacheSize=326 startMs=2.041 startCalls=3 flightMs=5.171 flightCalls=26059
CPC_ROUTE target='taxi_128' totalMs=283.759 navMs=9.451 probes=839 cacheHits=341 cacheSize=326 startMs=2.920 startCalls=18 flightMs=12.866 flightCalls=91970
CPC_ROUTE target='ironforge_gate' totalMs=166.231 navMs=1.689 probes=21 cacheHits=104 cacheSize=326 startMs=1.667 startCalls=5 flightMs=13.772 flightCalls=56321
CPC_ROUTE target='taxi_82' totalMs=166.269 navMs=2.068 probes=20 cacheHits=97 cacheSize=326 startMs=0.645 startCalls=1 flightMs=16.278 flightCalls=52745
CPC_ROUTE target='ironforge_gate' totalMs=187.505 navMs=1.907 probes=19 cacheHits=106 cacheSize=326 startMs=1.630 startCalls=5 flightMs=24.564 flightCalls=56072
CPC_ROUTE target='ironforge_gate' totalMs=182.197 navMs=1.905 probes=19 cacheHits=105 cacheSize=326 startMs=1.298 startCalls=4 flightMs=20.683 flightCalls=55823
CPC_ROUTE target='ironforge_gate' totalMs=235.239 navMs=1.981 probes=18 cacheHits=102 cacheSize=326 startMs=39.386 startCalls=80 flightMs=25.943 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=215.249 navMs=1.836 probes=18 cacheHits=102 cacheSize=326 startMs=39.269 startCalls=79 flightMs=17.132 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=204.349 navMs=1.659 probes=18 cacheHits=102 cacheSize=326 startMs=35.208 startCalls=78 flightMs=11.743 flightCalls=55323
CPC_ROUTE target='ironforge_gate' totalMs=206.213 navMs=1.625 probes=18 cacheHits=102 cacheSize=326 startMs=34.921 startCalls=77 flightMs=11.953 flightCalls=55323
CPC_ROUTE target='taxi_181' totalMs=221.744 navMs=7.748 probes=125 cacheHits=176 cacheSize=326 startMs=0.703 startCalls=2 flightMs=18.705 flightCalls=67018
CPC_ROUTE target='taxi_181' totalMs=221.263 navMs=7.643 probes=125 cacheHits=176 cacheSize=326 startMs=0.863 startCalls=2 flightMs=17.633 flightCalls=67017
CPC_ROUTE target='taxi_181' totalMs=220.328 navMs=7.587 probes=112 cacheHits=167 cacheSize=326 startMs=0.699 startCalls=2 flightMs=21.716 flightCalls=64576
CPC_ROUTE target='taxi_181' totalMs=228.781 navMs=8.185 probes=125 cacheHits=176 cacheSize=326 startMs=0.633 startCalls=2 flightMs=20.127 flightCalls=67015
CPC_ROUTE target='taxi_181' totalMs=226.745 navMs=7.594 probes=122 cacheHits=175 cacheSize=326 startMs=0.860 startCalls=2 flightMs=17.630 flightCalls=67011
CPC_ROUTE target='taxi_181' totalMs=233.746 navMs=7.755 probes=125 cacheHits=177 cacheSize=326 startMs=0.747 startCalls=2 flightMs=20.668 flightCalls=67201
CPC_ROUTE target='portal_at_7151_source' totalMs=68.457 navMs=1.858 probes=18 cacheHits=99 cacheSize=326 startMs=38.844 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_7151_source' totalMs=68.034 navMs=1.793 probes=18 cacheHits=99 cacheSize=326 startMs=38.776 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_7151_source' totalMs=66.806 navMs=1.675 probes=18 cacheHits=99 cacheSize=326 startMs=38.103 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_7151_source' totalMs=66.364 navMs=1.694 probes=18 cacheHits=99 cacheSize=326 startMs=37.836 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_11' totalMs=175.388 navMs=2.072 probes=18 cacheHits=97 cacheSize=328 startMs=0.844 startCalls=2 flightMs=21.636 flightCalls=52769
CPC_ROUTE target='taxi_601' totalMs=176.589 navMs=1.835 probes=18 cacheHits=95 cacheSize=328 startMs=2.825 startCalls=13 flightMs=16.754 flightCalls=54638
CPC_ROUTE target='portal_at_4367_target' totalMs=335.289 navMs=13.353 probes=909 cacheHits=283 cacheSize=328 startMs=1.088 startCalls=2 flightMs=26.730 flightCalls=97239
CPC_ROUTE target='portal_at_4367_target' totalMs=385.493 navMs=13.280 probes=909 cacheHits=283 cacheSize=328 startMs=41.052 startCalls=80 flightMs=26.465 flightCalls=97239
CPC_ROUTE target='portal_at_2530_target' totalMs=59.125 navMs=3.874 probes=77 cacheHits=272 cacheSize=328 startMs=2.969 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=55.584 navMs=3.138 probes=75 cacheHits=272 cacheSize=328 startMs=1.913 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=69.248 navMs=1.828 probes=18 cacheHits=97 cacheSize=328 startMs=39.938 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=67.173 navMs=1.556 probes=18 cacheHits=97 cacheSize=328 startMs=38.798 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=67.035 navMs=1.680 probes=18 cacheHits=97 cacheSize=328 startMs=38.413 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2230_source' totalMs=57.670 navMs=3.541 probes=72 cacheHits=272 cacheSize=328 startMs=0.708 startCalls=1 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_5193_source' totalMs=756.751 navMs=36.748 probes=1924 cacheHits=726 cacheSize=328 startMs=0.000 startCalls=0 flightMs=67.153 flightCalls=208064
CPC_ROUTE target='taxi_181' totalMs=67.506 navMs=0.475 probes=3 cacheHits=40 cacheSize=328 startMs=1.564 startCalls=2 flightMs=6.862 flightCalls=20141
CPC_ROUTE target='portal_at_324_source' totalMs=73.571 navMs=1.715 probes=36 cacheHits=136 cacheSize=328 startMs=41.194 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=69.901 navMs=1.630 probes=36 cacheHits=136 cacheSize=328 startMs=39.142 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=73.083 navMs=1.930 probes=36 cacheHits=136 cacheSize=328 startMs=40.777 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_324_source' totalMs=71.533 navMs=1.819 probes=36 cacheHits=136 cacheSize=328 startMs=39.369 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=59.233 navMs=4.020 probes=77 cacheHits=272 cacheSize=328 startMs=2.344 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=177.830 navMs=1.820 probes=19 cacheHits=99 cacheSize=328 startMs=1.580 startCalls=5 flightMs=20.999 flightCalls=54390
CPC_ROUTE target='taxi_82' totalMs=165.842 navMs=1.874 probes=20 cacheHits=99 cacheSize=328 startMs=1.080 startCalls=2 flightMs=12.407 flightCalls=52992
CPC_ROUTE target='taxi_82' totalMs=215.190 navMs=1.795 probes=18 cacheHits=97 cacheSize=328 startMs=42.616 startCalls=80 flightMs=14.537 flightCalls=52246
CPC_ROUTE target='portal_at_101_source' totalMs=72.074 navMs=1.856 probes=27 cacheHits=118 cacheSize=328 startMs=40.870 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=74.042 navMs=1.614 probes=27 cacheHits=118 cacheSize=328 startMs=40.243 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=71.419 navMs=1.853 probes=27 cacheHits=118 cacheSize=328 startMs=39.759 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=70.532 navMs=1.779 probes=27 cacheHits=118 cacheSize=328 startMs=39.050 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=185.802 navMs=1.864 probes=21 cacheHits=99 cacheSize=328 startMs=1.763 startCalls=5 flightMs=25.719 flightCalls=54888
CPC_ROUTE target='taxi_64' totalMs=85.558 navMs=0.464 probes=3 cacheHits=33 cacheSize=328 startMs=23.900 startCalls=45 flightMs=4.126 flightCalls=18825
CPC_ROUTE target='portal_at_2166_target' totalMs=181.556 navMs=1.887 probes=19 cacheHits=99 cacheSize=328 startMs=1.734 startCalls=5 flightMs=22.518 flightCalls=54390
CPC_PERF windowMs=30015 ticks=781 players=110 travelMs=62.087 perceptionMs=408.276 transportMs=12.536 flightMs=136.368 actionsMs=9366.665 controllersMs=1866.717 slowGuid=123 slowMs=105.831
CPC_ROUTE target='portal_at_2166_target' totalMs=179.170 navMs=1.855 probes=21 cacheHits=99 cacheSize=328 startMs=1.700 startCalls=5 flightMs=20.224 flightCalls=54888
CPC_ROUTE target='portal_at_2530_target' totalMs=56.085 navMs=3.513 probes=72 cacheHits=272 cacheSize=328 startMs=2.270 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=175.785 navMs=1.759 probes=19 cacheHits=99 cacheSize=328 startMs=1.695 startCalls=5 flightMs=19.443 flightCalls=54390
CPC_ROUTE target='portal_at_2166_target' totalMs=174.353 navMs=1.989 probes=19 cacheHits=98 cacheSize=328 startMs=1.185 startCalls=4 flightMs=17.913 flightCalls=54141
CPC_ROUTE target='portal_at_2166_target' totalMs=220.401 navMs=1.822 probes=18 cacheHits=97 cacheSize=328 startMs=40.616 startCalls=80 flightMs=19.010 flightCalls=53641
CPC_ROUTE target='portal_at_2166_target' totalMs=219.999 navMs=1.709 probes=18 cacheHits=97 cacheSize=328 startMs=39.234 startCalls=79 flightMs=18.401 flightCalls=53641
CPC_ROUTE target='portal_at_2166_target' totalMs=221.736 navMs=1.807 probes=18 cacheHits=97 cacheSize=328 startMs=39.048 startCalls=78 flightMs=19.129 flightCalls=53641
CPC_ROUTE target='portal_at_2166_target' totalMs=223.316 navMs=1.783 probes=18 cacheHits=97 cacheSize=328 startMs=38.491 startCalls=77 flightMs=20.531 flightCalls=53641
CPC_ROUTE target='portal_at_4367_target' totalMs=344.719 navMs=14.115 probes=910 cacheHits=284 cacheSize=328 startMs=3.018 startCalls=4 flightMs=27.284 flightCalls=97735
CPC_ROUTE target='portal_at_523_source' totalMs=71.051 navMs=1.682 probes=36 cacheHits=136 cacheSize=328 startMs=39.107 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=71.471 navMs=1.847 probes=36 cacheHits=136 cacheSize=328 startMs=38.822 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=71.736 navMs=1.690 probes=36 cacheHits=136 cacheSize=328 startMs=40.124 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_523_source' totalMs=68.656 navMs=1.674 probes=36 cacheHits=136 cacheSize=328 startMs=37.817 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=69.191 navMs=1.992 probes=18 cacheHits=99 cacheSize=328 startMs=39.015 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=68.683 navMs=1.769 probes=18 cacheHits=99 cacheSize=328 startMs=39.373 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=68.237 navMs=1.701 probes=18 cacheHits=99 cacheSize=328 startMs=38.309 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=67.345 navMs=1.695 probes=18 cacheHits=99 cacheSize=328 startMs=38.062 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=71.241 navMs=1.843 probes=18 cacheHits=102 cacheSize=328 startMs=39.855 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=68.556 navMs=1.935 probes=18 cacheHits=102 cacheSize=328 startMs=38.705 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=69.149 navMs=1.659 probes=18 cacheHits=102 cacheSize=328 startMs=39.988 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=68.117 navMs=1.659 probes=18 cacheHits=102 cacheSize=328 startMs=38.867 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=56.985 navMs=3.919 probes=77 cacheHits=272 cacheSize=328 startMs=2.143 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=74.342 navMs=0.357 probes=3 cacheHits=40 cacheSize=328 startMs=0.797 startCalls=2 flightMs=10.893 flightCalls=21645
CPC_ROUTE target='taxi_181' totalMs=70.036 navMs=0.417 probes=3 cacheHits=40 cacheSize=328 startMs=0.863 startCalls=2 flightMs=5.470 flightCalls=21644
CPC_ROUTE target='taxi_181' totalMs=69.377 navMs=0.443 probes=3 cacheHits=39 cacheSize=328 startMs=0.668 startCalls=2 flightMs=5.511 flightCalls=21267
CPC_ROUTE target='taxi_181' totalMs=74.212 navMs=1.667 probes=11 cacheHits=51 cacheSize=328 startMs=0.717 startCalls=2 flightMs=5.696 flightCalls=22206
CPC_ROUTE target='taxi_181' totalMs=79.746 navMs=2.152 probes=15 cacheHits=51 cacheSize=328 startMs=0.844 startCalls=2 flightMs=8.000 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=77.461 navMs=2.003 probes=15 cacheHits=51 cacheSize=328 startMs=0.881 startCalls=2 flightMs=6.095 flightCalls=22769
CPC_ROUTE target='taxi_128' totalMs=516.637 navMs=11.699 probes=839 cacheHits=341 cacheSize=328 startMs=2.601 startCalls=16 flightMs=224.614 flightCalls=91970
CPC_ROUTE target='portal_at_2530_target' totalMs=56.015 navMs=3.559 probes=72 cacheHits=272 cacheSize=328 startMs=2.245 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_82' totalMs=176.188 navMs=1.839 probes=22 cacheHits=101 cacheSize=328 startMs=4.037 startCalls=4 flightMs=14.138 flightCalls=53739
CPC_ROUTE target='taxi_601' totalMs=1229.272 navMs=1.672 probes=18 cacheHits=95 cacheSize=328 startMs=2.965 startCalls=13 flightMs=1073.934 flightCalls=54638
CPC_ROUTE target='taxi_64' totalMs=66.838 navMs=0.990 probes=5 cacheHits=39 cacheSize=328 startMs=3.543 startCalls=7 flightMs=6.857 flightCalls=19389
CPC_ROUTE target='ironforge_gate' totalMs=69.400 navMs=1.673 probes=18 cacheHits=113 cacheSize=328 startMs=40.983 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=1110.666 navMs=0.415 probes=3 cacheHits=40 cacheSize=328 startMs=0.039 startCalls=1 flightMs=1052.306 flightCalls=20141
CPC_ROUTE target='taxi_181' totalMs=60.350 navMs=0.410 probes=3 cacheHits=40 cacheSize=328 startMs=0.098 startCalls=1 flightMs=3.670 flightCalls=20141
CPC_ROUTE target='portal_at_1466_source' totalMs=67.267 navMs=1.662 probes=36 cacheHits=136 cacheSize=328 startMs=37.777 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=65.352 navMs=1.668 probes=36 cacheHits=136 cacheSize=328 startMs=36.375 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=66.391 navMs=1.686 probes=36 cacheHits=136 cacheSize=328 startMs=36.625 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1466_source' totalMs=65.407 navMs=1.591 probes=36 cacheHits=136 cacheSize=328 startMs=35.994 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=96.207 navMs=3.042 probes=56 cacheHits=95 cacheSize=328 startMs=0.000 startCalls=0 flightMs=7.308 flightCalls=28674
CPC_ROUTE target='taxi_181' totalMs=213.523 navMs=7.375 probes=133 cacheHits=191 cacheSize=328 startMs=0.081 startCalls=1 flightMs=12.512 flightCalls=69705
CPC_PERF windowMs=30011 ticks=1258 players=110 travelMs=55.301 perceptionMs=420.305 transportMs=18.870 flightMs=74.420 actionsMs=7762.125 controllersMs=1611.802 slowGuid=61 slowMs=18.412
CPC_ROUTE target='portal_at_2530_target' totalMs=52.766 navMs=3.526 probes=77 cacheHits=272 cacheSize=328 startMs=2.684 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=54.048 navMs=3.611 probes=77 cacheHits=272 cacheSize=328 startMs=2.677 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=181.023 navMs=1.706 probes=37 cacheHits=132 cacheSize=328 startMs=1.329 startCalls=5 flightMs=19.464 flightCalls=58831
CPC_ROUTE target='portal_at_286_source' totalMs=65.614 navMs=1.596 probes=36 cacheHits=136 cacheSize=328 startMs=36.905 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_286_source' totalMs=64.449 navMs=1.618 probes=36 cacheHits=136 cacheSize=328 startMs=35.939 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_286_source' totalMs=64.109 navMs=1.626 probes=36 cacheHits=136 cacheSize=328 startMs=35.354 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_286_source' totalMs=63.671 navMs=1.713 probes=36 cacheHits=136 cacheSize=328 startMs=34.972 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.681 navMs=1.611 probes=36 cacheHits=126 cacheSize=328 startMs=36.077 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.168 navMs=1.595 probes=36 cacheHits=126 cacheSize=328 startMs=35.951 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.734 navMs=1.699 probes=36 cacheHits=126 cacheSize=328 startMs=35.756 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.416 navMs=1.752 probes=36 cacheHits=126 cacheSize=328 startMs=35.542 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=176.666 navMs=1.731 probes=39 cacheHits=130 cacheSize=328 startMs=1.748 startCalls=5 flightMs=15.814 flightCalls=59080
CPC_ROUTE target='portal_at_2171_target' totalMs=175.548 navMs=1.713 probes=37 cacheHits=132 cacheSize=328 startMs=1.576 startCalls=5 flightMs=15.404 flightCalls=58831
CPC_ROUTE target='taxi_601' totalMs=162.117 navMs=1.683 probes=18 cacheHits=95 cacheSize=328 startMs=2.705 startCalls=13 flightMs=11.117 flightCalls=54638
CPC_ROUTE target='taxi_128' totalMs=285.494 navMs=9.507 probes=839 cacheHits=341 cacheSize=328 startMs=2.025 startCalls=16 flightMs=12.996 flightCalls=91970
CPC_ROUTE target='portal_at_2171_target' totalMs=176.487 navMs=1.708 probes=39 cacheHits=130 cacheSize=328 startMs=1.656 startCalls=5 flightMs=14.901 flightCalls=59080
CPC_ROUTE target='taxi_181' totalMs=62.917 navMs=0.369 probes=3 cacheHits=40 cacheSize=328 startMs=0.743 startCalls=2 flightMs=3.082 flightCalls=21645
CPC_ROUTE target='taxi_181' totalMs=63.963 navMs=0.360 probes=3 cacheHits=40 cacheSize=328 startMs=0.682 startCalls=2 flightMs=3.053 flightCalls=21644
CPC_ROUTE target='taxi_181' totalMs=63.146 navMs=0.380 probes=3 cacheHits=39 cacheSize=328 startMs=0.788 startCalls=2 flightMs=2.943 flightCalls=21267
CPC_ROUTE target='taxi_181' totalMs=67.325 navMs=1.575 probes=11 cacheHits=51 cacheSize=328 startMs=0.591 startCalls=2 flightMs=3.162 flightCalls=22206
CPC_ROUTE target='taxi_181' totalMs=69.559 navMs=1.866 probes=15 cacheHits=51 cacheSize=328 startMs=0.739 startCalls=2 flightMs=2.606 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=70.559 navMs=1.884 probes=15 cacheHits=51 cacheSize=328 startMs=0.766 startCalls=2 flightMs=3.075 flightCalls=22769
CPC_ROUTE target='portal_at_2171_target' totalMs=176.366 navMs=1.693 probes=37 cacheHits=132 cacheSize=328 startMs=1.472 startCalls=5 flightMs=15.948 flightCalls=58831
CPC_ROUTE target='portal_at_2171_target' totalMs=175.566 navMs=1.680 probes=37 cacheHits=131 cacheSize=328 startMs=1.083 startCalls=4 flightMs=15.518 flightCalls=58582
CPC_ROUTE target='portal_at_2171_target' totalMs=216.523 navMs=1.676 probes=36 cacheHits=126 cacheSize=328 startMs=36.293 startCalls=80 flightMs=17.086 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=212.781 navMs=1.624 probes=36 cacheHits=126 cacheSize=328 startMs=36.239 startCalls=79 flightMs=13.980 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=214.938 navMs=1.657 probes=36 cacheHits=126 cacheSize=328 startMs=35.019 startCalls=78 flightMs=14.814 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=215.493 navMs=1.655 probes=36 cacheHits=126 cacheSize=328 startMs=34.728 startCalls=77 flightMs=14.153 flightCalls=57833
CPC_ROUTE target='taxi_36' totalMs=65.389 navMs=1.606 probes=18 cacheHits=97 cacheSize=328 startMs=36.539 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.278 navMs=1.581 probes=18 cacheHits=97 cacheSize=328 startMs=35.539 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=61.723 navMs=1.634 probes=18 cacheHits=97 cacheSize=328 startMs=34.823 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=61.602 navMs=1.564 probes=18 cacheHits=97 cacheSize=328 startMs=34.566 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=309.099 navMs=12.717 probes=909 cacheHits=283 cacheSize=328 startMs=2.817 startCalls=5 flightMs=16.354 flightCalls=97240
CPC_ROUTE target='taxi_128' totalMs=286.388 navMs=10.150 probes=839 cacheHits=341 cacheSize=328 startMs=2.102 startCalls=16 flightMs=12.923 flightCalls=91970
CPC_ROUTE target='ironforge_gate' totalMs=62.540 navMs=1.616 probes=18 cacheHits=102 cacheSize=328 startMs=35.728 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.142 navMs=1.599 probes=18 cacheHits=102 cacheSize=328 startMs=35.622 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.533 navMs=1.563 probes=18 cacheHits=102 cacheSize=328 startMs=35.222 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.166 navMs=1.649 probes=18 cacheHits=102 cacheSize=328 startMs=34.637 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=51.323 navMs=3.133 probes=72 cacheHits=272 cacheSize=328 startMs=1.868 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=64.412 navMs=1.588 probes=36 cacheHits=136 cacheSize=328 startMs=35.818 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=63.988 navMs=1.588 probes=36 cacheHits=136 cacheSize=328 startMs=35.799 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=63.691 navMs=1.625 probes=36 cacheHits=136 cacheSize=328 startMs=35.254 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=63.575 navMs=1.611 probes=36 cacheHits=136 cacheSize=328 startMs=34.908 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_601' totalMs=163.303 navMs=1.643 probes=18 cacheHits=95 cacheSize=328 startMs=2.767 startCalls=13 flightMs=11.013 flightCalls=54638
CPC_PERF windowMs=30027 ticks=1600 players=110 travelMs=39.262 perceptionMs=364.001 transportMs=20.546 flightMs=4.953 actionsMs=5744.874 controllersMs=1729.274 slowGuid=61 slowMs=14.842
CPC_ROUTE target='portal_at_4367_target' totalMs=311.033 navMs=12.659 probes=909 cacheHits=283 cacheSize=328 startMs=3.399 startCalls=5 flightMs=18.913 flightCalls=97240
CPC_ROUTE target='taxi_82' totalMs=152.516 navMs=1.654 probes=20 cacheHits=97 cacheSize=328 startMs=3.048 startCalls=5 flightMs=6.591 flightCalls=52745
CPC_ROUTE target='portal_at_2530_target' totalMs=50.594 navMs=3.131 probes=72 cacheHits=272 cacheSize=328 startMs=1.730 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=65.306 navMs=1.644 probes=18 cacheHits=113 cacheSize=328 startMs=36.577 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=63.013 navMs=1.591 probes=18 cacheHits=113 cacheSize=328 startMs=35.876 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.949 navMs=1.590 probes=18 cacheHits=113 cacheSize=328 startMs=35.426 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=54.166 navMs=3.569 probes=77 cacheHits=272 cacheSize=328 startMs=2.666 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=52.712 navMs=3.289 probes=75 cacheHits=272 cacheSize=328 startMs=2.311 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=69.976 navMs=0.380 probes=3 cacheHits=42 cacheSize=328 startMs=0.739 startCalls=2 flightMs=8.544 flightCalls=21833
CPC_ROUTE target='taxi_181' totalMs=64.214 navMs=0.374 probes=3 cacheHits=42 cacheSize=328 startMs=0.740 startCalls=2 flightMs=3.049 flightCalls=21832
CPC_ROUTE target='taxi_181' totalMs=63.857 navMs=0.378 probes=3 cacheHits=41 cacheSize=328 startMs=0.748 startCalls=2 flightMs=2.857 flightCalls=21455
CPC_ROUTE target='taxi_181' totalMs=68.788 navMs=1.515 probes=11 cacheHits=53 cacheSize=328 startMs=0.744 startCalls=2 flightMs=3.477 flightCalls=22394
CPC_ROUTE target='taxi_181' totalMs=71.130 navMs=1.891 probes=15 cacheHits=51 cacheSize=328 startMs=0.734 startCalls=2 flightMs=3.500 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=71.490 navMs=1.836 probes=15 cacheHits=53 cacheSize=328 startMs=0.761 startCalls=2 flightMs=2.966 flightCalls=22957
CPC_ROUTE target='portal_at_4320_source' totalMs=184.971 navMs=3.013 probes=44 cacheHits=151 cacheSize=328 startMs=7.705 startCalls=20 flightMs=18.792 flightCalls=56328
CPC_ROUTE target='portal_at_6179_source' totalMs=65.389 navMs=1.610 probes=36 cacheHits=136 cacheSize=328 startMs=36.284 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6179_source' totalMs=64.475 navMs=1.599 probes=36 cacheHits=136 cacheSize=328 startMs=35.636 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6179_source' totalMs=64.836 navMs=1.665 probes=36 cacheHits=136 cacheSize=328 startMs=35.724 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6179_source' totalMs=64.096 navMs=1.590 probes=36 cacheHits=136 cacheSize=328 startMs=35.366 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=177.456 navMs=1.714 probes=37 cacheHits=132 cacheSize=328 startMs=1.278 startCalls=5 flightMs=17.642 flightCalls=58831
CPC_ROUTE target='portal_at_4320_source' totalMs=178.886 navMs=2.959 probes=44 cacheHits=149 cacheSize=328 startMs=8.145 startCalls=20 flightMs=11.423 flightCalls=56327
CPC_ROUTE target='portal_at_4320_source' totalMs=178.720 navMs=2.994 probes=44 cacheHits=149 cacheSize=328 startMs=7.762 startCalls=20 flightMs=10.449 flightCalls=56326
CPC_ROUTE target='portal_at_2171_target' totalMs=65.183 navMs=1.666 probes=36 cacheHits=126 cacheSize=328 startMs=36.162 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.201 navMs=1.581 probes=36 cacheHits=126 cacheSize=328 startMs=35.927 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=64.274 navMs=1.583 probes=36 cacheHits=126 cacheSize=328 startMs=35.634 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=63.786 navMs=1.595 probes=36 cacheHits=126 cacheSize=328 startMs=35.146 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4320_source' totalMs=178.781 navMs=2.928 probes=44 cacheHits=149 cacheSize=328 startMs=7.702 startCalls=20 flightMs=9.916 flightCalls=56325
CPC_ROUTE target='taxi_128' totalMs=450.910 navMs=10.125 probes=839 cacheHits=341 cacheSize=328 startMs=2.240 startCalls=16 flightMs=178.375 flightCalls=91970
CPC_ROUTE target='portal_at_2171_target' totalMs=173.651 navMs=1.694 probes=39 cacheHits=130 cacheSize=328 startMs=1.260 startCalls=5 flightMs=13.712 flightCalls=59080
CPC_ROUTE target='portal_at_4320_source' totalMs=174.979 navMs=2.476 probes=45 cacheHits=152 cacheSize=328 startMs=2.925 startCalls=20 flightMs=9.488 flightCalls=56574
CPC_ROUTE target='ironforge_gate' totalMs=150.035 navMs=1.233 probes=18 cacheHits=102 cacheSize=328 startMs=123.419 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=62.107 navMs=1.268 probes=18 cacheHits=102 cacheSize=328 startMs=35.544 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=61.862 navMs=1.228 probes=18 cacheHits=102 cacheSize=328 startMs=35.485 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=60.548 navMs=1.226 probes=18 cacheHits=102 cacheSize=328 startMs=34.511 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=1106.113 navMs=1.738 probes=37 cacheHits=132 cacheSize=328 startMs=1.320 startCalls=5 flightMs=944.865 flightCalls=58831
CPC_ROUTE target='portal_at_4520_target' totalMs=260.781 navMs=7.317 probes=770 cacheHits=205 cacheSize=328 startMs=1.888 startCalls=4 flightMs=37.730 flightCalls=75718
CPC_ROUTE target='portal_at_2171_target' totalMs=174.490 navMs=1.698 probes=39 cacheHits=130 cacheSize=328 startMs=1.411 startCalls=5 flightMs=13.989 flightCalls=59080
CPC_ROUTE target='portal_at_4367_target' totalMs=1216.573 navMs=12.305 probes=909 cacheHits=283 cacheSize=328 startMs=1.003 startCalls=2 flightMs=923.621 flightCalls=97239
CPC_ROUTE target='portal_at_4367_target' totalMs=350.910 navMs=12.357 probes=909 cacheHits=283 cacheSize=328 startMs=38.369 startCalls=80 flightMs=13.889 flightCalls=97239
CPC_ROUTE target='portal_at_2171_target' totalMs=175.082 navMs=1.712 probes=37 cacheHits=132 cacheSize=328 startMs=1.512 startCalls=5 flightMs=14.713 flightCalls=58831
CPC_ROUTE target='portal_at_2171_target' totalMs=175.784 navMs=1.685 probes=37 cacheHits=131 cacheSize=328 startMs=1.050 startCalls=4 flightMs=15.215 flightCalls=58582
CPC_ROUTE target='portal_at_2171_target' totalMs=217.013 navMs=1.718 probes=36 cacheHits=126 cacheSize=328 startMs=36.175 startCalls=80 flightMs=15.901 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=216.475 navMs=1.680 probes=36 cacheHits=126 cacheSize=328 startMs=35.735 startCalls=79 flightMs=15.434 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=220.812 navMs=1.682 probes=36 cacheHits=126 cacheSize=328 startMs=37.566 startCalls=78 flightMs=15.122 flightCalls=57833
CPC_ROUTE target='portal_at_2171_target' totalMs=218.269 navMs=1.669 probes=36 cacheHits=126 cacheSize=328 startMs=35.013 startCalls=77 flightMs=14.710 flightCalls=57833
CPC_ROUTE target='taxi_128' totalMs=286.463 navMs=9.826 probes=839 cacheHits=341 cacheSize=328 startMs=2.245 startCalls=16 flightMs=12.534 flightCalls=91970
CPC_ROUTE target='taxi_181' totalMs=233.451 navMs=8.262 probes=133 cacheHits=194 cacheSize=328 startMs=0.104 startCalls=2 flightMs=18.720 flightCalls=69951
CPC_ROUTE target='taxi_368' totalMs=54.233 navMs=3.498 probes=72 cacheHits=274 cacheSize=328 startMs=0.375 startCalls=2 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=237.620 navMs=8.011 probes=133 cacheHits=194 cacheSize=328 startMs=0.107 startCalls=1 flightMs=19.508 flightCalls=69950
CPC_PERF windowMs=30003 ticks=1124 players=110 travelMs=35.716 perceptionMs=377.288 transportMs=18.094 flightMs=2.354 actionsMs=9618.555 controllersMs=1708.803 slowGuid=102 slowMs=71.538
CPC_ROUTE target='portal_at_2534_target' totalMs=70.407 navMs=1.720 probes=18 cacheHits=97 cacheSize=328 startMs=40.339 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=69.118 navMs=1.701 probes=18 cacheHits=97 cacheSize=328 startMs=38.855 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=67.958 navMs=1.742 probes=18 cacheHits=97 cacheSize=328 startMs=38.210 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=68.533 navMs=1.632 probes=18 cacheHits=97 cacheSize=328 startMs=38.253 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=200.178 navMs=2.995 probes=45 cacheHits=154 cacheSize=328 startMs=1.985 startCalls=20 flightMs=23.068 flightCalls=58828
CPC_ROUTE target='taxi_181' totalMs=223.906 navMs=7.449 probes=136 cacheHits=216 cacheSize=328 startMs=0.053 startCalls=1 flightMs=10.862 flightCalls=71754
CPC_ROUTE target='taxi_601' totalMs=177.376 navMs=2.005 probes=18 cacheHits=95 cacheSize=328 startMs=2.702 startCalls=13 flightMs=17.671 flightCalls=54638
CPC_ROUTE target='portal_at_2166_target' totalMs=69.842 navMs=1.872 probes=18 cacheHits=97 cacheSize=328 startMs=39.605 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=68.216 navMs=1.726 probes=18 cacheHits=97 cacheSize=328 startMs=39.296 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=66.341 navMs=1.766 probes=18 cacheHits=97 cacheSize=328 startMs=37.778 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=67.185 navMs=1.852 probes=18 cacheHits=97 cacheSize=328 startMs=38.018 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=72.369 navMs=1.695 probes=36 cacheHits=136 cacheSize=328 startMs=40.316 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=70.330 navMs=1.872 probes=36 cacheHits=136 cacheSize=328 startMs=38.691 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=70.484 navMs=1.784 probes=36 cacheHits=136 cacheSize=328 startMs=38.366 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6108_source' totalMs=69.727 navMs=1.913 probes=36 cacheHits=136 cacheSize=328 startMs=37.411 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=210.274 navMs=3.183 probes=44 cacheHits=140 cacheSize=328 startMs=8.504 startCalls=20 flightMs=25.289 flightCalls=58080
CPC_ROUTE target='portal_at_101_source' totalMs=194.419 navMs=2.999 probes=44 cacheHits=147 cacheSize=328 startMs=8.467 startCalls=20 flightMs=16.939 flightCalls=58141
CPC_ROUTE target='portal_at_2166_target' totalMs=62.800 navMs=1.577 probes=18 cacheHits=97 cacheSize=328 startMs=36.200 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=62.213 navMs=1.615 probes=18 cacheHits=97 cacheSize=328 startMs=35.759 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=62.108 navMs=1.633 probes=18 cacheHits=97 cacheSize=328 startMs=35.417 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2166_target' totalMs=61.557 navMs=1.598 probes=18 cacheHits=97 cacheSize=328 startMs=34.992 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_82' totalMs=163.627 navMs=1.954 probes=20 cacheHits=97 cacheSize=328 startMs=3.729 startCalls=5 flightMs=10.516 flightCalls=52745
CPC_ROUTE target='portal_at_2530_target' totalMs=58.219 navMs=3.834 probes=77 cacheHits=272 cacheSize=328 startMs=2.850 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=55.652 navMs=3.513 probes=75 cacheHits=272 cacheSize=328 startMs=1.960 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_78_source' totalMs=271.676 navMs=10.177 probes=824 cacheHits=241 cacheSize=328 startMs=3.099 startCalls=20 flightMs=19.772 flightCalls=84551
CPC_ROUTE target='portal_at_2530_target' totalMs=50.926 navMs=3.488 probes=77 cacheHits=272 cacheSize=328 startMs=1.760 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_78_source' totalMs=276.942 navMs=10.578 probes=825 cacheHits=240 cacheSize=328 startMs=7.828 startCalls=20 flightMs=18.750 flightCalls=84550
CPC_ROUTE target='portal_at_78_source' totalMs=281.313 navMs=10.707 probes=825 cacheHits=240 cacheSize=328 startMs=8.393 startCalls=20 flightMs=19.325 flightCalls=84549
CPC_ROUTE target='portal_at_78_source' totalMs=275.244 navMs=10.099 probes=824 cacheHits=241 cacheSize=328 startMs=2.914 startCalls=20 flightMs=18.122 flightCalls=84549
CPC_ROUTE target='taxi_181' totalMs=62.754 navMs=0.363 probes=3 cacheHits=42 cacheSize=328 startMs=0.592 startCalls=2 flightMs=2.539 flightCalls=21833
CPC_ROUTE target='taxi_181' totalMs=63.682 navMs=0.363 probes=3 cacheHits=42 cacheSize=328 startMs=0.606 startCalls=2 flightMs=2.866 flightCalls=21832
CPC_ROUTE target='taxi_181' totalMs=64.291 navMs=0.396 probes=3 cacheHits=41 cacheSize=328 startMs=0.812 startCalls=2 flightMs=3.189 flightCalls=21455
CPC_ROUTE target='taxi_181' totalMs=67.608 navMs=1.499 probes=11 cacheHits=53 cacheSize=328 startMs=0.609 startCalls=2 flightMs=2.871 flightCalls=22394
CPC_ROUTE target='portal_at_4367_target' totalMs=320.338 navMs=13.243 probes=910 cacheHits=284 cacheSize=328 startMs=2.891 startCalls=4 flightMs=16.410 flightCalls=97735
CPC_ROUTE target='portal_at_78_source' totalMs=305.210 navMs=11.622 probes=824 cacheHits=241 cacheSize=328 startMs=3.631 startCalls=20 flightMs=29.436 flightCalls=84548
CPC_ROUTE target='portal_at_78_source' totalMs=307.897 navMs=10.873 probes=824 cacheHits=241 cacheSize=328 startMs=3.573 startCalls=20 flightMs=30.696 flightCalls=84547
CPC_ROUTE target='taxi_181' totalMs=75.624 navMs=2.003 probes=15 cacheHits=51 cacheSize=328 startMs=0.721 startCalls=2 flightMs=5.455 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=71.471 navMs=1.878 probes=15 cacheHits=53 cacheSize=328 startMs=0.607 startCalls=2 flightMs=3.120 flightCalls=22957
CPC_ROUTE target='portal_at_4520_target' totalMs=263.794 navMs=7.913 probes=770 cacheHits=200 cacheSize=328 startMs=2.278 startCalls=4 flightMs=32.191 flightCalls=75469
CPC_ROUTE target='taxi_601' totalMs=180.605 navMs=1.718 probes=18 cacheHits=95 cacheSize=328 startMs=2.787 startCalls=13 flightMs=20.688 flightCalls=54638
CPC_ROUTE target='taxi_368' totalMs=54.312 navMs=3.355 probes=72 cacheHits=274 cacheSize=328 startMs=0.466 startCalls=2 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_902_source' totalMs=65.035 navMs=1.563 probes=18 cacheHits=97 cacheSize=328 startMs=38.585 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_902_source' totalMs=62.092 navMs=1.564 probes=18 cacheHits=97 cacheSize=328 startMs=35.897 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_902_source' totalMs=61.616 navMs=1.617 probes=18 cacheHits=97 cacheSize=328 startMs=35.515 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_902_source' totalMs=60.952 navMs=1.557 probes=18 cacheHits=97 cacheSize=328 startMs=34.938 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.812 navMs=1.546 probes=18 cacheHits=99 cacheSize=328 startMs=35.655 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.155 navMs=1.550 probes=18 cacheHits=99 cacheSize=328 startMs=35.397 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=61.859 navMs=1.594 probes=18 cacheHits=99 cacheSize=328 startMs=34.873 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=61.735 navMs=1.689 probes=18 cacheHits=99 cacheSize=328 startMs=34.671 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=52.294 navMs=3.388 probes=77 cacheHits=272 cacheSize=328 startMs=2.646 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=164.754 navMs=1.661 probes=19 cacheHits=103 cacheSize=328 startMs=1.320 startCalls=5 flightMs=12.486 flightCalls=55823
CPC_ROUTE target='portal_at_1466_source' totalMs=213.435 navMs=7.757 probes=117 cacheHits=190 cacheSize=328 startMs=2.939 startCalls=20 flightMs=20.390 flightCalls=66259
CPC_ROUTE target='taxi_82' totalMs=149.869 navMs=1.673 probes=20 cacheHits=99 cacheSize=328 startMs=1.025 startCalls=2 flightMs=5.685 flightCalls=52992
CPC_ROUTE target='taxi_82' totalMs=203.652 navMs=1.796 probes=18 cacheHits=97 cacheSize=328 startMs=38.346 startCalls=80 flightMs=13.235 flightCalls=52246
CPC_ROUTE target='portal_at_1466_source' totalMs=222.882 navMs=8.266 probes=119 cacheHits=189 cacheSize=328 startMs=8.558 startCalls=20 flightMs=20.472 flightCalls=66259
CPC_ROUTE target='taxi_36' totalMs=163.618 navMs=1.668 probes=21 cacheHits=101 cacheSize=328 startMs=1.337 startCalls=5 flightMs=12.046 flightCalls=56072
CPC_ROUTE target='portal_at_1466_source' totalMs=217.534 navMs=8.193 probes=119 cacheHits=190 cacheSize=328 startMs=7.667 startCalls=20 flightMs=16.466 flightCalls=66445
CPC_ROUTE target='portal_at_1466_source' totalMs=231.056 navMs=8.601 probes=118 cacheHits=190 cacheSize=328 startMs=2.953 startCalls=20 flightMs=24.577 flightCalls=66258
CPC_ROUTE target='portal_at_1466_source' totalMs=236.173 navMs=8.689 probes=118 cacheHits=191 cacheSize=328 startMs=3.484 startCalls=20 flightMs=24.983 flightCalls=66444
CPC_ROUTE target='portal_at_1466_source' totalMs=237.060 navMs=8.499 probes=120 cacheHits=191 cacheSize=328 startMs=3.205 startCalls=20 flightMs=24.301 flightCalls=66642
CPC_PERF windowMs=30025 ticks=1163 players=110 travelMs=35.822 perceptionMs=427.297 transportMs=18.235 flightMs=2.627 actionsMs=8787.500 controllersMs=1723.486 slowGuid=61 slowMs=16.274
CPC_ROUTE target='taxi_36' totalMs=176.430 navMs=1.713 probes=19 cacheHits=103 cacheSize=328 startMs=1.429 startCalls=5 flightMs=17.723 flightCalls=55823
CPC_ROUTE target='taxi_36' totalMs=177.276 navMs=1.825 probes=21 cacheHits=101 cacheSize=328 startMs=1.324 startCalls=5 flightMs=18.555 flightCalls=56072
CPC_ROUTE target='portal_at_2171_target' totalMs=70.512 navMs=1.816 probes=36 cacheHits=126 cacheSize=328 startMs=39.175 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=70.918 navMs=1.803 probes=36 cacheHits=126 cacheSize=328 startMs=39.740 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=69.391 navMs=1.748 probes=36 cacheHits=126 cacheSize=328 startMs=38.094 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2171_target' totalMs=69.754 navMs=1.827 probes=36 cacheHits=126 cacheSize=328 startMs=39.246 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=180.880 navMs=1.730 probes=19 cacheHits=103 cacheSize=328 startMs=1.545 startCalls=5 flightMs=21.338 flightCalls=55823
CPC_ROUTE target='taxi_36' totalMs=178.010 navMs=1.706 probes=19 cacheHits=102 cacheSize=328 startMs=1.132 startCalls=4 flightMs=19.101 flightCalls=55574
CPC_ROUTE target='taxi_36' totalMs=223.673 navMs=1.876 probes=18 cacheHits=99 cacheSize=328 startMs=40.286 startCalls=80 flightMs=19.569 flightCalls=55074
CPC_ROUTE target='taxi_36' totalMs=221.946 navMs=1.768 probes=18 cacheHits=99 cacheSize=328 startMs=38.127 startCalls=79 flightMs=19.464 flightCalls=55074
CPC_ROUTE target='taxi_36' totalMs=224.075 navMs=1.704 probes=18 cacheHits=99 cacheSize=328 startMs=38.883 startCalls=78 flightMs=18.442 flightCalls=55074
CPC_ROUTE target='taxi_36' totalMs=225.034 navMs=1.906 probes=18 cacheHits=99 cacheSize=328 startMs=38.003 startCalls=77 flightMs=18.590 flightCalls=55074
CPC_ROUTE target='portal_at_2226_target' totalMs=52.385 navMs=3.553 probes=74 cacheHits=272 cacheSize=328 startMs=2.201 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=445.535 navMs=9.749 probes=839 cacheHits=341 cacheSize=328 startMs=2.163 startCalls=16 flightMs=170.645 flightCalls=91970
CPC_ROUTE target='taxi_601' totalMs=162.956 navMs=1.644 probes=18 cacheHits=95 cacheSize=328 startMs=3.006 startCalls=13 flightMs=10.808 flightCalls=54638
CPC_ROUTE target='portal_at_2226_target' totalMs=51.902 navMs=3.537 probes=77 cacheHits=272 cacheSize=328 startMs=1.712 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=64.623 navMs=1.587 probes=18 cacheHits=97 cacheSize=328 startMs=36.755 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=64.572 navMs=1.614 probes=18 cacheHits=97 cacheSize=328 startMs=36.152 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=62.550 navMs=1.602 probes=18 cacheHits=97 cacheSize=328 startMs=35.446 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2534_target' totalMs=62.500 navMs=1.592 probes=18 cacheHits=97 cacheSize=328 startMs=35.013 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_7' totalMs=62.875 navMs=1.605 probes=18 cacheHits=94 cacheSize=328 startMs=36.075 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_7' totalMs=61.912 navMs=1.577 probes=18 cacheHits=94 cacheSize=328 startMs=35.868 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_7' totalMs=62.063 navMs=1.605 probes=18 cacheHits=94 cacheSize=328 startMs=35.859 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_7' totalMs=61.247 navMs=1.630 probes=18 cacheHits=94 cacheSize=328 startMs=35.048 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=64.442 navMs=1.562 probes=27 cacheHits=118 cacheSize=328 startMs=35.820 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=63.925 navMs=1.617 probes=27 cacheHits=118 cacheSize=328 startMs=35.699 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=62.870 navMs=1.575 probes=27 cacheHits=118 cacheSize=328 startMs=35.070 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_101_source' totalMs=62.948 navMs=1.590 probes=27 cacheHits=118 cacheSize=328 startMs=34.759 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2226_target' totalMs=51.574 navMs=3.187 probes=72 cacheHits=272 cacheSize=328 startMs=1.759 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=1282.089 navMs=7.986 probes=96 cacheHits=189 cacheSize=328 startMs=3.315 startCalls=20 flightMs=1082.774 flightCalls=65129
CPC_ROUTE target='taxi_181' totalMs=67.394 navMs=0.367 probes=3 cacheHits=40 cacheSize=328 startMs=0.593 startCalls=2 flightMs=5.003 flightCalls=21645
CPC_ROUTE target='taxi_82' totalMs=172.518 navMs=1.794 probes=22 cacheHits=101 cacheSize=328 startMs=3.152 startCalls=4 flightMs=13.989 flightCalls=53739
CPC_ROUTE target='taxi_181' totalMs=68.317 navMs=0.446 probes=3 cacheHits=40 cacheSize=328 startMs=0.625 startCalls=2 flightMs=5.176 flightCalls=21644
CPC_ROUTE target='portal_at_4520_target' totalMs=258.986 navMs=7.929 probes=770 cacheHits=200 cacheSize=328 startMs=2.178 startCalls=4 flightMs=25.512 flightCalls=75469
CPC_ROUTE target='taxi_181' totalMs=68.437 navMs=0.471 probes=3 cacheHits=39 cacheSize=328 startMs=0.687 startCalls=2 flightMs=5.450 flightCalls=21267
CPC_ROUTE target='portal_at_2226_target' totalMs=56.352 navMs=3.718 probes=72 cacheHits=272 cacheSize=328 startMs=1.737 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_1468_source' totalMs=232.014 navMs=8.735 probes=98 cacheHits=189 cacheSize=328 startMs=8.514 startCalls=20 flightMs=26.017 flightCalls=65318
CPC_ROUTE target='taxi_181' totalMs=72.781 navMs=1.660 probes=11 cacheHits=51 cacheSize=328 startMs=0.655 startCalls=2 flightMs=5.219 flightCalls=22206
CPC_ROUTE target='taxi_181' totalMs=80.389 navMs=2.312 probes=15 cacheHits=51 cacheSize=328 startMs=0.868 startCalls=2 flightMs=7.716 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=79.249 navMs=2.033 probes=15 cacheHits=51 cacheSize=328 startMs=0.882 startCalls=2 flightMs=6.121 flightCalls=22769
CPC_ROUTE target='portal_at_1468_source' totalMs=235.690 navMs=8.731 probes=98 cacheHits=189 cacheSize=328 startMs=8.394 startCalls=20 flightMs=26.250 flightCalls=65317
CPC_ROUTE target='portal_at_1468_source' totalMs=230.758 navMs=7.880 probes=97 cacheHits=190 cacheSize=328 startMs=3.167 startCalls=20 flightMs=26.285 flightCalls=65317
CPC_ROUTE target='portal_at_1468_source' totalMs=232.732 navMs=7.918 probes=97 cacheHits=190 cacheSize=328 startMs=3.259 startCalls=20 flightMs=26.451 flightCalls=65316
CPC_ROUTE target='portal_at_1468_source' totalMs=234.959 navMs=8.575 probes=98 cacheHits=190 cacheSize=328 startMs=3.304 startCalls=20 flightMs=25.585 flightCalls=65502
@@ -0,0 +1,173 @@
CPC_ROUTE target='taxi_456' totalMs=2214.858 navMs=1.314 probes=41 cacheHits=2 cacheSize=34 startMs=0.645 startCalls=2 flightMs=2148.827 flightCalls=21457
CPC_ROUTE target='taxi_456' totalMs=355.109 navMs=0.365 probes=7 cacheHits=36 cacheSize=34 startMs=0.637 startCalls=2 flightMs=292.767 flightCalls=21456
CPC_ROUTE target='taxi_456' totalMs=352.997 navMs=0.417 probes=7 cacheHits=35 cacheSize=34 startMs=0.741 startCalls=2 flightMs=291.048 flightCalls=21079
CPC_ROUTE target='taxi_456' totalMs=365.696 navMs=1.689 probes=27 cacheHits=35 cacheSize=46 startMs=0.742 startCalls=2 flightMs=300.568 flightCalls=22018
CPC_ROUTE target='taxi_456' totalMs=386.600 navMs=2.325 probes=19 cacheHits=47 cacheSize=67 startMs=0.608 startCalls=2 flightMs=315.423 flightCalls=22582
CPC_ROUTE target='taxi_456' totalMs=374.697 navMs=1.899 probes=19 cacheHits=47 cacheSize=67 startMs=0.678 startCalls=2 flightMs=306.477 flightCalls=22581
CPC_ROUTE target='goldshire_center' totalMs=3867.203 navMs=4.198 probes=66 cacheHits=64 cacheSize=94 startMs=53.354 startCalls=7 flightMs=3672.038 flightCalls=52524
CPC_ROUTE target='portal_at_2530_target' totalMs=348.080 navMs=0.394 probes=7 cacheHits=37 cacheSize=94 startMs=0.000 startCalls=0 flightMs=288.229 flightCalls=20893
CPC_ROUTE target='taxi_181' totalMs=366.703 navMs=0.487 probes=11 cacheHits=41 cacheSize=98 startMs=0.604 startCalls=2 flightMs=302.451 flightCalls=22329
CPC_ROUTE target='taxi_181' totalMs=1006.625 navMs=8.239 probes=154 cacheHits=121 cacheSize=139 startMs=0.734 startCalls=2 flightMs=830.220 flightCalls=64572
CPC_ROUTE target='taxi_181' totalMs=1008.236 navMs=7.298 probes=113 cacheHits=162 cacheSize=141 startMs=0.620 startCalls=2 flightMs=835.049 flightCalls=64571
CPC_ROUTE target='taxi_181' totalMs=438.898 navMs=3.017 probes=41 cacheHits=72 cacheSize=141 startMs=0.658 startCalls=2 flightMs=355.826 flightCalls=26996
CPC_ROUTE target='taxi_181' totalMs=1008.990 navMs=7.100 probes=113 cacheHits=162 cacheSize=141 startMs=0.674 startCalls=2 flightMs=835.934 flightCalls=64381
CPC_ROUTE target='taxi_181' totalMs=1009.359 navMs=7.109 probes=114 cacheHits=162 cacheSize=142 startMs=0.737 startCalls=2 flightMs=831.265 flightCalls=64756
CPC_ROUTE target='taxi_36' totalMs=66.146 navMs=1.299 probes=9 cacheHits=5 cacheSize=143 startMs=9.039 startCalls=21 flightMs=44.930 flightCalls=3271
CPC_ROUTE target='goldshire_center' totalMs=828.349 navMs=2.907 probes=37 cacheHits=90 cacheSize=143 startMs=6.016 startCalls=16 flightMs=685.080 flightCalls=52277
CPC_ROUTE target='portal_at_5379_source' totalMs=3269.795 navMs=26.716 probes=2206 cacheHits=444 cacheSize=227 startMs=1.050 startCalls=3 flightMs=2684.359 flightCalls=205764
CPC_ROUTE target='taxi_388' totalMs=351.810 navMs=0.378 probes=7 cacheHits=36 cacheSize=227 startMs=0.623 startCalls=2 flightMs=291.863 flightCalls=21457
CPC_PERF windowMs=33650 ticks=2177 players=7 travelMs=2.189 perceptionMs=4.992 transportMs=0.288 flightMs=2.549 actionsMs=17838.969 controllersMs=341.025 slowGuid=26 slowMs=125.890
CPC_ROUTE target='taxi_388' totalMs=352.889 navMs=0.386 probes=7 cacheHits=36 cacheSize=227 startMs=0.613 startCalls=2 flightMs=290.815 flightCalls=21456
CPC_ROUTE target='taxi_388' totalMs=347.788 navMs=0.385 probes=7 cacheHits=35 cacheSize=227 startMs=0.659 startCalls=2 flightMs=285.779 flightCalls=21079
CPC_ROUTE target='portal_at_5379_source' totalMs=3315.129 navMs=27.010 probes=2122 cacheHits=528 cacheSize=227 startMs=0.490 startCalls=1 flightMs=2730.767 flightCalls=205764
CPC_ROUTE target='taxi_388' totalMs=365.517 navMs=1.488 probes=15 cacheHits=47 cacheSize=227 startMs=0.644 startCalls=2 flightMs=299.178 flightCalls=22017
CPC_ROUTE target='taxi_388' totalMs=374.289 navMs=1.884 probes=19 cacheHits=47 cacheSize=227 startMs=0.750 startCalls=2 flightMs=304.493 flightCalls=22581
CPC_ROUTE target='goldshire_center' totalMs=825.604 navMs=3.228 probes=39 cacheHits=91 cacheSize=227 startMs=2.671 startCalls=7 flightMs=687.870 flightCalls=52524
CPC_ROUTE target='taxi_388' totalMs=339.390 navMs=0.364 probes=7 cacheHits=36 cacheSize=227 startMs=0.602 startCalls=2 flightMs=280.987 flightCalls=20329
CPC_ROUTE target='taxi_388' totalMs=339.961 navMs=0.386 probes=7 cacheHits=36 cacheSize=227 startMs=0.700 startCalls=2 flightMs=278.712 flightCalls=20328
CPC_ROUTE target='taxi_388' totalMs=334.244 navMs=0.388 probes=7 cacheHits=35 cacheSize=227 startMs=0.755 startCalls=2 flightMs=275.034 flightCalls=19951
CPC_ROUTE target='taxi_388' totalMs=335.390 navMs=0.717 probes=8 cacheHits=38 cacheSize=227 startMs=0.598 startCalls=2 flightMs=275.492 flightCalls=19950
CPC_ROUTE target='taxi_388' totalMs=341.568 navMs=1.002 probes=9 cacheHits=41 cacheSize=227 startMs=0.612 startCalls=2 flightMs=280.585 flightCalls=20325
CPC_ROUTE target='taxi_388' totalMs=355.505 navMs=1.856 probes=18 cacheHits=47 cacheSize=227 startMs=0.633 startCalls=2 flightMs=288.773 flightCalls=21452
CPC_ROUTE target='taxi_388' totalMs=437.472 navMs=2.665 probes=40 cacheHits=70 cacheSize=227 startMs=0.608 startCalls=2 flightMs=359.287 flightCalls=26999
CPC_ROUTE target='taxi_388' totalMs=438.356 navMs=2.920 probes=41 cacheHits=73 cacheSize=227 startMs=0.599 startCalls=2 flightMs=356.948 flightCalls=27186
CPC_ROUTE target='taxi_388' totalMs=390.013 navMs=1.529 probes=26 cacheHits=63 cacheSize=227 startMs=0.638 startCalls=2 flightMs=318.018 flightCalls=23837
CPC_ROUTE target='taxi_388' totalMs=434.769 navMs=2.957 probes=41 cacheHits=72 cacheSize=227 startMs=0.673 startCalls=2 flightMs=352.308 flightCalls=26808
CPC_ROUTE target='taxi_388' totalMs=451.490 navMs=3.334 probes=45 cacheHits=73 cacheSize=227 startMs=0.624 startCalls=2 flightMs=366.583 flightCalls=27748
CPC_ROUTE target='taxi_128' totalMs=1796.072 navMs=12.401 probes=920 cacheHits=416 cacheSize=227 startMs=0.930 startCalls=15 flightMs=1492.389 flightCalls=102683
CPC_ROUTE target='taxi_388' totalMs=395.661 navMs=1.845 probes=21 cacheHits=58 cacheSize=227 startMs=0.642 startCalls=2 flightMs=322.357 flightCalls=24018
CPC_ROUTE target='goldshire_center' totalMs=928.417 navMs=3.438 probes=37 cacheHits=90 cacheSize=227 startMs=6.154 startCalls=16 flightMs=767.927 flightCalls=52277
CPC_ROUTE target='taxi_388' totalMs=528.031 navMs=3.336 probes=65 cacheHits=95 cacheSize=227 startMs=0.862 startCalls=2 flightMs=433.350 flightCalls=29804
CPC_ROUTE target='taxi_388' totalMs=1019.907 navMs=7.859 probes=113 cacheHits=162 cacheSize=227 startMs=0.633 startCalls=2 flightMs=840.089 flightCalls=64384
CPC_ROUTE target='taxi_388' totalMs=1014.268 navMs=7.338 probes=113 cacheHits=162 cacheSize=227 startMs=0.629 startCalls=2 flightMs=841.819 flightCalls=64383
CPC_ROUTE target='taxi_388' totalMs=1016.920 navMs=7.526 probes=113 cacheHits=162 cacheSize=227 startMs=0.608 startCalls=2 flightMs=841.615 flightCalls=64382
CPC_ROUTE target='portal_at_6581_source' totalMs=992.963 navMs=3.750 probes=95 cacheHits=152 cacheSize=227 startMs=1.056 startCalls=3 flightMs=830.411 flightCalls=62709
CPC_ROUTE target='taxi_388' totalMs=1013.281 navMs=7.446 probes=113 cacheHits=163 cacheSize=227 startMs=0.609 startCalls=2 flightMs=834.491 flightCalls=64757
CPC_ROUTE target='taxi_388' totalMs=3557.661 navMs=3.699 probes=69 cacheHits=97 cacheSize=227 startMs=0.603 startCalls=2 flightMs=3457.871 flightCalls=30929
CPC_ROUTE target='portal_at_4367_target' totalMs=1700.270 navMs=11.733 probes=937 cacheHits=264 cacheSize=229 startMs=2.024 startCalls=3 flightMs=1408.310 flightCalls=97847
CPC_PERF windowMs=30330 ticks=257 players=16 travelMs=17.117 perceptionMs=18.270 transportMs=0.126 flightMs=0.181 actionsMs=23911.821 controllersMs=882.219 slowGuid=42 slowMs=372.233
CPC_ROUTE target='goldshire_center' totalMs=950.699 navMs=3.396 probes=39 cacheHits=91 cacheSize=229 startMs=2.700 startCalls=7 flightMs=808.811 flightCalls=52524
CPC_ROUTE target='goldshire_center' totalMs=839.236 navMs=2.791 probes=36 cacheHits=91 cacheSize=229 startMs=2.339 startCalls=6 flightMs=695.923 flightCalls=52275
CPC_ROUTE target='goldshire_center' totalMs=839.685 navMs=2.321 probes=34 cacheHits=90 cacheSize=229 startMs=2.078 startCalls=5 flightMs=697.528 flightCalls=52026
CPC_ROUTE target='goldshire_center' totalMs=837.566 navMs=2.388 probes=28 cacheHits=90 cacheSize=229 startMs=1.734 startCalls=4 flightMs=694.310 flightCalls=51775
CPC_ROUTE target='goldshire_center' totalMs=861.368 navMs=1.763 probes=23 cacheHits=89 cacheSize=229 startMs=5.048 startCalls=12 flightMs=707.412 flightCalls=51088
CPC_ROUTE target='taxi_181' totalMs=440.682 navMs=1.914 probes=27 cacheHits=64 cacheSize=229 startMs=0.648 startCalls=2 flightMs=362.693 flightCalls=24975
CPC_ROUTE target='portal_at_6581_source' totalMs=999.918 navMs=3.855 probes=102 cacheHits=154 cacheSize=229 startMs=0.507 startCalls=1 flightMs=835.102 flightCalls=62900
CPC_ROUTE target='taxi_181' totalMs=433.767 navMs=1.960 probes=27 cacheHits=64 cacheSize=229 startMs=0.593 startCalls=2 flightMs=353.015 flightCalls=24974
CPC_ROUTE target='taxi_36' totalMs=907.594 navMs=2.816 probes=52 cacheHits=130 cacheSize=231 startMs=3.063 startCalls=20 flightMs=753.096 flightCalls=56337
CPC_ROUTE target='portal_at_6581_source' totalMs=989.096 navMs=3.637 probes=102 cacheHits=154 cacheSize=231 startMs=0.500 startCalls=1 flightMs=827.862 flightCalls=62900
CPC_ROUTE target='taxi_181' totalMs=412.041 navMs=2.131 probes=32 cacheHits=66 cacheSize=231 startMs=0.609 startCalls=2 flightMs=336.491 flightCalls=24973
CPC_ROUTE target='taxi_181' totalMs=382.943 navMs=1.650 probes=15 cacheHits=51 cacheSize=231 startMs=0.606 startCalls=2 flightMs=312.595 flightCalls=22642
CPC_ROUTE target='taxi_128' totalMs=1900.826 navMs=12.987 probes=920 cacheHits=360 cacheSize=231 startMs=2.891 startCalls=17 flightMs=1567.846 flightCalls=102683
CPC_ROUTE target='taxi_181' totalMs=425.473 navMs=2.544 probes=36 cacheHits=66 cacheSize=231 startMs=0.617 startCalls=2 flightMs=347.065 flightCalls=25536
CPC_ROUTE target='taxi_36' totalMs=915.483 navMs=2.613 probes=50 cacheHits=135 cacheSize=231 startMs=1.911 startCalls=20 flightMs=759.527 flightCalls=56834
CPC_ROUTE target='taxi_181' totalMs=404.432 navMs=2.032 probes=21 cacheHits=58 cacheSize=231 startMs=0.636 startCalls=2 flightMs=329.880 flightCalls=24394
CPC_ROUTE target='portal_at_4367_target' totalMs=1687.337 navMs=12.226 probes=937 cacheHits=264 cacheSize=231 startMs=1.009 startCalls=2 flightMs=1399.451 flightCalls=97846
CPC_ROUTE target='taxi_36' totalMs=932.673 navMs=2.733 probes=50 cacheHits=138 cacheSize=231 startMs=1.969 startCalls=20 flightMs=773.682 flightCalls=58327
CPC_ROUTE target='portal_at_4367_target' totalMs=1808.298 navMs=12.645 probes=937 cacheHits=264 cacheSize=231 startMs=38.847 startCalls=80 flightMs=1464.229 flightCalls=97846
CPC_ROUTE target='taxi_395' totalMs=64.844 navMs=1.553 probes=41 cacheHits=131 cacheSize=231 startMs=36.555 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=63.426 navMs=1.357 probes=41 cacheHits=131 cacheSize=231 startMs=35.536 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=62.412 navMs=1.256 probes=41 cacheHits=131 cacheSize=231 startMs=34.870 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_395' totalMs=62.916 navMs=1.568 probes=41 cacheHits=131 cacheSize=231 startMs=34.692 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_388' totalMs=446.987 navMs=3.015 probes=41 cacheHits=73 cacheSize=231 startMs=0.600 startCalls=2 flightMs=368.376 flightCalls=27187
CPC_ROUTE target='taxi_388' totalMs=441.798 navMs=2.985 probes=41 cacheHits=73 cacheSize=231 startMs=0.619 startCalls=2 flightMs=360.639 flightCalls=27186
CPC_ROUTE target='taxi_128' totalMs=1795.166 navMs=12.147 probes=920 cacheHits=444 cacheSize=231 startMs=1.067 startCalls=15 flightMs=1499.299 flightCalls=102683
CPC_ROUTE target='taxi_36' totalMs=911.093 navMs=3.230 probes=49 cacheHits=132 cacheSize=231 startMs=7.806 startCalls=20 flightMs=748.218 flightCalls=56585
CPC_ROUTE target='taxi_388' totalMs=436.665 navMs=2.947 probes=41 cacheHits=72 cacheSize=231 startMs=0.620 startCalls=2 flightMs=355.027 flightCalls=26809
CPC_ROUTE target='taxi_36' totalMs=904.089 navMs=3.115 probes=49 cacheHits=132 cacheSize=231 startMs=7.624 startCalls=20 flightMs=740.913 flightCalls=56584
CPC_ROUTE target='taxi_388' totalMs=440.630 navMs=2.973 probes=41 cacheHits=72 cacheSize=231 startMs=0.599 startCalls=2 flightMs=360.589 flightCalls=26808
CPC_ROUTE target='taxi_388' totalMs=457.026 navMs=3.648 probes=45 cacheHits=73 cacheSize=231 startMs=0.676 startCalls=2 flightMs=371.320 flightCalls=27748
CPC_ROUTE target='portal_at_702_target' totalMs=59.898 navMs=0.846 probes=9 cacheHits=7 cacheSize=231 startMs=2.903 startCalls=20 flightMs=45.397 flightCalls=3271
CPC_ROUTE target='taxi_388' totalMs=411.799 navMs=1.898 probes=21 cacheHits=58 cacheSize=231 startMs=0.599 startCalls=2 flightMs=334.826 flightCalls=24206
CPC_ROUTE target='portal_at_2530_target' totalMs=53.145 navMs=3.224 probes=87 cacheHits=262 cacheSize=231 startMs=2.141 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_6354_source' totalMs=1493.130 navMs=9.602 probes=798 cacheHits=211 cacheSize=231 startMs=1.029 startCalls=3 flightMs=1255.668 flightCalls=79836
CPC_ROUTE target='taxi_388' totalMs=419.594 navMs=1.915 probes=29 cacheHits=64 cacheSize=231 startMs=0.619 startCalls=2 flightMs=345.306 flightCalls=24987
CPC_ROUTE target='taxi_388' totalMs=445.307 navMs=2.031 probes=29 cacheHits=64 cacheSize=231 startMs=0.751 startCalls=2 flightMs=364.946 flightCalls=24986
CPC_PERF windowMs=30377 ticks=20 players=23 travelMs=17.975 perceptionMs=25.773 transportMs=0.048 flightMs=0.058 actionsMs=26443.439 controllersMs=506.857 slowGuid=44 slowMs=64.554
CPC_ROUTE target='taxi_388' totalMs=429.092 navMs=2.395 probes=34 cacheHits=66 cacheSize=231 startMs=0.618 startCalls=2 flightMs=350.595 flightCalls=24985
CPC_ROUTE target='portal_at_322_target' totalMs=67.201 navMs=1.579 probes=41 cacheHits=131 cacheSize=231 startMs=37.613 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=66.358 navMs=1.528 probes=41 cacheHits=131 cacheSize=231 startMs=37.372 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=65.916 navMs=1.638 probes=41 cacheHits=131 cacheSize=231 startMs=36.682 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=64.859 navMs=1.457 probes=41 cacheHits=131 cacheSize=231 startMs=35.947 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_388' totalMs=387.530 navMs=1.539 probes=15 cacheHits=56 cacheSize=231 startMs=0.624 startCalls=2 flightMs=317.524 flightCalls=22702
CPC_ROUTE target='taxi_388' totalMs=438.113 navMs=2.783 probes=38 cacheHits=66 cacheSize=231 startMs=0.642 startCalls=2 flightMs=357.206 flightCalls=25548
CPC_ROUTE target='portal_at_4367_target' totalMs=1779.669 navMs=12.998 probes=938 cacheHits=265 cacheSize=231 startMs=2.988 startCalls=4 flightMs=1479.668 flightCalls=98342
CPC_ROUTE target='taxi_388' totalMs=446.276 navMs=2.627 probes=38 cacheHits=68 cacheSize=231 startMs=0.603 startCalls=2 flightMs=363.392 flightCalls=26299
CPC_ROUTE target='ironforge_gate' totalMs=65.538 navMs=1.668 probes=23 cacheHits=94 cacheSize=231 startMs=37.570 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=63.948 navMs=1.618 probes=23 cacheHits=94 cacheSize=231 startMs=36.394 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=64.270 navMs=1.566 probes=23 cacheHits=94 cacheSize=231 startMs=36.757 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_128' totalMs=1849.705 navMs=13.206 probes=920 cacheHits=360 cacheSize=231 startMs=2.819 startCalls=18 flightMs=1533.219 flightCalls=102683
CPC_ROUTE target='taxi_55' totalMs=391.835 navMs=1.064 probes=15 cacheHits=53 cacheSize=231 startMs=0.692 startCalls=2 flightMs=322.400 flightCalls=22897
CPC_ROUTE target='taxi_55' totalMs=389.674 navMs=1.063 probes=15 cacheHits=53 cacheSize=231 startMs=0.748 startCalls=2 flightMs=319.684 flightCalls=22896
CPC_ROUTE target='portal_at_322_target' totalMs=66.016 navMs=1.614 probes=41 cacheHits=131 cacheSize=231 startMs=36.805 startCalls=81 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=66.346 navMs=1.565 probes=41 cacheHits=131 cacheSize=231 startMs=37.279 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_322_target' totalMs=64.695 navMs=1.580 probes=41 cacheHits=131 cacheSize=231 startMs=35.934 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_55' totalMs=390.493 navMs=1.579 probes=21 cacheHits=58 cacheSize=231 startMs=0.638 startCalls=2 flightMs=320.259 flightCalls=23083
CPC_ROUTE target='taxi_55' totalMs=419.426 navMs=1.660 probes=16 cacheHits=56 cacheSize=231 startMs=0.603 startCalls=2 flightMs=343.306 flightCalls=23078
CPC_ROUTE target='taxi_55' totalMs=405.946 navMs=1.920 probes=25 cacheHits=58 cacheSize=231 startMs=0.612 startCalls=2 flightMs=331.939 flightCalls=23646
CPC_ROUTE target='taxi_55' totalMs=405.629 navMs=1.905 probes=25 cacheHits=60 cacheSize=231 startMs=0.601 startCalls=2 flightMs=332.701 flightCalls=24397
CPC_ROUTE target='taxi_36' totalMs=63.988 navMs=1.584 probes=23 cacheHits=94 cacheSize=231 startMs=36.716 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.725 navMs=1.465 probes=23 cacheHits=94 cacheSize=231 startMs=35.816 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=62.194 navMs=1.435 probes=23 cacheHits=94 cacheSize=231 startMs=35.432 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_36' totalMs=63.981 navMs=1.700 probes=23 cacheHits=94 cacheSize=231 startMs=35.064 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_2530_target' totalMs=52.710 navMs=3.088 probes=87 cacheHits=262 cacheSize=231 startMs=3.037 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=1050.896 navMs=7.390 probes=130 cacheHits=171 cacheSize=231 startMs=0.622 startCalls=2 flightMs=874.481 flightCalls=67018
CPC_ROUTE target='taxi_181' totalMs=1060.096 navMs=7.858 probes=130 cacheHits=171 cacheSize=231 startMs=0.622 startCalls=2 flightMs=876.981 flightCalls=67017
CPC_ROUTE target='taxi_181' totalMs=1040.842 navMs=7.682 probes=117 cacheHits=162 cacheSize=231 startMs=0.610 startCalls=2 flightMs=860.158 flightCalls=64576
CPC_ROUTE target='taxi_181' totalMs=1358.371 navMs=9.771 probes=130 cacheHits=171 cacheSize=231 startMs=0.708 startCalls=2 flightMs=1076.454 flightCalls=67015
CPC_ROUTE target='taxi_128' totalMs=2873.536 navMs=18.123 probes=920 cacheHits=444 cacheSize=231 startMs=1.445 startCalls=15 flightMs=2382.915 flightCalls=102683
CPC_ROUTE target='taxi_181' totalMs=1456.702 navMs=10.368 probes=127 cacheHits=170 cacheSize=231 startMs=1.009 startCalls=2 flightMs=1172.415 flightCalls=67011
CPC_ROUTE target='taxi_181' totalMs=1158.368 navMs=8.871 probes=130 cacheHits=172 cacheSize=231 startMs=0.917 startCalls=2 flightMs=947.491 flightCalls=67201
CPC_ROUTE target='taxi_601' totalMs=6813.609 navMs=2.425 probes=23 cacheHits=90 cacheSize=231 startMs=3.301 startCalls=13 flightMs=6606.420 flightCalls=54638
CPC_PERF windowMs=32728 ticks=246 players=32 travelMs=34.747 perceptionMs=48.057 transportMs=0.090 flightMs=0.103 actionsMs=26365.464 controllersMs=731.614 slowGuid=50 slowMs=74.783
CPC_ROUTE target='ironforge_gate' totalMs=72.716 navMs=1.732 probes=23 cacheHits=108 cacheSize=231 startMs=39.323 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=70.580 navMs=1.773 probes=23 cacheHits=108 cacheSize=231 startMs=39.258 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=70.403 navMs=1.851 probes=23 cacheHits=108 cacheSize=231 startMs=39.527 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=71.045 navMs=1.689 probes=23 cacheHits=108 cacheSize=231 startMs=40.298 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_170' totalMs=1950.251 navMs=13.290 probes=1023 cacheHits=308 cacheSize=231 startMs=3.118 startCalls=16 flightMs=1603.719 flightCalls=106366
CPC_ROUTE target='taxi_601' totalMs=958.686 navMs=2.278 probes=23 cacheHits=90 cacheSize=231 startMs=3.555 startCalls=12 flightMs=769.965 flightCalls=54638
CPC_ROUTE target='taxi_181' totalMs=389.998 navMs=0.581 probes=7 cacheHits=36 cacheSize=231 startMs=0.694 startCalls=2 flightMs=313.944 flightCalls=21645
CPC_ROUTE target='portal_at_4319_source' totalMs=1610.486 navMs=12.391 probes=868 cacheHits=236 cacheSize=231 startMs=1.097 startCalls=3 flightMs=1315.143 flightCalls=84888
CPC_ROUTE target='taxi_181' totalMs=389.309 navMs=0.420 probes=7 cacheHits=36 cacheSize=231 startMs=0.644 startCalls=2 flightMs=312.377 flightCalls=21644
CPC_ROUTE target='taxi_181' totalMs=378.313 navMs=0.416 probes=7 cacheHits=35 cacheSize=231 startMs=0.610 startCalls=2 flightMs=302.771 flightCalls=21267
CPC_ROUTE target='taxi_181' totalMs=396.136 navMs=2.085 probes=15 cacheHits=47 cacheSize=231 startMs=0.761 startCalls=2 flightMs=316.087 flightCalls=22206
CPC_ROUTE target='taxi_181' totalMs=404.777 navMs=2.247 probes=19 cacheHits=47 cacheSize=231 startMs=0.642 startCalls=2 flightMs=324.399 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=410.924 navMs=2.537 probes=19 cacheHits=47 cacheSize=231 startMs=0.640 startCalls=2 flightMs=329.153 flightCalls=22769
CPC_ROUTE target='taxi_128' totalMs=1923.169 navMs=13.909 probes=920 cacheHits=454 cacheSize=231 startMs=4.204 startCalls=18 flightMs=1572.602 flightCalls=102683
CPC_ROUTE target='taxi_23' totalMs=57.387 navMs=3.922 probes=87 cacheHits=262 cacheSize=231 startMs=1.902 startCalls=3 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=546.985 navMs=0.731 probes=7 cacheHits=36 cacheSize=231 startMs=2.066 startCalls=2 flightMs=434.947 flightCalls=21645
CPC_ROUTE target='taxi_181' totalMs=469.655 navMs=0.609 probes=7 cacheHits=36 cacheSize=235 startMs=0.912 startCalls=2 flightMs=379.540 flightCalls=21644
CPC_ROUTE target='ironforge_gate' totalMs=70.336 navMs=1.826 probes=19 cacheHits=101 cacheSize=235 startMs=40.145 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=70.823 navMs=1.806 probes=19 cacheHits=101 cacheSize=235 startMs=40.828 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=80.744 navMs=1.833 probes=19 cacheHits=101 cacheSize=235 startMs=48.158 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=68.158 navMs=1.755 probes=19 cacheHits=101 cacheSize=235 startMs=37.602 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=314.097 navMs=0.417 probes=3 cacheHits=39 cacheSize=235 startMs=0.597 startCalls=2 flightMs=262.588 flightCalls=21267
CPC_ROUTE target='taxi_181' totalMs=329.218 navMs=1.804 probes=11 cacheHits=51 cacheSize=235 startMs=0.621 startCalls=2 flightMs=273.416 flightCalls=22206
CPC_ROUTE target='taxi_23' totalMs=54.151 navMs=3.330 probes=74 cacheHits=270 cacheSize=235 startMs=1.711 startCalls=4 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=338.334 navMs=2.017 probes=15 cacheHits=51 cacheSize=235 startMs=0.618 startCalls=2 flightMs=280.241 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=338.514 navMs=2.154 probes=15 cacheHits=51 cacheSize=235 startMs=0.627 startCalls=2 flightMs=277.723 flightCalls=22769
CPC_ROUTE target='taxi_310' totalMs=3372.660 navMs=38.337 probes=2021 cacheHits=637 cacheSize=326 startMs=9.153 startCalls=21 flightMs=2743.776 flightCalls=208560
CPC_ROUTE target='taxi_181' totalMs=351.639 navMs=0.385 probes=3 cacheHits=42 cacheSize=326 startMs=0.707 startCalls=2 flightMs=294.906 flightCalls=21833
CPC_ROUTE target='taxi_181' totalMs=352.368 navMs=0.385 probes=3 cacheHits=42 cacheSize=326 startMs=0.679 startCalls=2 flightMs=294.131 flightCalls=21832
CPC_ROUTE target='portal_at_4151_source' totalMs=71.722 navMs=1.868 probes=36 cacheHits=136 cacheSize=326 startMs=39.923 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=72.085 navMs=1.823 probes=36 cacheHits=136 cacheSize=326 startMs=40.510 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=71.600 navMs=1.776 probes=36 cacheHits=136 cacheSize=326 startMs=40.024 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4151_source' totalMs=65.400 navMs=1.656 probes=36 cacheHits=136 cacheSize=326 startMs=36.448 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=313.389 navMs=0.400 probes=3 cacheHits=41 cacheSize=326 startMs=0.620 startCalls=2 flightMs=262.560 flightCalls=21455
CPC_ROUTE target='taxi_627' totalMs=66.384 navMs=1.796 probes=18 cacheHits=97 cacheSize=326 startMs=37.792 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='taxi_181' totalMs=334.102 navMs=1.674 probes=11 cacheHits=53 cacheSize=326 startMs=0.809 startCalls=2 flightMs=277.205 flightCalls=22394
CPC_ROUTE target='taxi_181' totalMs=337.939 navMs=1.989 probes=15 cacheHits=51 cacheSize=326 startMs=0.613 startCalls=2 flightMs=280.709 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=349.130 navMs=2.100 probes=15 cacheHits=53 cacheSize=326 startMs=0.605 startCalls=2 flightMs=285.402 flightCalls=22957
CPC_ROUTE target='portal_at_7155_source' totalMs=880.780 navMs=3.946 probes=66 cacheHits=148 cacheSize=326 startMs=1.011 startCalls=3 flightMs=734.175 flightCalls=58385
CPC_ROUTE target='taxi_181' totalMs=340.819 navMs=0.395 probes=3 cacheHits=42 cacheSize=326 startMs=0.755 startCalls=2 flightMs=282.663 flightCalls=21833
CPC_ROUTE target='taxi_181' totalMs=341.864 navMs=0.546 probes=3 cacheHits=42 cacheSize=326 startMs=0.611 startCalls=2 flightMs=282.281 flightCalls=21832
CPC_ROUTE target='ironforge_gate' totalMs=73.997 navMs=2.026 probes=18 cacheHits=102 cacheSize=326 startMs=41.525 startCalls=80 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=72.531 navMs=1.779 probes=18 cacheHits=102 cacheSize=326 startMs=40.446 startCalls=79 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=69.623 navMs=1.763 probes=18 cacheHits=102 cacheSize=326 startMs=39.845 startCalls=78 flightMs=0.000 flightCalls=0
CPC_ROUTE target='ironforge_gate' totalMs=71.164 navMs=2.174 probes=18 cacheHits=102 cacheSize=326 startMs=37.811 startCalls=77 flightMs=0.000 flightCalls=0
CPC_ROUTE target='portal_at_4367_target' totalMs=1517.644 navMs=13.297 probes=909 cacheHits=283 cacheSize=326 startMs=3.320 startCalls=5 flightMs=1240.960 flightCalls=97240
CPC_ROUTE target='taxi_181' totalMs=344.380 navMs=0.415 probes=3 cacheHits=41 cacheSize=326 startMs=0.756 startCalls=2 flightMs=284.913 flightCalls=21455
CPC_PERF windowMs=34228 ticks=30 players=41 travelMs=34.890 perceptionMs=74.125 transportMs=0.111 flightMs=0.098 actionsMs=23621.628 controllersMs=3348.595 slowGuid=26 slowMs=1434.777
CPC_ROUTE target='taxi_181' totalMs=355.210 navMs=2.714 probes=11 cacheHits=53 cacheSize=326 startMs=0.604 startCalls=2 flightMs=290.524 flightCalls=22394
CPC_ROUTE target='taxi_181' totalMs=335.283 navMs=1.963 probes=15 cacheHits=51 cacheSize=326 startMs=0.597 startCalls=2 flightMs=276.075 flightCalls=22770
CPC_ROUTE target='taxi_181' totalMs=346.000 navMs=2.158 probes=15 cacheHits=53 cacheSize=326 startMs=0.837 startCalls=2 flightMs=285.424 flightCalls=22957
@@ -0,0 +1,189 @@
TEST tests/clientless/test_adventure_area_node.py
Production area destination excludes outside and unreachable graph nodes.
TEST tests/clientless/test_adventure_async_database.py
Async creation DB contracts: prepared connection masks, native security column names, no future waits, successful-save cache publication and world-update-only loader hook passed
TEST tests/clientless/test_adventure_behavior_policy.py
24-hour generation, shared intents with changing destinations, broad location classification and repetition penalties passed.
TEST tests/clientless/test_adventure_class_rotation.py
Production class rotations: persistent PvE solo pools, native rank aura IDs, combo/holy power/proc/execute/resource gates, Eclipse and healer coverage passed
TEST tests/clientless/test_adventure_combat_exercise.py
Production exercise: stance/charge/melee/casts, native validation delegation, bounded lifetime, invalid targets and unchanged native phases passed.
TEST tests/clientless/test_adventure_combat_preparation.py
Production talent learner: native tiers/dependencies/class gates, all 26 legal level60 points, no capstone bypass and repeat safety passed.
TEST tests/clientless/test_adventure_combat_reactions.py
Production combat focus, damage ordering, risk filters, corpse radius/delay, flight/group override, blocked escape, danger avoidance and malus-free persisted fallback passed.
TEST tests/clientless/test_adventure_day_persistence.py
Production day planner: all 24 TINYINT slots restored across logins, incomplete/old-day replacement, full transaction and curiosity/level weighting passed
TEST tests/clientless/test_adventure_economy.py
Economy: native service roles, friendly/phase/LOS/bounds gates, no bot service targets and coherent performative cues passed.
TEST tests/clientless/test_adventure_economy_catalog.py
Economy catalog: eleven actions, three faction-bound service anchors, native flag gates and idempotent preservation passed.
TEST tests/clientless/test_adventure_encounter.py
Production encounters: bot-only exclusion, mixed mode, extension hook, wait/revive, wipe fallback/reentry/gather/return, living-player priority, kick exit and offline cleanup passed
TEST tests/clientless/test_adventure_equipment_maintenance.py
Production gear maintenance: same birth/retention gate rejects wrong armor/stats, malformed effects, level, temporary, reputation, map, holiday, native-use and slot mismatches passed
TEST tests/clientless/test_adventure_exploration.py
Exploration: visible native props only, no chests/traps/furniture, phase/map/LOS/range gates and contextual preparation passed.
TEST tests/clientless/test_adventure_exploration_catalog.py
Exploration catalog: ten actions, shared scenes, default wander replacement, explicit category eligibility and preserved edits passed.
TEST tests/clientless/test_adventure_generator_equipment.py
Production equipment affinity: mana-only/direct/triggered procs, caster/physical stat effects and bounded cycles passed
TEST tests/clientless/test_adventure_generator_ownership.py
Production generator commands: batch bounds, dedicated ownership, persistent/online/removing retirement protection and retired login refusal passed
TEST tests/clientless/test_adventure_generator_policy.py
Production generator: 6144 cultural names and 61440 real Lua profiles, profession coherence, personality ranges, escaping and equipment/armor gates passed
TEST tests/clientless/test_adventure_graph_handover.py
Production graph handover waits for ship/taxi/flight/teleport and stops at safe road/node boundaries.
TEST tests/clientless/test_adventure_ground_avoidance.py
Production ground avoidance: harmful/friendly, phase169, height, reachable safe endpoint, rejected paths and reuse without cast/movement thrashing passed
TEST tests/clientless/test_adventure_group_plan.py
Production group plans: leader meeting/goal/deadline inheritance, untouched personal day, manual preparation and instance-state guards passed.
TEST tests/clientless/test_adventure_group_travel.py
Production group travel: distinct slots, phase169 cliff safety, width, mounts, flight/kick landing, taxi grace, portal queue, bounded separation and recorded-road validation passed
TEST tests/clientless/test_adventure_groups.py
Production recruitment: capitals, different goals, native inviter leadership, joining existing groups, capacity/reservations, raid conversion, planned transition and local contact passed.
TEST tests/clientless/test_adventure_instance.py
Production instance lifecycle: time budget, true entry, denied/shared entry, native rear exit, restart, expired copy, late arrival, HP and return replay passed.
TEST tests/clientless/test_adventure_instance_autoresume.py
Deferred instance script: missing schema/visits stays idle; no login work on startup; saved visitors resume with Adventure controllers and native accounts.
TEST tests/clientless/test_adventure_instance_begin.py
Production entrance travel uses the existing location planner, requires mapping and retains normal social/area travel.
TEST tests/clientless/test_adventure_instance_catalog.py
Instance migrations: outside entrances only, native graph preserved, disabled/missing transitions excluded, edits and saved visits preserved.
TEST tests/clientless/test_adventure_instance_loader.py
Production instance recovery: no startup DB/login work, asynchronous delayed/paced manual recovery, generated-bot quota ownership, absent-schema compatibility and existing preparation ticks passed
TEST tests/clientless/test_adventure_instance_persistence.py
Production instance persistence: phases, original deadline, instance ID, transactional HP marker, failed commit and intent release passed.
TEST tests/clientless/test_adventure_intent_state.py
Production intent arrival, failed/partial travel, deadlines and safe schedule handover passed.
TEST tests/clientless/test_adventure_interactions.py
/tmp/tmpdotxz1_t/test.cpp: In member function ‘void AdventureInteractionMgr::Leave(Player*, Record&, const char*)’:
/tmp/tmpdotxz1_t/test.cpp:143:69: warning: unused parameter ‘reason’ [-Wunused-parameter]
143 | void AdventureInteractionMgr::Leave(Player* p,Record& r,char const* reason)
| ~~~~~~~~~~~~^~~~~~
production interaction manager: invitations, factions, reservations, follow, AFK and deferred departure passed
TEST tests/clientless/test_adventure_leisure.py
Leisure: substantial curved MMAP routes, mirrored return, interrupted return, rejected corridors, actual arrival, companion follow, riding, flight and fishing passed.
TEST tests/clientless/test_adventure_leisure_catalog.py
Leisure migration: native city anchor, shared scene references, pet-walk mapping and preservation of edited weights passed.
TEST tests/clientless/test_adventure_location_import.py
Locations: actual Debug SMALLINT reads retain continent IDs; explicit location eligibility and edited weight overrides passed.
TEST tests/clientless/test_adventure_manager_inventory.py
Production inventory maintenance: only full backpacks, native stack trimming, level-appropriate supplies, tools, leash, fishing pole, containers and untouched equipped slots passed
TEST tests/clientless/test_adventure_micro_reset.py
Micro cleanup ends physical local movement, preserves transit and does not stand up dead players.
TEST tests/clientless/test_adventure_native_lfg.py
Native LFG: ID26, localized standard channel, zone eligibility, join verification and population throttle passed
TEST tests/clientless/test_adventure_population.py
Production population: four independent faction/persistence targets, fair selection, pending reservations, retries, existing inventory, once-per-boot rotation and connected/persistent protection passed
TEST tests/clientless/test_adventure_profession_catalog.py
Profession catalog: native workstation roles, no workshop/resource inference, idempotence and preserved edits passed.
TEST tests/clientless/test_adventure_profession_profile.py
Production profession parser, real Lua profiles, primary restrictions and secondary permissions passed.
TEST tests/clientless/test_adventure_profession_sightline.py
Native workstation working-surface sightline and blocked geometry rejection passed.
TEST tests/clientless/test_adventure_profession_targets.py
Production profession targets: native locks, phase/spawn/loot, stations, corpses, history and trainers passed.
TEST tests/clientless/test_adventure_profile_selection.py
Production profile selection: real Lua ID dictionaries, exact 9:1 companion weighting, zero/negative/infinite/NaN/oversized weights rejected and legacy companion fallback passed
TEST tests/clientless/test_adventure_pvp.py
Production PvP selector: level boundaries, radius, factions, native legality, navigation, intent, personality and resources passed.
TEST tests/clientless/test_adventure_repair_catalog.py
Repair action catalog: proper native service requirement, economy-only intent and preserved administrator weights passed.
TEST tests/clientless/test_adventure_rest.py
Recovery: authored places, bounds, arrival, occupancy, full rest duration, failure, reload and interruption passed.
TEST tests/clientless/test_adventure_rest_fire.py
Rest fire: shared scene mapping, additive migration, preserved weights and authored creation-place policy passed.
TEST tests/clientless/test_adventure_rest_space.py
Sleep footprint: furniture, body extent, overhead collision, ledges, stairs, missing heights, rotation and scale passed.
TEST tests/clientless/test_adventure_rest_targets.py
Native sleep targets: chair exclusion, phase, despawn, floor search, indoors, water, storey, occupancy, bed/surface preference passed.
TEST tests/clientless/test_adventure_retry_policy.py
Travel failures: exponential/jittered retry spacing, strict 30s bound and overflow safety passed
TEST tests/clientless/test_adventure_rotation.py
/tmp/tmpkjywp8re/test.cpp: In instantiation of ‘std::string Trinity::StringFormat(const char*, A ...) [with A = {}; std::string = std::__cxx11::basic_string<char>]’:
/tmp/tmpkjywp8re/test.cpp:22:126: required from ‘void Tx::PAppend(const char*, A ...) [with A = {}]’
22 | struct Tx{std::vector<std::string>sql;template<class...A>void PAppend(char const*f,A...a){sql.push_back(Trinity::StringFormat(f,a...));}};
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
/tmp/tmpkjywp8re/test.cpp:51:75: required from here
51 | auto barrier=CharacterDatabase.BeginTransaction();barrier->PAppend("DO 0");
| ~~~~~~~~~~~~~~~~^~~~~~~~
/tmp/tmpkjywp8re/test.cpp:11:113: warning: format not a string literal and no format arguments [-Wformat-security]
11 | namespace Trinity{template<class...A>std::string StringFormat(char const* f,A...args){char b[4096];std::snprintf(b,sizeof(b),f,args...);return b;}}
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
Production rotation: connected/native-online protection, ownership refusal, native delete failure, world cleanup failure and journal-retained retry before successful profile/plan/state removal passed
TEST tests/clientless/test_adventure_social.py
Production social flow: approach before talk, coherent greeting/talk/listen/farewell, lost targets, native chair confirmation and real fire confirmation passed.
TEST tests/clientless/test_adventure_social_fire.py
Shared fire: native detection/provisioning, buildings/city/parent/zone restrictions, existing fires and outdoor/water checks passed.
TEST tests/clientless/test_adventure_supplies.py
Production supplies: exact10% boundary, bandage-before-food, native lockout fallback, recovery completion, combat potions, mana-only drinking and daily/post-combat top-ups passed.
TEST tests/clientless/test_adventure_supply_catalog.py
Supply migrations: all five roles, level60 netherweave tier, editable/disabled catalog preservation and persistent daily stamp passed.
TEST tests/clientless/test_adventure_supply_items.py
Production native-item delegation: usable bandage tiers, native cooldown/lockout gates, real inventory consumption, self targeting and level60 secondary caps passed.
TEST tests/clientless/test_adventure_talent_templates.py
Canonical Cata PvE builds: 4.3.4 class/tree/rank/prerequisite gates, all 1..41 point budgets, solo selection coverage passed
TEST tests/clientless/test_adventure_training_catalog.py
Training catalog: real dummy requirement, leisure-only intent, bounded duration and preserved administrator weights passed.
TEST tests/clientless/test_adventure_walk.py
Production travel gait reaches native spline, survives repaths, prevents mounting and preserves legacy running defaults.
TEST tests/clientless/test_adventure_world_presence.py
Production world presence: persistent PvP, Worgen intent/arrival decisions, travel deferral, native Running Wild, human horse and aura cleanup passed
TEST tests/clientless/test_clientless_character_factory.py
Production native factory: character/profile atomicity, failed preparation/commit, cache publication order, account/security/name/cap gates passed
TEST tests/clientless/test_clientless_companion.py
Native companion: provisioning, delayed summon, ownership, real item target, leash confirmation/timeout, reuse and cleanup passed.
TEST tests/clientless/test_clientless_damage_notifications.py
Production damage handoff: 16 concurrent map-worker writers, ordered GUID-only events, clientless-only/positive damage gates and post-health notification passed.
TEST tests/clientless/test_clientless_near_teleport_observer.py
Production near-teleport observer packet includes actual mover GUID and destination; clientless timestamp refreshed, regular client timestamp preserved.
TEST tests/clientless/test_clientless_skill_preparation.py
Production offline skill preparation: native tier caps, no downgrading, rank/level/race/tier gates and no modification of online players passed
TEST tests/clientless/test_clientless_social_notifications.py
Production social/helper queues: concurrent GUID-only delivery, bounded queues, human/self/zero-damage gates, pet attribution and lethal-cleanup ordering passed
TEST tests/clientless/test_default_phase.py
Native PhaseShift: implicit/default 169 visibility, genuine custom-phase separation and reference updates passed.
TEST tests/clientless/test_empty_spell_effect.py
Native empty spell effects: poisoned-memory scaling initialization, Lock and Load cleared slot, active effect values and all-empty spell values passed
TEST tests/clientless/test_flight_area_query.py
Native terrain query map/phase, area/zone ordering and cache passed.
TEST tests/clientless/test_flight_handoff.py
Flight handoff before spline end, terminal landing, return corners, collision stop and actual distance passed.
TEST tests/clientless/test_flight_policy.py
Flight native eligibility, license/profile/zone policy, RP costs and fail-safe return decisions passed.
TEST tests/clientless/test_follow_spline_velocity.py
Native follow: actual player/creature spline velocity, client gait and independent follower speeds passed.
TEST tests/clientless/test_free_flight.py
Flight geometry passed: takeoff/landing, smoothed peak, ceiling, lateral/climbing avoidance, missing terrain and blocked corridors.
TEST tests/clientless/test_free_flight_planner.py
ground planner regressions and dynamic flight/node/location/virtual-exit integration passed
TEST tests/clientless/test_graph_probe_cache.py
Graph probe cache: exact directed/map/instance keys, successful geometry only, invalidation and bounded storage passed
TEST tests/clientless/test_ground_exit_continuation.py
optional exits: repeated probes, retained route, delayed success, forward resume, flight fallback passed
TEST tests/clientless/test_group_flight_follow.py
Moving-target flight: bounded phased corridors, obstacle hold, ceiling rejection, aerial formation hold, safe landing and return fallback passed
TEST tests/clientless/test_item_equip_cooldown.py
Native item equip cooldown: zero/sentinel/missing spells safely skipped, valid use cooldown preserved and longer/disabled cooldowns untouched passed
TEST tests/clientless/test_local_spline_segments.py
Production local spline clipping passes native path-length validation, tiny remainders and 1000 sampled paths.
TEST tests/clientless/test_lua_reload.py
Lua reload regression tests passed (production reload/bindings, real Lua 5.4).
TEST tests/clientless/test_player_pure_max_skill.py
Native pure skill cap: learned skills return stored cap; missing/deleted/zero-rank skills return0.
TEST tests/clientless/test_portal_transfer.py
Portal near/far ACK and denied same-map transfer regressions passed.
TEST tests/clientless/test_portal_use.py
Interactive portal native click, near/far/global ACK, denial, timeout and target checks passed.
Native portal destination discovery and unsupported/ambiguous spell rejection passed.
Production clientless ACK completion sequence increments only after completed near/far transfers.
TEST tests/clientless/test_shared_group_route.py
Production generic shared routes: same edges/taxi/free flight, independent execution state, final local goal, late catch-up, permissions and stale-goal rejection passed.
TEST tests/clientless/test_taxi_import_disabled.py
Taxi importer preserves disabled rows and their reasons.
TEST tests/clientless/test_transport.py
Transport dock, frame, recorder, cross-map copy and ride regressions passed
TEST tests/clientless/test_transport_grid_loading.py
Core transport grid initialization regressions passed (no CPC dependency).
TOTAL 86 FAILED []
+74
View File
@@ -0,0 +1,74 @@
# Clientless performance, 2026-10-29
The test installation has twelve logical CPUs. The initial process sample showed
95.1% of one CPU in the world thread and about9.9% in the single map worker.
The existing build is Debug (`-g`, no optimization); these are not production
Release/RelWithDebInfo capacity numbers. Production infrastructure was untouched.
## Observed bottleneck
External perf/ptrace sampling was denied by OS permissions. No kernel settings
were changed. CPC_PERF now reports steady-clock time in travel, perception,
transport, flight, actions and controllers every30 seconds. Times include blocking
and are not CPU percentages. The controller bucket includes login preparation.
CPC_ROUTE reports searches taking at least50ms, separating future MMAP probes,
current-player entry probes and dynamic flight-cost evaluations.
An initial31.923-second window with16 managed characters spent24.381 seconds
inside actions. Perception used27ms; controllers1.032 seconds. A later20-character
window spent27.872 seconds in actions over31.537 seconds. A traced warm search
made21,456 flight-cost calls and spent292.767ms there out of355.109ms total.
Static future MMAP probes used only0.365ms and current entry probes0.637ms.
## Changes
* Flight planning snapshots profile eligibility, minimum-distance configuration
and preferred zones once per synchronous planning scope. Scope exit clears it.
Actual departure checks still use live eligibility. Map licenses, area mount
rules and dynamic restrictions remain evaluated. Area keys now use exact binary
coordinates instead of repeatedly formatting and parsing floating-point text.
* Successful static ground probes between graph points are reused across plans.
Cache keys include map, instance, direction and exact endpoints. Storage is
bounded to32,768 proofs. No Player paths, negative/transient results, Detour
objects or tile pointers are retained. Graph reload clears the cache. Reload
the graph after replacing MMAP data. Execution still validates actual movement.
* Fixed graph neighborhoods are reused, bounded to4,096 entries. A cube shortlist
preserves the original exact distance, route-blocklist and path checks.
* Current-player entry probes are shared only within the same immutable planning
request, including its two search tiers. They never become global route proofs.
* Consecutive failed destinations back off from2–3 seconds to a maximum30 seconds,
with per-bot jitter. New intents reset this state. Deadlines are unchanged;
combat and immediate social/damage notifications are not delayed.
* The active test config uses MapUpdate.Threads=4, previously1. Network and database
worker settings were retained. Native map jobs can run concurrently; bot/Lua/
Player-manager work remains on its owning world thread. A single map update
is still serial. Arbitrarily parallelizing those managers would introduce races.
## Verification
All86 clientless tests pass. Tests cover scoped configuration reuse without extra
reads over1,000 estimates, fresh departure eligibility after the scope, exact area
coordinates and phase-aware terrain queries, unchanged routes, route-specific
blocklists, cold/warm proof reuse, map/instance isolation, bounded caches, two-way
map-thread notice handoff, bounded retry timing and immediate new-intent reset.
Native warm searches with about20,000 flight-cost calls fell to roughly34–37ms
in flight evaluation and around100ms total. Targets and actor positions differ
between live windows: this is an observed workload comparison, not a deterministic
before/after benchmark. Early cold queries can still take longer.
With retry backoff, a30.006-second window at84 managed characters spent7.114 seconds
in actions and1.848 seconds in controllers. With all110 bots online (50/5/50/5, no pending logins or loader error), the next
30.011-second window spent7.762 seconds in actions and1.612 seconds in controllers.
A10.069-second /proc sample recorded26.2% of one CPU in the main thread and
38.6%,37.6%,38.1%,38.5% in the four map workers. The process remained ready and
TCP8085 listening. Samples cover different live workloads; they do not establish
a fixed speedup or guaranteed capacity. Evidence is in checkpoints/2026-10-29-performance.
## Remaining limits
Compiler optimization is still required for a meaningful production capacity test.
No existing Debug CMake configuration was replaced. Native map updates, initial
character preparation and cold terrain loads can still produce individual spikes.
Four map workers do not parallelize one continent, and the bot controllers are
still world-thread owned. No claim is made that1,000 bots or production load has
been accepted. User in-game acceptance remains separate from automated tests.
+48
View File
@@ -0,0 +1,48 @@
# AdventureBot world presence and recruitment
Adventure controllers maintain native voluntary PvP flags, including the saved
CHARACTER_FLAG_PVP_DESIRED flag. Native faction, sanctuary and attack-validity
checks still decide whether a target can be attacked. DungeonBots are unchanged.
Worgen use native Altered Form during adventure, dungeon and raid activity,
combat and mixed player instances. At arrival for quiet activities, one random
form is chosen and retained; mounting, transport, flying, casting and death defer
the change until safe. Failed changes retry at most once every five seconds.
Logout clears pending presentation state.
A Worgen in altered form uses native Running Wild (87840) for ground travel.
Human form uses a horse; Brown Horse (458) and Two Forms (68996) are learned
where appropriate. Existing generated profiles with empty mount dictionaries
can still use these Worgen mounts. New generated Worgen profiles contain horses.
Dismounting removes the Running Wild aura before restoring normal run speed.
Flying continues through the existing native flight subsystem.
Recruitment uses native localized LookingForGroup channel ID26 (`SucheNachGruppe`
in deDE), with native capital eligibility. Test config Channel.RestrictedLfg=0
allows already grouped players and recruiting bot leaders to join. No custom
channel with a reserved standard-channel name is created. Human chat text is not parsed as
bot recruitment commands. Bot coordination uses structured intent and party
state. Announcements now include the actual next activity and destination;
logs contain GROUP_CHANNEL for diagnosis. The entire bot population shares a
15-second channel limit, with each advertiser waiting three to five minutes.
During groupformation, the normal microaction executor can now run. The additive
migration sql/custom/world/2026_10_29_01_adventure_group_preparation.sql adds gear
checks, listening, local NPC contact, gestures and bounded searches. Search walks
use verified MMAP paths, remain within an 18-yard path budget and return to their
origin; they also work indoors. Combat, native travel and group following retain
priority. Meeting points and group transition deadlines remain unchanged.
Bot leaders can invite nearby, visible, same-faction human players who are not
AFK, grouped, already invited, in combat or in transit. A whisper describing the
next activity and actual destination precedes the native party invitation. A
shared ten-minute per-player cooldown limits invitations across all bots. Native
party capacity and pending invitations are respected. On acceptance, the existing
player-leadership policy still transfers leadership to the human player.
Compilation and production-method adapter tests cover PvP persistence requests,
Worgen decisions and deferral, Running Wild/horse selection, dismount cleanup,
bounded indoor searches, intent handover and human recruitment/cooldowns. The
native server verifies startup and saved PvP flags; visual form transitions,
animations, channel visibility and invitation UI require in-game acceptance.
Ship boarding stands and transport routes are unchanged by this task.
@@ -0,0 +1,9 @@
-- Visible preparation at the existing capital meeting point; native local paths.
INSERT IGNORE INTO vcore_adventure_action
(action_key,kind,min_seconds,max_seconds,requirement,emote_id) VALUES
('group_search_walk','leisure',35,65,'walk',0),
('group_ready','emote',12,24,'',1);
INSERT IGNORE INTO vcore_adventure_action_intent(action_key,intent,weight) VALUES
('group_search_walk','groupformation',5),('group_ready','groupformation',2),
('profession_tools','groupformation',3),('social_listen','groupformation',1),
('social_npc','groupformation',1);
+10 -7
View File
@@ -347,6 +347,7 @@ void AdventureBehaviorMgr::SetWanted(Player * player, Record & r, std::string co
r.Deadline = deadline;
r.Dirty = true;
r.Tried.clear();
r.RetryTimer=0;
if (r.Instance.Active)
{
if (r.Instance.Stage>=AdventureInstancePolicy::Phase::Entering &&
@@ -485,8 +486,8 @@ void AdventureBehaviorMgr::Fallback(Player * player, Record & r)
r.WantedLocation = nearest->Point.Id;
r.Dirty = true;
r.State = Phase::Idle;
r.RetryTimer = 1000;
TC_LOG_WARN("server.adventurebot", "INTENT_FALLBACK guid=%u from='%s' to='%s' tried=%u", player->GetGUID().GetCounter(), r.Location.c_str(), nearest->Point.Id.c_str(), uint32(r.Tried.size()));
r.RetryTimer = AdventureBehaviorPolicy::TravelRetryMs(uint32(r.Tried.size()),std::uniform_int_distribution<uint32>(0,1000)(r.Random));
TC_LOG_WARN("server.adventurebot", "INTENT_FALLBACK guid=%u from='%s' to='%s' tried=%u retryMs=%u", player->GetGUID().GetCounter(), r.Location.c_str(), nearest->Point.Id.c_str(), uint32(r.Tried.size()),r.RetryTimer);
}
else
{
@@ -599,6 +600,7 @@ bool AdventureBehaviorMgr::LeisureAvailable(Player* p,Record const& r,AdventureM
auto rod=p->GetWeaponForAttack(BASE_ATTACK,true);float direction=0;
return rod && rod->GetTemplate()->GetSubClass()==ITEM_SUBCLASS_WEAPON_FISHING_POLE && FishingDirection(p,direction);
}
if (r.Intent=="groupformation") return a.Requirement=="walk";
if (r.Intent!="leisure") return false;
auto profile=sClientlessLuaEngine->GetAdventureProfile(p->GetGUID().GetCounter());
auto location=sAdventureLocationMgr->Find(r.Location);
@@ -628,12 +630,12 @@ bool AdventureBehaviorMgr::PlanLeisureWalk(Player* p, Record& r)
// Choose one substantial destination, then follow its actual ground corridor.
// Randomness selects the outing, never the next individual footstep.
float const offset=std::uniform_real_distribution<float>(0,6.2831853f)(r.Random);
float const budget=std::min(220.0f,std::max(100.0f,float(r.MicroTimer)*0.001f*1.0f));
float const budget=r.Intent=="groupformation"?18.0f:std::min(220.0f,std::max(100.0f,float(r.MicroTimer)*0.001f*1.0f));
float best=0;
for (unsigned i=0;i<16;++i)
{
float const angle=offset+float(i%8)*6.2831853f/8;
float const radius=i<8?std::min(150.0f,budget*0.7f):80.0f;
float const radius=r.Intent=="groupformation"?(i<8?12.0f:8.0f):(i<8?std::min(150.0f,budget*0.7f):80.0f);
Position goal;
goal.Relocate(s.Origin.GetPositionX()+std::cos(angle)*radius,
s.Origin.GetPositionY()+std::sin(angle)*radius,s.Origin.GetPositionZ());
@@ -660,12 +662,12 @@ bool AdventureBehaviorMgr::PlanLeisureWalk(Player* p, Record& r)
p->GetMap()->GetTerrain()->GetFullTerrainStatusForPosition(p->GetPhaseShift(),p->GetMapId(),point.x,point.y,point.z,terrain);
uint32 zone=0,area=0;
p->GetMap()->GetTerrain()->GetZoneAndAreaId(p->GetPhaseShift(),p->GetMapId(),zone,area,target);
if (!terrain.outdoors || (boundary && area!=boundary && zone!=boundary)) {valid=false;break;}
if ((r.Intent!="groupformation" && !terrain.outdoors) || (boundary && area!=boundary && zone!=boundary)) {valid=false;break;}
length+=step;section+=step;last=target;
if (section>=20) {outbound.push_back(target);section=0;}
}
float const span=s.Origin.GetExactDist(last);
if (!valid || length>budget || span<65 || length>span*2.5f || last.GetExactDist(goal)>1.5f) continue;
if (!valid || length>budget || span<(r.Intent=="groupformation"?4.0f:65.0f) || length>span*2.5f || last.GetExactDist(goal)>1.5f) continue;
if (outbound.empty() || outbound.back().GetExactDist(last)>2) outbound.push_back(last);
else outbound.back()=last;
if (span>best)
@@ -1388,12 +1390,13 @@ void AdventureBehaviorMgr::Update(Player * player, uint32 diff)
r.AnchorMap = player->GetMapId();
r.State = Phase::OnSite;
r.Detail = "performing intent at destination";
sClientlessLuaEngine->UpdateWorldPresence(player,r.Intent,true);
TC_LOG_INFO("server.adventurebot", "INTENT_ARRIVED guid=%u intent='%s' location='%s'", guid, r.Intent.c_str(), r.Location.c_str());
}
if (r.State == Phase::OnSite)
{
if ((r.Intent=="instance" || r.Intent=="raid")) {UpdateInstance(player,r,now);return;}
if(r.Intent=="groupformation")return;
if(sAdventureGroupMgr->FollowMember(player))return;
if (r.Recovery.Active)
{
@@ -11,6 +11,13 @@
namespace AdventureBehaviorPolicy
{
// Failed destinations may share the same disconnected local graph. Avoid a
// population-wide retry storm without suppressing combat or extending schedules.
inline unsigned TravelRetryMs(unsigned attempts,unsigned jitter)
{
unsigned shift=std::min(attempts?attempts-1:0u,4u);
return std::min(30000u,2000u*(1u<<shift)+std::min(jitter,1000u));
}
inline std::string Normalize(std::string text)
{
std::string result;
+3 -2
View File
@@ -448,13 +448,14 @@ Creature* AdventureCombatMgr::Proactive(Player* p) const
}
bool AdventureCombatMgr::Flee(Player* p,Record& r)
{
if(p->GetGroup())
auto profile=sClientlessLuaEngine->GetAdventureProfile(p->GetGUID().GetCounter());
if(p->GetGroup() || (profile && !profile->AllowRetreat))
{
if(r.Fleeing)
{
sClientlessTravelMgr->CancelTravel(p->GetGUID().GetCounter());p->StopMoving();
r.Fleeing=false;r.ThreatPositions.clear();
TC_LOG_INFO("server.adventurebot","COMBAT_FLEE_CANCEL guid=%u reason='group'",p->GetGUID().GetCounter());
TC_LOG_INFO("server.adventurebot","COMBAT_FLEE_CANCEL guid=%u reason='%s'",p->GetGUID().GetCounter(),p->GetGroup()?"group":"profile");
}
return false;
}
@@ -243,7 +243,7 @@ namespace
case 8:ground={10796,10799,8395};break;
case 10:ground={34795,35018,35020};break;
case 9:ground={87090};break;
case 22:ground={103195,103196};break;
case 22:ground={458,470,472};break;
default:ground={458,470,472};break;
}
std::ostringstream lua;lua<<"movement = { can_ground_mount = "<<(level>=20?"true":"false")
@@ -525,7 +525,7 @@ std::unordered_set<uint32> AdventureGeneratorMgr::ProtectedEquipment(Player* pla
{
std::unordered_set<uint32> result;
auto profile=sClientlessLuaEngine->GetAdventureProfile(player->GetGUID().GetCounter());
if(!profile || profile->SourcePath.find("generated:")!=0)return result;
if(!profile || profile->ProfileVersion<2 || !profile->Class)return result;
std::vector<Item*> items;
for(uint8 slot=INVENTORY_SLOT_ITEM_START;slot<INVENTORY_SLOT_ITEM_END;++slot)
if(auto item=player->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))items.push_back(item);
@@ -559,7 +559,7 @@ bool AdventureGeneratorMgr::PrepareCombat(Player* player,std::string& error)
{
auto profile=sClientlessLuaEngine->GetAdventureProfile(player->GetGUID().GetCounter());
if(!profile)return false;
if(profile->Class && profile->SourcePath.find("generated:")==0)return Reconcile(player,error);
if(profile->ProfileVersion>=2 && profile->Class)return Reconcile(player,error);
// Named Adventure profiles share the canonical combat templates, while
// retaining their manually assigned inventory, professions and level.
auto found=std::find_if(AdventureGeneratorPolicy::Archetypes().begin(),AdventureGeneratorPolicy::Archetypes().end(),
@@ -576,7 +576,7 @@ bool AdventureGeneratorMgr::PrepareCombat(Player* player,std::string& error)
bool AdventureGeneratorMgr::Reconcile(Player* player,std::string& error)
{
auto profile=sClientlessLuaEngine->GetAdventureProfile(player->GetGUID().GetCounter());
if(!profile || !profile->Level || profile->SourcePath.find("generated:")!=0)return true;
if(!profile || !profile->Level || !profile->Class || profile->ProfileVersion<2)return true;
if(profile->Class!=player->getClass()){error="Profile class mismatch; no class conversion performed.";return false;}
auto found=std::find_if(AdventureGeneratorPolicy::Archetypes().begin(),AdventureGeneratorPolicy::Archetypes().end(),
[&](Archetype const& a){return a.Class==profile->Class;});
+42 -8
View File
@@ -10,6 +10,7 @@
#include "ClientlessTravelGraphMgr.h"
#include "Channel.h"
#include "ChannelMgr.h"
#include "DBCStores.h"
#include "Chat.h"
#include "GameTime.h"
#include "Group.h"
@@ -65,12 +66,44 @@ bool AdventureGroupMgr::PlannedTransition(Player* p)
}
void AdventureGroupMgr::Speak(Player* p,std::string const& message)
{
if(!AdventureGroupPolicy::Capital(p->GetZoneId()))return;
if(!AdventureGroupPolicy::Capital(p->GetZoneId()) || GameTime::GetGameTime()<_nextChannelMessage)return;
_nextChannelMessage=GameTime::GetGameTime()+15;
auto manager=ChannelMgr::forTeam(p->GetTeam());if(!manager)return;
auto channel=manager->GetJoinChannel(0,"sucheNachGruppe");if(!channel)return;
auto entry=sChatChannelsStore.LookupEntry(26); // Native LookingForGroup, localized by the client.
auto zone=sAreaTableStore.LookupEntry(p->GetZoneId());
if(!entry || !zone || !p->CanJoinConstantChannelInZone(entry,zone))return;
auto channel=manager->GetJoinChannel(entry->ID,"",zone);if(!channel)return;
if(std::find(p->GetJoinedChannels().begin(),p->GetJoinedChannels().end(),channel)==p->GetJoinedChannels().end())channel->JoinChannel(p,"");
if(std::find(p->GetJoinedChannels().begin(),p->GetJoinedChannels().end(),channel)==p->GetJoinedChannels().end())return;
channel->Say(p->GetGUID(),message,p->GetTeam()==ALLIANCE?LANG_COMMON:LANG_ORCISH);
TC_LOG_INFO("server.adventurebot","GROUP_CHANNEL guid=%u zone=%u text='%s'",p->GetGUID().GetCounter(),p->GetZoneId(),message.c_str());
}
std::string AdventureGroupMgr::RecruitmentText(Player* player)
{
auto plan=sAdventureBehaviorMgr->GroupPlan(player);
auto activity=Activity(plan);
auto destination=sAdventureLocationMgr->Find(plan.Forming?plan.NextLocation:plan.Location);
std::string label=activity=="raid"?"einen Schlachtzug":activity=="instance"?"einen Instanzbesuch":
activity=="profession"?"gemeinsame Berufsarbeit":activity=="social"?"eine gesellige Runde":"ein Abenteuer";
return "Ich suche Gefaehrten fuer "+label+". Ziel: "+(destination?destination->Name:std::string("noch offen"))+".";
}
bool AdventureGroupMgr::RecruitPlayer(Player* player, std::string const& intent)
{
auto now=GameTime::GetGameTime();
for(auto it=_playerInvites.begin();it!=_playerInvites.end();)if(it->second<=now)it=_playerInvites.erase(it);else ++it;
std::vector<Player*> people;player->GetPlayerListInGrid(people,25);
for(auto other:people)
{
if(other==player || other->GetSession()->IsClientless() || !Ready(other) || other->isAFK() ||
other->GetGroup() || other->GetGroupInvite() || other->GetTeam()!=player->GetTeam() ||
!player->IsInMap(other) || !player->IsInPhase(other) || !player->CanSeeOrDetect(other) ||
!player->IsWithinLOSInMap(other) || _playerInvites.count(other->GetGUID()))continue;
_playerInvites[other->GetGUID()]=now+600;
Invite(player,other,intent,true);return true;
}
return false;
}
void AdventureGroupMgr::Offline(Player* p)
{
// Native player logout owns channel membership cleanup.
@@ -120,15 +153,14 @@ void AdventureGroupMgr::Update(Player* p)
if(plan.Forming)
{
if(!AdventureGroupPolicy::Capital(p->GetZoneId()))return;
if(now>=r.SpeakAt)
if(now>=r.SpeakAt && now>=_nextChannelMessage)
{
r.SpeakAt=now+urand(120,240);
auto place=sAdventureLocationMgr->Find(plan.Location);
std::string activity=intent=="instance"?"einen Instanzbesuch":intent=="raid"?"einen Schlachtzug":intent=="profession"?"gemeinsame Berufsarbeit":intent=="social"?"eine gesellige Runde":"ein Abenteuer";
Speak(p,"Ich suche Gefaehrten fuer "+activity+" in der naechsten Stunde. Treffpunkt: "+(place?place->Name:std::string("hier in der Stadt"))+".");
r.SpeakAt=now+urand(180,300);
Speak(p,RecruitmentText(p));
}
}
if(frand(0,1)>Sociability(p))return;
if(plan.Forming && RecruitPlayer(p,intent))return;
// Snapshot GUIDs: callbacks/native invitations may update manager records.
std::vector<ObjectGuid> candidates;for(auto const& entry:_records)candidates.push_back(entry.first);
std::sort(candidates.begin(),candidates.end());
@@ -196,8 +228,10 @@ void AdventureGroupMgr::Invite(Player* p,Player* other,std::string const& intent
peer.Partners[p->GetGUID()]=now+600;r.Partners[other->GetGUID()]=now+600;
WorldPackets::Party::PartyInviteClient packet{WorldPacket(CMSG_PARTY_INVITE)};
packet.TargetName=other->GetName();packet.TargetGUID=other->GetGUID();
if(!other->GetSession()->IsClientless())
p->Whisper(RecruitmentText(p)+" Moechtest du mitkommen?",p->GetTeam()==ALLIANCE?LANG_COMMON:LANG_ORCISH,other);
p->GetSession()->HandlePartyInviteOpcode(packet);
if(forming && other->GetGroupInvite())Speak(other,"Ich wuerde mich euch anschliessen.");
if(forming && other->GetSession()->IsClientless() && other->GetGroupInvite())Speak(other,"Ich wuerde mich euch anschliessen.");
else if(other->GetGroupInvite()){p->SetFacingToObject(other);p->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);}
TC_LOG_INFO("server.adventurebot","GROUP_BOT_INVITE leader=%u target=%u intent='%s' forming=%u",p->GetGUID().GetCounter(),other->GetGUID().GetCounter(),intent.c_str(),forming);
}
@@ -39,6 +39,10 @@ private:
};
void Invite(Player* leader,Player* member,std::string const& intent,bool forming);
void Speak(Player* player,std::string const& message);
std::string RecruitmentText(Player* player);
bool RecruitPlayer(Player* player,std::string const& intent);
std::unordered_map<ObjectGuid,time_t> _playerInvites;
time_t _nextChannelMessage=0;
std::unordered_map<ObjectGuid,Record> _records;
};
#define sAdventureGroupMgr AdventureGroupMgr::instance()
@@ -221,7 +221,7 @@ void AdventurePopulationMgr::DeleteRotated()
void AdventurePopulationMgr::Online(Player* p)
{
auto profile=sClientlessLuaEngine->GetAdventureProfile(p->GetGUID().GetCounter());
if(profile && profile->ProfileVersion>=2 && profile->SourcePath.find("generated:")==0)_checks[p->GetGUID().GetCounter()]=0;
if(profile && profile->ProfileVersion>=2 && profile->Class && profile->Level)_checks[p->GetGUID().GetCounter()]=0;
}
void AdventurePopulationMgr::Offline(Player* p){_checks.erase(p->GetGUID().GetCounter());}
void AdventurePopulationMgr::CleanInventory(Player* p)
+20 -6
View File
@@ -1,4 +1,5 @@
#include "ClientlessFlightMgr.h"
#include <cstring>
#include "ClientlessLuaEngine.h"
#include "ClientlessTravelMgr.h"
#include "ClientlessActionExecutorMgr.h"
@@ -75,15 +76,26 @@ ClientlessFlightMgr * ClientlessFlightMgr::instance()
return & mgr;
}
void ClientlessFlightMgr::BeginPlanning()
void ClientlessFlightMgr::BeginPlanning(Player const* player)
{
_planningAreas.clear();
_planningTerrain.clear();
_planningAreas.clear();_planningTerrain.clear();_planningPreferredZones.clear();
_planningPlayer=player;_planningEnabled=player && Enabled(player);
if(player)
{
_planningMinDistance=sConfigMgr->GetFloatDefault("Clientless.Flight.MinDistance",600);
std::istringstream list(sConfigMgr->GetStringDefault("Clientless.Flight.PreferredZones","210 4197"));
uint32 zone;while(list>>zone)_planningPreferredZones.insert(zone);
}
}
std::pair < uint32, uint32 > ClientlessFlightMgr::AreaZone(Player const * player, uint32 map, Position const & point) const
{
std::string key = std::to_string(map) + ":" + std::to_string(point.GetPositionX()) + ":" + std::to_string(point.GetPositionY()) + ":" + std::to_string(point.GetPositionZ());
// Exact binary coordinates avoid repeated floating-point text formatting
// in the O(nodes^2) flight alternatives loop, and do not merge nearby points.
std::string key(sizeof(map)+3*sizeof(float),'\0');
float coordinates[]{point.GetPositionX(),point.GetPositionY(),point.GetPositionZ()};
std::memcpy(key.data(),&map,sizeof(map));
std::memcpy(key.data()+sizeof(map),coordinates,sizeof(coordinates));
auto found = _planningAreas.find(key);
if (found != _planningAreas.end()) return found->second;
auto & terrain = _planningTerrain[map];
@@ -103,6 +115,7 @@ bool ClientlessFlightMgr::Enabled(Player const * player) const
bool ClientlessFlightMgr::Preferred(Player const * player, uint32 map, Position const & position) const
{
if(_planningPlayer==player)return _planningPreferredZones.count(AreaZone(player,map,position).second)!=0;
std::istringstream list(sConfigMgr->GetStringDefault("Clientless.Flight.PreferredZones", "210 4197"));
uint32 zone = AreaZone(player, map, position).second, candidate;
while (list >> candidate) if (zone == candidate) return true;
@@ -112,7 +125,8 @@ bool ClientlessFlightMgr::Preferred(Player const * player, uint32 map, Position
float ClientlessFlightMgr::Estimate(Player const * player, uint32 map, Position const & from, Position const & to, bool recovery) const
{
auto const * entry = sMapStore.LookupEntry(map);
if (! Enabled(player) || ! entry || entry->MapType != MAP_COMMON) return Infinity();
bool planning=_planningPlayer==player;
if (!(planning?_planningEnabled:Enabled(player)) || ! entry || entry->MapType != MAP_COMMON) return Infinity();
if ((map == 0 || map == 1) && ! player->HasSpell(90267)) return Infinity();
if (map == 571 && ! player->HasSpell(54197)) return Infinity();
uint32 const area = AreaZone(player, map, from).first;
@@ -127,7 +141,7 @@ float ClientlessFlightMgr::Estimate(Player const * player, uint32 map, Position
float const distance = Distance(PointOf(from), PointOf(to));
// Recovery keeps native eligibility, but has no RP
// distance threshold or zone preference. Start still validates the flight.
float minimum = recovery ? 0.0f : preferred ? 60.0f : std::max(100.0f, sConfigMgr->GetFloatDefault("Clientless.Flight.MinDistance", 600));
float minimum = recovery ? 0.0f : preferred ? 60.0f : std::max(100.0f, planning?_planningMinDistance:sConfigMgr->GetFloatDefault("Clientless.Flight.MinDistance", 600));
if (! std::isfinite(distance) || distance < minimum || (!recovery && distance > 20000)) return Infinity();
return recovery ? distance : preferred ? 40 + distance * 0.4f : 180 + distance * 1.5f;
}
+7 -1
View File
@@ -6,6 +6,7 @@
#include <string>
#include <memory>
#include <unordered_map>
#include <unordered_set>
class Player;
class ChatHandler;
class TerrainInfo;
@@ -29,7 +30,7 @@ class TC_GAME_API ClientlessFlightMgr
float Estimate(Player const * player, uint32 mapId, Position const & from, Position const & to, bool recovery = false) const;
bool Preferred(Player const * player, uint32 mapId, Position const & position) const;
bool Enabled(Player const * player) const;
void BeginPlanning();
void BeginPlanning(Player const* player = nullptr);
bool Start(Player * player, Position const & target, std::string & error);
bool Follow(Player* player, Position const& target, std::string& error);
bool LandFollowing(Player* player);
@@ -59,6 +60,11 @@ class TC_GAME_API ClientlessFlightMgr
bool AdvanceFollowing(Player* player, Record& record);
void Fail(Player * player, Record & record, std::string const & reason);
std::pair < uint32, uint32 > AreaZone(Player const * player, uint32 map, Position const & point) const;
// Immutable only for one explicit world-thread graph-planning scope.
Player const* _planningPlayer = nullptr;
bool _planningEnabled = false;
float _planningMinDistance = 600;
std::unordered_set<uint32> _planningPreferredZones;
mutable std::unordered_map < std::string, std::pair < uint32, uint32 >> _planningAreas;
mutable std::unordered_map < uint32, std::shared_ptr < TerrainInfo >> _planningTerrain;
std::unordered_map < uint32, Record > _records;
@@ -0,0 +1,41 @@
#ifndef VCORE_CLIENTLESS_GRAPH_PROBE_CACHE_H
#define VCORE_CLIENTLESS_GRAPH_PROBE_CACHE_H
#include <array>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <unordered_map>
// World-thread only. Store successful STATIC ground geometry, never Player paths,
// transient failures, Detour objects or tile pointers. Clear on graph reload.
class ClientlessGraphProbeCache
{
public:
using Key=std::array<std::uint32_t,8>;
struct Value {float Length,Final,Direct;};
static Key MakeKey(std::uint32_t map,std::uint32_t instance,float ax,float ay,float az,float bx,float by,float bz)
{
Key key{map,instance};float coordinates[]{ax,ay,az,bx,by,bz};
for(unsigned i=0;i<6;++i)std::memcpy(&key[i+2],&coordinates[i],sizeof(float));
return key;
}
Value const* Find(Key const& key)
{
auto found=_values.find(key);
if(found==_values.end()){++Misses;return nullptr;}
++Hits;return &found->second;
}
void Record(Key const& key,bool complete,float length,float final,float direct)
{
if(!complete || !std::isfinite(length) || length<0 || !std::isfinite(final) || final>1.5f || final<0 || !std::isfinite(direct))return;
if(_values.size()>=32768)_values.clear();
_values.insert_or_assign(key,Value{length,final,direct});
}
void Clear(){_values.clear();Hits=Misses=0;}
std::size_t Size()const{return _values.size();}
std::uint64_t Hits=0,Misses=0;
private:
struct Hash {std::size_t operator()(Key const& key)const{std::size_t hash=0;for(auto value:key)hash^=std::hash<std::uint32_t>{}(value)+0x9e3779b9+(hash<<6)+(hash>>2);return hash;}};
std::unordered_map<Key,Value,Hash> _values;
};
#endif
+44 -3
View File
@@ -17,6 +17,8 @@
#include "Log.h"
#include "Player.h"
#include "Random.h"
#include "GameTime.h"
#include "Map.h"
#include <lua.hpp>
#include <algorithm>
#include <cmath>
@@ -230,6 +232,7 @@ public:
{ sAdventureBehaviorMgr->IntentChanged(player, intent); }
void Update(Player* player, uint32 diff) override
{
sClientlessLuaEngine->UpdateWorldPresence(player,sAdventureBehaviorMgr->InteractionIntent(player));
sAdventureGroupTravelMgr->Observe(player,diff);
sAdventurePopulationMgr->Maintain(player,diff);
if(sAdventureGroupTravelMgr->Airborne(player)){sAdventureGroupTravelMgr->Follow(player);return;}
@@ -246,7 +249,7 @@ public:
void OnDamageTaken(Player* player, Unit* attacker, uint32 damage) override
{ sAdventureCombatMgr->DamageTaken(player, attacker, damage); }
void OnPlayerLogout(Player* player) override
{ sAdventurePopulationMgr->Offline(player); sAdventureInteractionMgr->Offline(player); sAdventureSupplyMgr->Offline(player); sAdventureCombatMgr->Offline(player); sAdventureBehaviorMgr->Offline(player); }
{ sClientlessLuaEngine->ForgetWorldPresence(player->GetGUID().GetCounter()); sAdventurePopulationMgr->Offline(player); sAdventureInteractionMgr->Offline(player); sAdventureSupplyMgr->Offline(player); sAdventureCombatMgr->Offline(player); sAdventureBehaviorMgr->Offline(player); }
};
}
@@ -472,6 +475,7 @@ bool ClientlessLuaEngine::LoadAdventureProfile(Player* player)
{
profile.AutonomousBehavior = ReadBoolField(_state, -1, "enabled", false);
profile.DailySchedule = ReadBoolField(_state, -1, "daily_schedule", false);
profile.AllowRetreat = ReadBoolField(_state, -1, "allow_retreat", true);
profile.InitialIntent = ReadStringField(_state, -1, "initial_intent");
profile.InitialLocation = ReadStringField(_state, -1, "initial_location");
profile.Locale = ReadStringField(_state, -1, "locale", "enUS");
@@ -563,20 +567,56 @@ uint32 ClientlessLuaEngine::SelectCompanionSpell(uint32 guid) const
return 0;
}
void ClientlessLuaEngine::UpdateWorldPresence(Player* player, std::string const& intent, bool arrived)
{
if (!player || !player->IsInWorld()) return;
player->AddCharacterFlag(CHARACTER_FLAG_PVP_DESIRED);
player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP);
if (!player->IsPvP() || player->pvpInfo.EndTimer) player->UpdatePvP(true,true);
if (player->getRace()!=RACE_WORGEN) return;
if (!player->HasSpell(SPELL_TWO_FORMS_RACIAL)) player->LearnSpell(SPELL_TWO_FORMS_RACIAL,false);
if (player->getLevel()>=20 && !player->HasSpell(458)) player->LearnSpell(458,false);
bool active=intent=="adventure" || intent=="instance" || intent=="raid" || player->IsInCombat() || player->GetMap()->IsDungeon();
auto guid=player->GetGUID().GetCounter();
auto wanted=_worgenForms.find(guid);
if (arrived && !active) wanted=_worgenForms.insert_or_assign(guid,urand(0,1)!=0).first;
if (active) wanted=_worgenForms.insert_or_assign(guid,true).first;
if (wanted==_worgenForms.end() || !player->IsAlive() || player->IsMounted() ||
player->GetTransport() || player->IsInFlight() || player->IsFlying() || player->IsBeingTeleported() ||
player->HasUnitState(UNIT_STATE_CASTING)) return;
bool altered=player->HasAuraType(SPELL_AURA_WORGEN_ALTERED_FORM);
if (altered==wanted->second || _worgenNextAttempt[guid]>GameTime::GetGameTime()) return;
_worgenNextAttempt[guid]=GameTime::GetGameTime()+5;
if (wanted->second) player->CastSpell(player,SPELL_ALTERED_FORM_RACIAL,true);
else if (player->HasSpell(SPELL_TWO_FORMS_RACIAL)) player->CastSpell(player,SPELL_TWO_FORMS_RACIAL,true);
TC_LOG_INFO("server.adventurebot","WORGEN_FORM guid=%u intent='%s' desired=%u arrived=%u",guid,intent.c_str(),wanted->second,arrived);
}
bool ClientlessLuaEngine::PrepareGroundMount(Player* player, float travelDistance, char const* context)
{
if (!player || !player->IsInWorld())
return false;
ClientlessAdventureProfile const* profile = GetAdventureProfile(player->GetGUID().GetCounter());
if (!profile || !profile->CanGroundMount || profile->GroundMounts.empty())
if (!profile || !profile->CanGroundMount || (profile->GroundMounts.empty() && player->getRace()!=RACE_WORGEN))
return false;
if (travelDistance < profile->GroundMountMinDistance || !player->IsOutdoors())
return false;
if (player->IsMounted())
return true;
uint32 const displayId = SelectGroundMountDisplayId(player->GetGUID().GetCounter());
if (player->getRace()==RACE_WORGEN && player->HasAuraType(SPELL_AURA_WORGEN_ALTERED_FORM) && player->getLevel()>=20)
{
if (!player->HasSpell(87840)) player->LearnSpell(87840,false);
player->CastSpell(player,87840,true);
if (player->HasAura(87840) && player->IsMounted())
{
TC_LOG_INFO("server.adventurebot.navigation","GROUND_RUNNING_WILD guid=%u",player->GetGUID().GetCounter());
return true;
}
return false;
}
uint32 const displayId = player->getRace()==RACE_WORGEN?2404:SelectGroundMountDisplayId(player->GetGUID().GetCounter());
if (!displayId)
return false;
@@ -598,6 +638,7 @@ void ClientlessLuaEngine::DismountGroundMount(Player* player, char const* reason
return;
uint32 const oldDisplay = player->GetMountID();
player->RemoveAurasDueToSpell(87840);
player->Dismount();
player->UpdateSpeed(MOVE_RUN);
@@ -53,6 +53,7 @@ struct TC_GAME_API ClientlessAdventureProfile
std::unordered_map<std::string, float> MicroActionAffinity;
bool AutonomousBehavior = false;
bool DailySchedule = false;
bool AllowRetreat = true;
std::string InitialIntent, InitialLocation, Locale = "enUS";
uint32 InitialDurationSeconds = 3600;
};
@@ -71,6 +72,8 @@ public:
ClientlessAdventureProfile const* GetAdventureProfile(uint32 characterGuid) const;
uint32 SelectGroundMountDisplayId(uint32 characterGuid) const;
uint32 SelectCompanionSpell(uint32 characterGuid) const;
void ForgetWorldPresence(uint32 guid) { _worgenForms.erase(guid); _worgenNextAttempt.erase(guid); }
void UpdateWorldPresence(Player* player, std::string const& intent, bool arrived = false);
bool PrepareGroundMount(Player* player, float travelDistance, char const* context);
void DismountGroundMount(Player* player, char const* reason);
@@ -84,6 +87,8 @@ private:
lua_State* _state = nullptr;
std::string _scriptRoot;
std::unordered_map<uint32, ClientlessAdventureProfile> _profiles;
std::unordered_map<uint32, bool> _worgenForms;
std::unordered_map<uint32, time_t> _worgenNextAttempt;
};
TC_GAME_API std::unique_ptr<ClientlessPlayerController> CreateClientlessAdventureLuaController();
+30 -5
View File
@@ -10,6 +10,8 @@
#include "ObjectAccessor.h"
#include "World.h"
#include "WorldSession.h"
#include <array>
#include <chrono>
ClientlessPlayerMgr* ClientlessPlayerMgr::instance()
{
@@ -152,6 +154,17 @@ std::deque<ClientlessAction> const* ClientlessPlayerMgr::GetQueuedActions(uint32
void ClientlessPlayerMgr::Update(uint32 diff)
{
using Clock=std::chrono::steady_clock;
static std::array<uint64,6> costs{};
static auto window=Clock::now();
static uint32 ticks=0,slowGuid=0;
static uint64 slowUs=0;
++ticks;
auto measure=[&](unsigned slot,auto&& update)
{
auto begin=Clock::now();update();
costs[slot]+=std::chrono::duration_cast<std::chrono::microseconds>(Clock::now()-begin).count();
};
// Damage can arrive from different map workers. Hand GUID-only notices to
// the world-thread controller, preserving order within each character.
decltype(_damageNotices) damageNotices;
@@ -161,13 +174,13 @@ void ClientlessPlayerMgr::Update(uint32 diff)
{ std::lock_guard<std::mutex> lock(_damageMutex); damageNotices.swap(_damageNotices); emoteNotices.swap(_emoteNotices); helpNotices.swap(_helpNotices); groupJoinNotices.swap(_groupJoinNotices); }
// CLIENTLESS_PLAYER_CORE_C8_2_TRAVEL_ROBUSTNESS
sClientlessTravelMgr->Update(diff);
measure(0,[&]{sClientlessTravelMgr->Update(diff);});
// CLIENTLESS_PLAYER_CORE_C8_3_LOCAL_PERCEPTION
sClientlessPerceptionMgr->Update(diff);
measure(1,[&]{sClientlessPerceptionMgr->Update(diff);});
// CLIENTLESS_PLAYER_CORE_C8_4_ACTION_EXECUTOR
sClientlessTransportMgr->Update(diff);
sClientlessFlightMgr->Update(diff);
sClientlessActionExecutorMgr->Update(diff);
measure(2,[&]{sClientlessTransportMgr->Update(diff);});
measure(3,[&]{sClientlessFlightMgr->Update(diff);});
measure(4,[&]{sClientlessActionExecutorMgr->Update(diff);});
for (auto itr = _records.begin(); itr != _records.end(); )
{
@@ -188,6 +201,7 @@ void ClientlessPlayerMgr::Update(uint32 diff)
if (state == ClientlessPlayerState::Online && player)
{
auto begin=Clock::now();
if (!record.OnlineNotified)
{
record.OnlineNotified = true;
@@ -214,6 +228,9 @@ void ClientlessPlayerMgr::Update(uint32 diff)
record.Controller->OnGroupJoinRequest(player,ObjectAccessor::FindPlayer(source));
record.Controller->Update(player, diff);
}
auto elapsed=uint64(std::chrono::duration_cast<std::chrono::microseconds>(Clock::now()-begin).count());
costs[5]+=elapsed;
if(elapsed>slowUs){slowUs=elapsed;slowGuid=characterGuid;}
}
else if (state == ClientlessPlayerState::Removing && !record.LogoutNotified)
{
@@ -224,6 +241,14 @@ void ClientlessPlayerMgr::Update(uint32 diff)
++itr;
}
auto now=Clock::now();
auto wall=std::chrono::duration_cast<std::chrono::milliseconds>(now-window).count();
if(wall>=30000)
{
TC_LOG_INFO("server.worldserver","CPC_PERF windowMs=%llu ticks=%u players=%u travelMs=%.3f perceptionMs=%.3f transportMs=%.3f flightMs=%.3f actionsMs=%.3f controllersMs=%.3f slowGuid=%u slowMs=%.3f",
static_cast<unsigned long long>(wall),ticks,uint32(_records.size()),costs[0]/1000.0,costs[1]/1000.0,costs[2]/1000.0,costs[3]/1000.0,costs[4]/1000.0,costs[5]/1000.0,slowGuid,slowUs/1000.0);
costs={};ticks=0;slowUs=0;slowGuid=0;window=now;
}
}
void ClientlessPlayerMgr::DamageTaken(Player* player, Unit* attacker, uint32 damage)
@@ -12,6 +12,8 @@
#include "SpellInfo.h"
#include <algorithm>
#include <chrono>
#include <map>
#include <cmath>
#include <limits>
#include <queue>
@@ -101,6 +103,8 @@ ClientlessPortalUse const* ClientlessTravelGraphMgr::GetPortalUse(uint32 edgeDat
bool ClientlessTravelGraphMgr::Reload()
{
_positionProbes.Clear();
_bridgeNeighborhoods.clear();
_nodes.clear();
_edges.clear();
_edgePoints.clear();
@@ -516,7 +520,31 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
std::unordered_set<std::string> const* blockedBridgeKeys,
ClientlessTravelLocationGoal const* locationGoal)
{
sClientlessFlightMgr->BeginPlanning();
struct Trace
{
ClientlessGraphProbeCache& Cache;std::string const& Target;
std::chrono::steady_clock::time_point Start=std::chrono::steady_clock::now();
std::uint64_t Hits=Cache.Hits,Calls=0,NavUs=0,StartUs=0,StartCalls=0,FlightUs=0,FlightCalls=0;
~Trace()
{
auto us=std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-Start).count();
if(us>=50000)TC_LOG_INFO("server.worldserver","CPC_ROUTE target='%s' totalMs=%.3f navMs=%.3f probes=%llu cacheHits=%llu cacheSize=%u startMs=%.3f startCalls=%llu flightMs=%.3f flightCalls=%llu",Target.c_str(),us/1000.0,NavUs/1000.0,static_cast<unsigned long long>(Calls),static_cast<unsigned long long>(Cache.Hits-Hits),uint32(Cache.Size()),StartUs/1000.0,static_cast<unsigned long long>(StartCalls),FlightUs/1000.0,static_cast<unsigned long long>(FlightCalls));
}
} trace{_positionProbes,destinationNode};
// Reuse all start-point observations only WITHIN this immutable planning
// call, including its two search tiers. Never cache live Player paths globally.
std::map<ClientlessGraphProbeCache::Key,ClientlessPathDiagnostics> startProbes;
auto analyzeStart=[&](Position const& target,ClientlessPathDiagnostics& result)
{
auto key=ClientlessGraphProbeCache::MakeKey(player->GetMapId(),player->GetInstanceId(),player->GetPositionX(),player->GetPositionY(),player->GetPositionZ(),target.GetPositionX(),target.GetPositionY(),target.GetPositionZ());
auto found=startProbes.find(key);if(found!=startProbes.end()){result=found->second;return;}
auto begin=std::chrono::steady_clock::now();++trace.StartCalls;
sClientlessTravelMgr->AnalyzePath(const_cast<Player*>(player),target,result);
trace.StartUs+=std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-begin).count();
startProbes.emplace(key,result);
};
sClientlessFlightMgr->BeginPlanning(player);
struct FlightPlanningScope
{
~FlightPlanningScope() { sClientlessFlightMgr->BeginPlanning(); }
@@ -551,7 +579,10 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
if (!flightEnabled || from.MapId != map)
return std::numeric_limits<float>::infinity();
Position a,b; a.Relocate(from.X,from.Y,from.Z,from.O); b.Relocate(x,y,z);
return sClientlessFlightMgr->Estimate(player,map,a,b);
auto begin=std::chrono::steady_clock::now();++trace.FlightCalls;
float result=sClientlessFlightMgr->Estimate(player,map,a,b);
trace.FlightUs+=std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-begin).count();
return result;
};
if (startRadius <= 0.0f)
startRadius = 500.0f;
@@ -663,7 +694,7 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
Position entryTarget;
entryTarget.Relocate(node.X, node.Y, node.Z, node.O);
ClientlessPathDiagnostics entryNav;
sClientlessTravelMgr->AnalyzePath(const_cast<Player*>(player), entryTarget, entryNav);
analyzeStart(entryTarget,entryNav);
bool const reachable = entryNav.Calculated && entryNav.Complete &&
entryNav.FinalDistance <= 1.5f && entryNav.MaxSegmentLength <= 8.0f &&
entryNav.MaxZDelta <= 5.0f && entryNav.PathLength <= 500.0f;
@@ -789,7 +820,7 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
bool const alreadyThere = candidate.DistanceSq <= 2.25f;
if (!alreadyThere)
{
sClientlessTravelMgr->AnalyzePath(const_cast<Player*>(player), target, nav);
analyzeStart(target,nav);
if (!nav.Calculated || !nav.Complete || nav.Suspicious ||
nav.FinalDistance > 1.5f || nav.PathLength > 500.0f)
continue;
@@ -856,8 +887,18 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
// from Arthoran's current position. No Player/WorldObject is required.
if (targetMap != from.MapId)
return VcorePositionPathResult{};
return PathGenerator::AnalyzePositions(from.MapId, from.MapId,
player->GetInstanceId(), a, b, NAV_GROUND);
auto key=ClientlessGraphProbeCache::MakeKey(from.MapId,player->GetInstanceId(),from.X,from.Y,from.Z,x,y,z);
if(auto cached=_positionProbes.Find(key))
{
VcorePositionPathResult result;result.Result=VcorePositionPathResult::Status::Complete;
result.PathLength=cached->Length;result.FinalDistance=cached->Final;result.DirectDistance=cached->Direct;
return result;
}
auto started=std::chrono::steady_clock::now();++trace.Calls;
auto result=PathGenerator::AnalyzePositions(from.MapId, from.MapId,player->GetInstanceId(),a,b,NAV_GROUND);
trace.NavUs+=std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()-started).count();
_positionProbes.Record(key,result.IsComplete(),result.PathLength,result.FinalDistance,result.DirectDistance);
return result;
};
// Select the closest eligible waypoint per directed road geometrically.
@@ -1319,9 +1360,26 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
}
}
for (auto const& pair : _nodes)
// Fixed graph-node neighborhoods are shared across plans. Keep a cube
// superset: the original exact sphere/path/block-list checks still run.
uint32 radiusBits=0;std::memcpy(&radiusBits,&bridgeRadius,sizeof(float));
std::string neighborhoodKey=from.Key+":"+std::to_string(radiusBits);
auto neighborhood=_bridgeNeighborhoods.find(neighborhoodKey);
if(neighborhood==_bridgeNeighborhoods.end())
{
ClientlessTravelNode const& to = pair.second;
if(_bridgeNeighborhoods.size()>=4096)_bridgeNeighborhoods.clear();
std::vector<std::string> candidates;
for(auto const& entry:_nodes)
{
auto const& to=entry.second;
if(to.MapId==from.MapId && std::fabs(to.X-from.X)<=bridgeRadius &&
std::fabs(to.Y-from.Y)<=bridgeRadius && std::fabs(to.Z-from.Z)<=bridgeRadius)candidates.push_back(entry.first);
}
neighborhood=_bridgeNeighborhoods.emplace(neighborhoodKey,std::move(candidates)).first;
}
for (auto const& key : neighborhood->second)
{
ClientlessTravelNode const& to = _nodes.at(key);
if (to.Key == from.Key || to.MapId != from.MapId)
continue;
@@ -11,6 +11,7 @@
#define VCORE_CLIENTLESS_TRAVEL_GRAPH_MGR_H
#include "Common.h"
#include "ClientlessGraphProbeCache.h"
#include <string>
#include <unordered_map>
@@ -171,6 +172,8 @@ public:
private:
std::string FindNearestStartNode(Player const* player, float maxDistance) const;
ClientlessGraphProbeCache _positionProbes;
std::unordered_map<std::string,std::vector<std::string>> _bridgeNeighborhoods;
bool _loaded = false;
uint32 _edgeCount = 0;
@@ -1,14 +1,19 @@
-- Arthoran: first named AdventureBot character profile.
-- Arthoran: persistent managed level-60 warrior; tank in groups, Arms solo.
-- These values bias future weighted decisions; they do not prescribe a route.
return {
identity = {
name = "Arthoran",
profile_version = 2, level = 60, class = 1,
specialization = 2, solo_specialization = 0, role = "tank", seed = 26,
home_zone = 12, home_capital = 1519,
favorite_zone = 139, favorite_region = "eastern_plaguelands",
home_region = "elwynn",
},
behavior = {
enabled = true,
daily_schedule = false, -- First acceptance: social intent, planner remains inactive.
daily_schedule = true,
allow_retreat = false, -- Arthoran holds his ground even when outmatched.
initial_intent = "social",
initial_location = "goldshire_tavern",
initial_duration_seconds = 3600,
@@ -36,14 +41,19 @@ return {
personality = {
group_loyalty = 0.35, -- Chance to stay when the scheduled intent changes.
sociability = 0.65,
adventurousness = 0.70,
wanderlust = 0.30,
tavern_affinity = 0.85,
wilderness_affinity = 0.65,
aggression = 1.00,
home_attachment = 0.80,
adventurousness = 0.20,
wanderlust = 0.20,
tavern_affinity = 1.00,
wilderness_affinity = 0.25,
city_affinity = 0.35,
danger_tolerance = 0.70,
danger_tolerance = 1.00,
},
inventory = { keep_items = {37460, 6256, 5956, 2901, 7005, 6217} },
zone_affinity = { [12] = 4, [1519] = 5, [139] = 3 },
region_affinity = {
elwynn = 1.00,
stormwind = 0.70,
@@ -52,11 +62,13 @@ return {
},
activity_affinity = {
tavern = 0.90,
hunting = 0.75,
adventure = 0.25,
instance = 0.60, raid = 0.25, rest = 1.00, profession = 0.60,
tavern = 3.00,
hunting = 0.35,
travelling = 0.35,
city_visit = 0.35,
social = 0.60,
social = 2.00,
leisure = 0.60,
economy = 0.45,
},
@@ -94,8 +94,8 @@ struct Travel{
struct Behavior{int interrupts=0;void InterruptForCombat(Player*){++interrupts;}}behavior;auto sAdventureBehaviorMgr=&behavior;
'''
code+=r'''
struct Profile{unsigned Class=0,Specialization=0,SoloSpecialization=0;std::string SourcePath;};
struct Lua{Profile*GetAdventureProfile(unsigned){return nullptr;}void DismountGroundMount(Player*,char const*){}}lua;auto sClientlessLuaEngine=&lua;
struct Profile{bool AllowRetreat=true;unsigned Class=0,Specialization=0,SoloSpecialization=0;std::string SourcePath;};
struct Lua{Profile* profile=nullptr;Profile*GetAdventureProfile(unsigned){return profile;}void DismountGroundMount(Player*,char const*){}}lua;auto sClientlessLuaEngine=&lua;
'''
# production Update uses direct Position members and creature near point.
code=code.replace('float x=0,y=0,z=0;','union{float x=0;float m_positionX;};union{float y=0;float m_positionY;};union{float z=0;float m_positionZ;};',1)
@@ -197,6 +197,11 @@ int main(){
// Group join aborts immediately, even while critically injured.
p.grouped=true;p.health=1;assert(!mgr.Flee(&p,r)&&!r.Fleeing&&!travel.present);
assert(!mgr.Flee(&p,r));p.grouped=false;p.health=100;
// Explicit profile refusal cancels retreat without suppressing combat.
Profile steadfast;steadfast.AllowRetreat=false;lua.profile=&steadfast;
p.health=1;r.Fleeing=true;travel.present=true;
assert(!mgr.Flee(&p,r)&&!r.Fleeing&&!travel.present&&r.AI);
lua.profile=nullptr;p.health=100;
// Blocked paths preserve native self-defence; no teleport/resurrection.
travel={};travel.path=false;GameTime::now=1004;
int ticks=r.AI->ticks;assert(mgr.Flee(&p,r)&&r.Fleeing&&travel.starts==0&&r.AI->ticks>ticks);
+14 -2
View File
@@ -29,7 +29,7 @@ struct Map{bool IsDungeon(){return false;}}map;
struct Member{Player*player=nullptr;Member*nextMember=nullptr;Player*GetSource(){return player;}Member*next(){return nextMember;}};
constexpr int GROUP_REMOVEMETHOD_LEAVE=1;
struct Group{struct Slot{ObjectGuid guid;};std::vector<Slot>slots;auto const&GetMemberSlots(){return slots;}void RemoveMember(ObjectGuid,int);Member*members=nullptr;Member*GetFirstMember(){return members;}void ChangeLeader(ObjectGuid g){leader=g;}void SendUpdate(){}ObjectGuid leader;unsigned count=2;bool raid=false;ObjectGuid GetLeaderGUID(){return leader;}unsigned GetMembersCount(){return count;}bool isRaidGroup(){return raid;}void ConvertToRaid(){raid=true;}void ConvertToGroup(){raid=false;}};
struct WorldPacket{unsigned value=0;WorldPacket(int,int=0){}WorldPacket&operator<<(unsigned n){value=n;return *this;}};constexpr int MSG_SET_RAID_DIFFICULTY=2,RAID_DIFFICULTY_25MAN_NORMAL=1;constexpr int CMSG_PARTY_INVITE=1,EMOTE_ONESHOT_WAVE=1;
struct WorldPacket{unsigned value=0;WorldPacket(int,int=0){}WorldPacket&operator<<(unsigned n){value=n;return *this;}};constexpr int MSG_SET_RAID_DIFFICULTY=2,RAID_DIFFICULTY_25MAN_NORMAL=1;constexpr int ALLIANCE=0,LANG_COMMON=7,LANG_ORCISH=1;constexpr int CMSG_PARTY_INVITE=1,EMOTE_ONESHOT_WAVE=1;
namespace WorldPackets{namespace Party{struct PartyInviteClient{PartyInviteClient(WorldPacket&&){}std::string TargetName;ObjectGuid TargetGUID;};}}
struct Session{Player*owner;bool clientless=true;bool IsClientless(){return clientless;}void HandlePartyInviteOpcode(WorldPackets::Party::PartyInviteClient&);void HandleSetRaidDifficultyOpcode(WorldPacket&);};
struct Player{ObjectGuid guid;Group*group=nullptr,*invite=nullptr;Session session{this};bool combat=false;unsigned zone=1519,level=60,team=0;float distance=10;
@@ -39,6 +39,7 @@ struct Player{ObjectGuid guid;Group*group=nullptr,*invite=nullptr;Session sessio
Group*GetGroup(){return group;}Group*GetGroupInvite(){return invite;}Session*GetSession(){return &session;}std::string GetName(){return std::to_string(guid.id);}
bool IsInMap(Player*o){return zone==o->zone;}bool IsInPhase(Player*){return true;}bool CanSeeOrDetect(Player*){return true;}
float GetExactDist(Player*){return distance;}bool IsWithinLOSInMap(Player*){return true;}
std::vector<Player*> people;bool afk=false;std::string whisper;bool isAFK(){return afk;}void GetPlayerListInGrid(std::vector<Player*>& out,int){out=people;}void Whisper(std::string const& s,int,Player*){whisper=s;}
void SetFacingToObject(Player*){}void HandleEmoteCommand(int){}
};
namespace ObjectAccessor{std::unordered_map<ObjectGuid,Player*> players;Player*FindPlayer(ObjectGuid g){auto it=players.find(g);return it==players.end()?nullptr:it->second;}}
@@ -58,7 +59,7 @@ int messages=0;
void AdventureGroupMgr::Speak(Player*,std::string const&){++messages;}
'''
code+=fun('float Sociability(')+'\n'+fun('bool Ready(')+'\n'+fun('std::string Activity(')
for name in ['bool AdventureGroupMgr::BotLed(', 'bool AdventureGroupMgr::Forming(', 'bool AdventureGroupMgr::PlannedTransition(', 'bool AdventureGroupMgr::Accept(', 'void AdventureGroupMgr::Update(', 'void AdventureGroupMgr::Invite(', 'void AdventureGroupMgr::RequestPlayerAdmission(', 'bool AdventureGroupMgr::PlayerLeadership(', 'bool AdventureGroupMgr::EnforceCapacity(']:code+='\n'+fun(name)
for name in ['std::string AdventureGroupMgr::RecruitmentText(', 'bool AdventureGroupMgr::RecruitPlayer(', 'bool AdventureGroupMgr::BotLed(', 'bool AdventureGroupMgr::Forming(', 'bool AdventureGroupMgr::PlannedTransition(', 'bool AdventureGroupMgr::Accept(', 'void AdventureGroupMgr::Update(', 'void AdventureGroupMgr::Invite(', 'void AdventureGroupMgr::RequestPlayerAdmission(', 'bool AdventureGroupMgr::PlayerLeadership(', 'bool AdventureGroupMgr::EnforceCapacity(']:code+='\n'+fun(name)
code+=r'''
int main(){
using namespace AdventureGroupPolicy;
@@ -112,6 +113,17 @@ int main(){
mgr.RequestPlayerAdmission(&a,&human);assert(invites==5&&human.invite==&party);
human.group=&party;Member humanSlot;humanSlot.player=&human;party.members=&humanSlot;
mgr.Update(&a);assert(party.leader==human.guid&&!mgr.BotLed(&a));
// Inform nearby humans of the actual NEXT destination before invitation.
{mgr={};Player human;human.guid={999};human.session.clientless=false;
ObjectAccessor::players[human.guid]=&human;a.group=nullptr;a.people={&human};
behavior.plans[a.guid.id]={true,true,"groupformation","capital","raid","target"};
int before=invites;assert(mgr.RecruitPlayer(&a,"raid"));
assert(invites==before+1&&human.invite&&a.whisper.find("Schlachtzug")!=std::string::npos&&a.whisper.find("Stormwind")!=std::string::npos);
human.invite=nullptr;assert(!mgr.RecruitPlayer(&a,"raid")); // shared cooldown even after decline
GameTime::now+=601;human.afk=true;assert(!mgr.RecruitPlayer(&a,"raid"));
human.afk=false;human.team=1;assert(!mgr.RecruitPlayer(&a,"raid"));
human.team=0;human.group=&pending;assert(!mgr.RecruitPlayer(&a,"raid"));}
}
'''
with tempfile.TemporaryDirectory() as d:
@@ -30,6 +30,7 @@ struct Player {
Map* GetMap(){return &map;}
} player;
namespace ObjectAccessor{Player*FindPlayer(Guid){return nullptr;}}
struct Lua{void UpdateWorldPresence(Player*,std::string const&,bool){}}lua;auto sClientlessLuaEngine=&lua;
struct BotGroups{bool BotLed(Player*){return false;}bool FollowMember(Player*){return false;}}botGroups;auto sAdventureGroupMgr=&botGroups;
struct Encounters{bool active=false;bool Active(Player*){return active;}}encounters;auto sAdventureEncounterMgr=&encounters;
bool unsafe=false;bool Unsafe(Player*){return unsafe;}
+9 -3
View File
@@ -53,11 +53,11 @@ bool Unsafe(Player* p){return p->combat||p->flying;}
constexpr int PATHFIND_NORMAL=1;
struct PathGenerator{
struct Point{float x,y,z;};std::vector<Point> path;
static inline bool reachable=true,broken=false;static inline int type=1;
static inline bool reachable=true,broken=false;static inline int type=1;static inline float bend=20;
PathGenerator(Player*){}void SetPathLengthLimit(float){}
bool CalculatePath(Position const&a,Position const&b){
path.clear();int n=int(a.GetExactDist(b)/4)+1;
for(int i=0;i<=n;++i){float t=float(i)/n;path.push_back({a.m_positionX+(b.m_positionX-a.m_positionX)*t,a.m_positionY+(b.m_positionY-a.m_positionY)*t+20*std::sin(3.14159265f*t),a.m_positionZ+(b.m_positionZ-a.m_positionZ)*t});}
for(int i=0;i<=n;++i){float t=float(i)/n;path.push_back({a.m_positionX+(b.m_positionX-a.m_positionX)*t,a.m_positionY+(b.m_positionY-a.m_positionY)*t+bend*std::sin(3.14159265f*t),a.m_positionZ+(b.m_positionZ-a.m_positionZ)*t});}
if(broken && path.size()>5) path[5].z+=10;
return reachable;
}
@@ -89,7 +89,7 @@ class AdventureBehaviorMgr{public:
enum class Phase{Idle,OnSite,Switching};
struct Record{
AdventureInstancePolicy::Visit Instance;
std::string Intent="leisure",Location="city",WantedIntent,WantedLocation,Detail;Position Anchor;uint32 AnchorMap=0,MicroTimer=240000;std::mt19937 Random{26};
std::string Intent="leisure",Location="city",WantedIntent,WantedLocation,Detail;Position Anchor;uint32 AnchorMap=0,MicroTimer=240000,RetryTimer=0;std::mt19937 Random{26};
time_t Deadline=0;bool Dirty=false;std::unordered_set<std::string> Tried;Phase State=Phase::OnSite;
struct LeisureScene{bool Active=false,Flying=false,Moving=false,StopRequested=false,Returning=false,PlannedWalk=false,Progressive=false;std::string Kind;Position Origin;std::vector<Position> Route,WalkTrace;std::size_t Step=0,OutboundSteps=0;uint32 Elapsed=0,LegElapsed=0,PauseMs=0,CompanionWait=0,CompletedLegs=0;ClientlessCompanionScene Companion;}Leisure;
};
@@ -219,6 +219,12 @@ int main(){
combatMgr.available=true;assert(mgr.LeisureAvailable(&p,r,{"training"}));
assert(mgr.StartLeisure(&p,r,{"training"}) && combatMgr.starts==1);
r.Intent="adventure";assert(!mgr.LeisureAvailable(&p,r,{"training"}));
// Recruitment walks stay near the meeting point, also inside a tavern.
mgr.ResetLeisure(&p,r);r.Intent="groupformation";r.MicroTimer=45000;terrain.outdoors=false;p.outdoors=false;PathGenerator::bend=2;
assert(mgr.StartLeisure(&p,r,{"walk"}));
for(auto const& point:r.Leisure.Route)assert(point.GetExactDist(r.Leisure.Origin)<=18);
assert(!mgr.LeisureAvailable(&p,r,{"ride"}));mgr.ResetLeisure(&p,r);terrain.outdoors=true;PathGenerator::bend=20;
r.RetryTimer=30000;r.Tried.insert("old");mgr.SetWanted(&p,r,"rest","new",1234);assert(r.RetryTimer==0&&r.Tried.empty()&&r.Deadline==1234);
}
'''
@@ -0,0 +1,33 @@
"""Run real bot Speak against native channel/zone adapters."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2];s=(root/'src/server/game/World/AdventureGroupMgr.cpp').read_text()
a=s.index('void AdventureGroupMgr::Speak(');b=s.index('std::string AdventureGroupMgr::RecruitmentText(',a)
code=r'''
#include <vector>
#include <string>
#include <algorithm>
#include <cassert>
using uint32=unsigned;using time_t=long;
#define TC_LOG_INFO(...) ((void)0)
constexpr int ALLIANCE=0,LANG_COMMON=7,LANG_ORCISH=1;
namespace AdventureGroupPolicy{bool Capital(unsigned z){return z==1519;}}
namespace GameTime{time_t now=100;time_t GetGameTime(){return now;}}
struct Entry{unsigned ID=26;}entry;
struct Store{unsigned expected;Entry*LookupEntry(unsigned id){assert(id==expected);return &entry;}}sChatChannelsStore{26},sAreaTableStore{1519};
struct Channel;
struct Player{bool allowed=true;std::vector<Channel*> channels;unsigned GetZoneId(){return 1519;}unsigned GetTeam(){return 0;}unsigned GetGUID(){return 1;}bool CanJoinConstantChannelInZone(Entry*,Entry*){return allowed;}auto&GetJoinedChannels(){return channels;}};
struct Channel{int messages=0;bool deny=false;void JoinChannel(Player*p,char const*){if(!deny)p->channels.push_back(this);}void Say(unsigned,std::string const&,int){++messages;}}channel;
struct Manager{Channel*GetJoinChannel(unsigned id,char const* name,Entry*){assert(id==26 && std::string(name).empty());return &channel;}}manager;
namespace ChannelMgr{Manager*forTeam(unsigned){return &manager;}}
struct AdventureGroupMgr{time_t _nextChannelMessage=0;void Speak(Player*,std::string const&);};
'''+s[a:b]+r'''
int main(){AdventureGroupMgr m;Player p;m.Speak(&p,"test");assert(channel.messages==1&&p.channels.size()==1);m.Speak(&p,"test");assert(channel.messages==1);
GameTime::now+=16;p.allowed=false;m.Speak(&p,"test");assert(channel.messages==1);
GameTime::now+=16;p.allowed=true;p.channels.clear();channel.deny=true;m.Speak(&p,"test");assert(channel.messages==1);
}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'test.cpp').write_text(code)
subprocess.run(['g++','-std=c++17',str(p/'test.cpp'),'-o',str(p/'test')],check=True);subprocess.run([str(p/'test')],check=True)
print('Native LFG: ID26, localized standard channel, zone eligibility, join verification and population throttle passed')
+13 -2
View File
@@ -17,7 +17,7 @@ code=r'''
using uint32=unsigned;using uint64=unsigned long long;
using namespace AdventurePopulationPolicy;
namespace GameTime{time_t now=100000;time_t GetGameTime(){return now;}}
struct ObjectGuid{enum{Player};unsigned id;ObjectGuid(int,unsigned i):id(i){}};
struct ObjectGuid{enum{Player};unsigned id;ObjectGuid(int,unsigned i):id(i){} unsigned GetCounter(){return id;}};
namespace HighGuid{constexpr int Player=0;}
namespace ObjectAccessor{std::unordered_set<unsigned>connected;bool FindConnectedPlayer(ObjectGuid g){return connected.count(g.id);}}
enum class ClientlessPlayerState{Offline,Loading,Online,Removing};
@@ -26,14 +26,18 @@ struct Core{bool succeed=true;std::vector<unsigned>started;bool StartPlayer(unsi
int CreateClientlessAdventureLuaController(){return 0;}
float sample=.5;float frand(int,int){return sample;}
#define TC_LOG_INFO(...) ((void)0)
struct Profile{unsigned ProfileVersion=0,Class=0,Level=0;std::string SourcePath;};
struct Player{ObjectGuid GetGUID(){return ObjectGuid{ObjectGuid::Player,26};}};
struct Lua{Profile* profile=nullptr;Profile* GetAdventureProfile(unsigned){return profile;}}lua;auto sClientlessLuaEngine=&lua;
struct AdventurePopulationMgr{
struct Bot{uint32 Guid,Account,Pool;uint64 Created;uint32 Failures=0;time_t Retry=0;};
unsigned _cursor=0,_rotationAge=86400;double _rotationChance=.15;
std::array<unsigned,4>_targets{};std::vector<Bot>_bots;std::unordered_set<unsigned>_considered;
std::vector<std::pair<unsigned,unsigned>>generated;
std::unordered_map<unsigned,unsigned> _checks;void Online(Player*);
void Step();void Generate(unsigned pool,unsigned replace=0){generated.push_back({pool,replace});}
};
'''+function('void AdventurePopulationMgr::Step()')+r'''
'''+function('void AdventurePopulationMgr::Step()')+function('void AdventurePopulationMgr::Online(')+r'''
int main(){
assert(Pool(1,true)==0 && Pool(1,false)==1 && Pool(2,true)==2 && Pool(2,false)==3);
assert(!Replace(true,true,false,100,0,0,1));assert(!Replace(false,false,false,100,0,0,1));
@@ -41,6 +45,13 @@ int main(){
assert(Replace(false,true,false,100,100,.1,.2));assert(!Replace(false,true,false,100,0,.3,.2));
assert(!Deficit(5,3,2) && Deficit(5,2,1)==2 && !Deficit(0,2,0));
AdventurePopulationMgr mgr;
Player named;Profile profile;lua.profile=&profile;
mgr.Online(&named);assert(mgr._checks.empty());
profile.ProfileVersion=2;profile.Class=1;profile.Level=60;profile.SourcePath="profiles/arthoran.lua";
mgr.Online(&named);assert(mgr._checks.count(26));
mgr._checks.clear();profile.Level=0;mgr.Online(&named);assert(mgr._checks.empty());
profile.Level=60;profile.ProfileVersion=0;mgr.Online(&named);assert(mgr._checks.empty());
lua.profile=nullptr;mgr.Online(&named);assert(mgr._checks.empty());
mgr.Step();assert(mgr.generated.empty() && core.started.empty());
mgr._targets={1,2,3,4};
mgr.Step();assert(mgr.generated.back().first==0);mgr.Step();assert(mgr.generated.back().first==1);
@@ -0,0 +1,24 @@
"""Population retry spacing is bounded and increases only after failures."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
code=r'''
#include "AdventureBehaviorPolicy.h"
#include <cassert>
#include <limits>
int main(){using AdventureBehaviorPolicy::TravelRetryMs;
assert(TravelRetryMs(1,0)==2000&&TravelRetryMs(2,0)==4000);
assert(TravelRetryMs(3,0)==8000&&TravelRetryMs(4,0)==16000);
assert(TravelRetryMs(5,0)==30000&&TravelRetryMs(1000,1000)==30000);
assert(TravelRetryMs(std::numeric_limits<unsigned>::max(),1000)==30000);
assert(TravelRetryMs(1,1000)==3000&&TravelRetryMs(1,10000)==3000);
for(unsigned count=1;count<100;++count)for(unsigned jitter=0;jitter<=1000;jitter+=25){
auto value=TravelRetryMs(count,jitter);assert(value>=2000&&value<=30000);
}
}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'test.cpp').write_text(code)
subprocess.run(['c++','-std=c++17','-I'+str(root/'src/server/game/World'),str(p/'test.cpp'),'-o',str(p/'test')],check=True)
subprocess.run([str(p/'test')],check=True)
print('Travel failures: exponential/jittered retry spacing, strict 30s bound and overflow safety passed')
@@ -0,0 +1,73 @@
"""Execute production PvP/Worgen presence and ground-mount methods."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
s=(root/'src/server/game/World/ClientlessLuaEngine.cpp').read_text()
def fn(sig):
a=s.index(sig);b=s.index('{',a);e=b+1;n=1
while n:n+=(s[e]=='{')-(s[e]=='}');e+=1
return s[a:e]
code=r'''
#include <cassert>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <ctime>
using uint32=unsigned;
#define TC_LOG_INFO(...) ((void)0)
constexpr int CHARACTER_FLAG_PVP_DESIRED=65536,PLAYER_FLAGS=1,PLAYER_FLAGS_IN_PVP=512,RACE_WORGEN=22,
SPELL_TWO_FORMS_RACIAL=68996,SPELL_ALTERED_FORM_RACIAL=97709,SPELL_AURA_WORGEN_ALTERED_FORM=1,UNIT_STATE_CASTING=2,MOVE_RUN=3;
namespace GameTime{time_t now=100;time_t GetGameTime(){return now;}}
unsigned roll=0;unsigned urand(unsigned,unsigned){return roll;}
struct Guid{unsigned GetCounter(){return 26;}};
struct Map{bool dungeon=false;bool IsDungeon(){return dungeon;}}map;
struct Player{
unsigned race=22,level=60,flags=0,characterFlags=0,display=0,casts=0,updates=0;
bool world=true,alive=true,combat=false,mounted=false,transport=false,taxi=false,flying=false,teleport=false,casting=false,outdoors=true,pvp=false,fail=false;
float speed=1;std::unordered_set<unsigned>spells,auras;struct{unsigned EndTimer=10;}pvpInfo;
Map*GetMap(){return &map;}Guid GetGUID(){return {};}std::string GetName(){return "Test";}bool IsInWorld(){return world;}void AddCharacterFlag(int f){characterFlags|=f;}void SetFlag(int,int f){flags|=f;}
bool IsPvP(){return pvp;}void UpdatePvP(bool on,bool){pvp=on;pvpInfo.EndTimer=0;++updates;}
unsigned getRace(){return race;}unsigned getLevel(){return level;}bool IsAlive(){return alive;}bool IsInCombat(){return combat;}
bool IsMounted(){return mounted;}bool GetTransport(){return transport;}bool IsInFlight(){return taxi;}bool IsFlying(){return flying;}
bool IsBeingTeleported(){return teleport;}bool HasUnitState(int){return casting;}bool HasAuraType(int){return auras.count(97709);}
bool HasSpell(unsigned id){return spells.count(id);}void LearnSpell(unsigned id,bool){spells.insert(id);}
bool HasAura(unsigned id){return auras.count(id);}bool IsOutdoors(){return outdoors;}
void CastSpell(Player*,unsigned id,bool){++casts;if(fail)return;if(id==97709)auras.insert(id);if(id==68996)auras.erase(97709);if(id==87840){auras.insert(id);mounted=true;display=29422;speed=2;}}
void Mount(unsigned id){display=id;mounted=true;}void SetSpeedRate(int,float v){speed=v;}unsigned GetMountID(){return display;}
void RemoveAurasDueToSpell(unsigned id){auras.erase(id);}void Dismount(){mounted=false;display=0;}void UpdateSpeed(int){speed=1;}
};
struct ClientlessAdventureProfile{bool CanGroundMount=true;std::vector<int>GroundMounts{2404};float GroundMountMinDistance=40,GroundMountSpeedRate=2;}profile;
struct ClientlessLuaEngine{
std::unordered_map<unsigned,bool>_worgenForms;std::unordered_map<unsigned,time_t>_worgenNextAttempt;
ClientlessAdventureProfile*GetAdventureProfile(unsigned){return &profile;}unsigned SelectGroundMountDisplayId(unsigned){return 2404;}
void UpdateWorldPresence(Player*,std::string const&,bool=false);bool PrepareGroundMount(Player*,float,char const*);void DismountGroundMount(Player*,char const*);
};
'''+fn('void ClientlessLuaEngine::UpdateWorldPresence(')+fn('bool ClientlessLuaEngine::PrepareGroundMount(')+fn('void ClientlessLuaEngine::DismountGroundMount(')+r'''
int main(){
ClientlessLuaEngine e;Player p;e.UpdateWorldPresence(&p,"adventure");
assert(p.pvp&&p.pvpInfo.EndTimer==0&&(p.flags&512)&&(p.characterFlags&65536)&&p.HasAura(97709));
assert(e.PrepareGroundMount(&p,100,"test")&&p.HasAura(87840)&&p.IsMounted()&&p.display==29422);
e.DismountGroundMount(&p,"test");assert(!p.IsMounted()&&!p.HasAura(87840)&&p.speed==1);
GameTime::now+=6;roll=0;e.UpdateWorldPresence(&p,"leisure",true);assert(!p.HasAura(97709));
assert(e.PrepareGroundMount(&p,100,"test")&&p.display==2404&&!p.HasAura(87840));
e.DismountGroundMount(&p,"test");
p.transport=true;GameTime::now+=6;e.UpdateWorldPresence(&p,"raid");assert(!p.HasAura(97709));
p.transport=false;e.UpdateWorldPresence(&p,"raid");assert(p.HasAura(97709));
// Decide quiet arrival once, defer while mounted, never reroll every update.
p.mounted=true;roll=0;e.UpdateWorldPresence(&p,"rest",true);assert(p.HasAura(97709));
p.mounted=false;GameTime::now+=6;roll=1;e.UpdateWorldPresence(&p,"rest");assert(!p.HasAura(97709));
// Combat and mixed player instances require Worgen even with a quiet personal intent.
GameTime::now+=6;p.combat=true;e.UpdateWorldPresence(&p,"rest");assert(p.HasAura(97709));p.combat=false;
p.auras.clear();map.dungeon=true;GameTime::now+=6;e.UpdateWorldPresence(&p,"rest");assert(p.HasAura(97709));map.dungeon=false;p.auras.clear();
// Failed native casts are throttled, not spammed every world tick.
p.fail=true;GameTime::now+=6;e.UpdateWorldPresence(&p,"instance");auto casts=p.casts;
e.UpdateWorldPresence(&p,"instance");assert(p.casts==casts);
p.race=1;p.pvp=false;p.pvpInfo.EndTimer=5;e.UpdateWorldPresence(&p,"rest");assert(p.pvp&&!p.pvpInfo.EndTimer);
}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'test.cpp').write_text(code)
subprocess.run(['g++','-std=c++17',str(p/'test.cpp'),'-o',str(p/'test')],check=True)
subprocess.run([str(p/'test')],check=True)
print('Production world presence: persistent PvP, Worgen intent/arrival decisions, travel deferral, native Running Wild, human horse and aura cleanup passed')
+3 -2
View File
@@ -7,12 +7,13 @@ a=s.index('std::pair < uint32, uint32 > ClientlessFlightMgr::AreaZone(')
b=s.index('bool ClientlessFlightMgr::Enabled(',a)
code=r'''
#include <cassert>
#include <cstring>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <memory>
using uint32=uint32_t;
struct Position{float GetPositionX()const{return 1;}float GetPositionY()const{return 2;}float GetPositionZ()const{return 3;}};
struct Position{float x=1,y=2,z=3;float GetPositionX()const{return x;}float GetPositionY()const{return y;}float GetPositionZ()const{return z;}};
struct Player{int GetPhaseShift()const{return 17;}};
struct TerrainInfo{int calls=0;void GetZoneAndAreaId(int phase,uint32 map,uint32& zone,uint32& area,Position const&){assert(phase==17&&map==530);++calls;zone=3430;area=3460;}};
struct TerrainMgr{std::shared_ptr<TerrainInfo> value=std::make_shared<TerrainInfo>();auto LoadTerrain(uint32 map){assert(map==530);return value;}} sTerrainMgr;
@@ -23,7 +24,7 @@ class ClientlessFlightMgr{public:
};
'''
code+=s[a:b]+r'''
int main(){ClientlessFlightMgr mgr;Player p;Position pos;auto r=mgr.AreaZone(&p,530,pos);assert(r.first==3460&&r.second==3430);assert(mgr.AreaZone(&p,530,pos)==r);assert(sTerrainMgr.value->calls==1);}
int main(){ClientlessFlightMgr mgr;Player p;Position pos;auto r=mgr.AreaZone(&p,530,pos);assert(r.first==3460&&r.second==3430);assert(mgr.AreaZone(&p,530,pos)==r);assert(sTerrainMgr.value->calls==1);pos.x=1.0000001f;mgr.AreaZone(&p,530,pos);assert(sTerrainMgr.value->calls==2);}
'''
with tempfile.TemporaryDirectory(prefix='vcore-area-query-') as folder:
cpp=Path(folder)/'test.cpp';binary=Path(folder)/'test';cpp.write_text(code)
+19 -2
View File
@@ -16,6 +16,8 @@ harness=r'''
#include <string>
#include <vector>
#include <sstream>
#include <unordered_set>
#include <unordered_map>
#include <limits>
using uint32=uint32_t;
using namespace ClientlessFlightPath;
@@ -39,7 +41,7 @@ struct Player{
struct Mount{uint32 DisplayId=32235,Weight=100;};
struct Profile{bool CanFreeFly=true;std::vector<Mount> FlightMounts{{}};} profile;
struct Lua{auto GetAdventureProfile(uint32){return &profile;}} lua;
struct Config{bool enabled=true;bool GetBoolDefault(const char*,bool){return enabled;}float GetFloatDefault(const char*,float v){return v;}std::string GetStringDefault(const char*,const char*v){return v;}} config;
struct Config{int reads=0;bool enabled=true;bool GetBoolDefault(const char*,bool){++reads;return enabled;}float GetFloatDefault(const char*,float v){++reads;return v;}std::string GetStringDefault(const char*,const char*v){++reads;return v;}} config;
auto sClientlessLuaEngine=&lua;auto sConfigMgr=&config;
struct SpellMgr{void* GetSpellInfo(uint32){return this;}} spells;auto sSpellMgr=&spells;
uint32 FlightType(void*){return 1;}
@@ -54,6 +56,10 @@ struct Record{std::shared_ptr<ClientlessFlightPath::SharedTrail>Published=std::m
bool Moving=true,Returning=false;std::vector<Position> Breadcrumbs{{}};std::string AbortReason;
};
class ClientlessFlightMgr{public:
Player const* _planningPlayer=nullptr;bool _planningEnabled=false;float _planningMinDistance=600;
std::unordered_set<uint32> _planningPreferredZones;
std::unordered_map<int,int> _planningAreas,_planningTerrain;
void BeginPlanning(Player const* = nullptr);
uint32 areaCode=87,zoneCode=12;
std::pair<uint32,uint32> AreaZone(Player const*,uint32,Position const&)const{return {areaCode,zoneCode};}
bool Enabled(Player const*)const;bool Preferred(Player const*,uint32,Position const&)const;
@@ -61,7 +67,7 @@ class ClientlessFlightMgr{public:
void Fail(Player*,Record&,std::string const&);
};
'''
for signature in ('bool ClientlessFlightMgr::Enabled(', 'bool ClientlessFlightMgr::Preferred(', 'float ClientlessFlightMgr::Estimate(', 'void ClientlessFlightMgr::Fail('):
for signature in ('void ClientlessFlightMgr::BeginPlanning(', 'bool ClientlessFlightMgr::Enabled(', 'bool ClientlessFlightMgr::Preferred(', 'float ClientlessFlightMgr::Estimate(', 'void ClientlessFlightMgr::Fail('):
harness+=function(signature)+'\n'
harness+=r'''
int main(){
@@ -95,6 +101,17 @@ int main(){
mgr.Fail(&p,r,"reverse blocked");assert(r.Status.State==ClientlessFlightState::Failed);
Record mounting;mounting.Status.State=ClientlessFlightState::Mounting;mgr.Fail(&p,mounting,"cast rejected");
assert(mounting.Status.State==ClientlessFlightState::Failed&&p.interrupts==1&&!mounting.Returning);
// A planning scope snapshots repeated config/profile work, while actual
// departure checks and per-map licenses remain live.
profile.CanFreeFly=true;p.skill=225;p.learned=true;p.license=true;config.enabled=true;
area.fly=true;areas.known=true;p.restrictions=false;mgr.zoneCode=12;b.x=1000;
mgr.BeginPlanning(&p);int reads=config.reads;
for(int i=0;i<1000;++i)assert(std::isfinite(mgr.Estimate(&p,0,a,b)));
assert(config.reads==reads);
p.license=false;assert(!std::isfinite(mgr.Estimate(&p,0,a,b)));p.license=true;
profile.CanFreeFly=false;assert(!mgr.Enabled(&p));
mgr.BeginPlanning();assert(!std::isfinite(mgr.Estimate(&p,0,a,b)));
profile.CanFreeFly=true;
Record revoked;p.canFly=false;mgr.Fail(&p,revoked,"permission lost");assert(revoked.Status.State==ClientlessFlightState::Failed&&!revoked.Returning);
}
'''
+20 -5
View File
@@ -8,6 +8,9 @@ structs=h[h.index('struct TC_GAME_API ClientlessTravelNode'):h.index('class TC_G
method=s[s.index('bool ClientlessTravelGraphMgr::PlanAdaptiveRoute('):s.index('bool ClientlessTravelGraphMgr::PlanRouteToPosition(')]
signature=h[h.index(' bool PlanAdaptiveRoute('):h.index(' bool FindNearestNodeToPosition(')]
preamble=r'''
#include "ClientlessGraphProbeCache.h"
#include <chrono>
#include <map>
#include <algorithm>
#include <cassert>
#include <cmath>
@@ -24,7 +27,7 @@ using uint32=uint32_t; using int32=int32_t;
#define TC_LOG_DEBUG(...) do {} while(0)
#define TC_LOG_WARN(...) do {} while(0)
constexpr uint32 NAV_GROUND=1, PATHFIND_INCOMPLETE=2, PATHFIND_NOPATH=4;
struct Position { float x=0,y=0,z=0; void Relocate(float a,float b,float c,float=0){x=a;y=b;z=c;} };
struct Position { float x=0,y=0,z=0;float GetPositionX()const{return x;}float GetPositionY()const{return y;}float GetPositionZ()const{return z;} void Relocate(float a,float b,float c,float=0){x=a;y=b;z=c;} };
struct Player { float x=0,y=0,z=0; bool IsInWorld() const{return true;} uint32 GetMapId()const{return 0;} uint32 GetInstanceId()const{return 0;} float GetPositionX()const{return x;} float GetPositionY()const{return y;} float GetPositionZ()const{return z;} };
float dist(Position a,Position b){return std::sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}
struct ClientlessPathDiagnostics {bool Calculated=true, Complete=true,Suspicious=false; uint32 PathType=1,PointCount=2; float DirectDistance=0,PathLength=0,MaxSegmentLength=0,MaxZDelta=0,FinalDistance=0; std::string Reason;};
@@ -32,18 +35,19 @@ struct Travel {void AnalyzePath(Player* p,Position b,ClientlessPathDiagnostics&
auto sClientlessTravelMgr=&travel;
struct Flight {
bool enabled=false;float minimumX=-10000;
void BeginPlanning(){}
void BeginPlanning(Player const* = nullptr){}
bool Enabled(Player const*){return enabled;}
float Estimate(Player const*,uint32 map,Position a,Position b){
float d=dist(a,b);return enabled&&map==0&&a.x>=minimumX&&d>=60?180+d*1.5f:std::numeric_limits<float>::infinity();
}
} flight;
auto sClientlessFlightMgr=&flight;
struct VcorePositionPathResult {bool complete=false; uint32 Result=2;float FinalDistance=0,PathLength=0;bool IsComplete()const{return complete;}};
struct PathGenerator {static inline bool available=false; static inline float maxDistance=10000;static VcorePositionPathResult AnalyzePositions(uint32,uint32,uint32,Position a,Position b,uint32){float d=dist(a,b);return {available && d<=maxDistance,2,0,d};}};
struct VcorePositionPathResult {enum class Status{Complete,Partial};Status Result=Status::Partial;float FinalDistance=0,PathLength=0,DirectDistance=0;bool IsComplete()const{return Result==Status::Complete;}};
struct PathGenerator {static inline unsigned probes=0;static inline bool available=false; static inline float maxDistance=10000;static VcorePositionPathResult AnalyzePositions(uint32,uint32,uint32,Position a,Position b,uint32){++probes;float d=dist(a,b);return {available && d<=maxDistance?VcorePositionPathResult::Status::Complete:VcorePositionPathResult::Status::Partial,0,d,d};}};
std::string MakeLocalBridgeKey(std::string const&a,std::string const&b){return a+"->"+b;}
'''
cls='class ClientlessTravelGraphMgr { public: bool EnsureLoaded(){return true;}\n'+signature+'''
ClientlessGraphProbeCache _positionProbes;std::unordered_map<std::string,std::vector<std::string>> _bridgeNeighborhoods;
std::unordered_map<std::string,ClientlessTravelNode> _nodes;
std::unordered_map<std::string,std::vector<ClientlessTravelEdge>> _edges;
std::unordered_map<uint32,std::vector<ClientlessTravelEdgePoint>> _edgePoints;
@@ -107,6 +111,17 @@ assert(exits.PlanAdaptiveRoute(&start,"D",1,200,route,done,endKey,why));
assert(done&&route.back().NodeKey=="D"&&route.back().EdgeType=="free_flight");
assert(route[route.size()-2].NodeKey=="virtual_ground_exit");
for(auto const& step:route)if(step.EdgeType=="free_flight")assert(step.NodeKey!="virtual_ground_entry");
// A second plan reuses static proofs, but still honors query-specific failures.
flight.enabled=false;PathGenerator::available=true;PathGenerator::maxDistance=10000;
ClientlessTravelGraphMgr cached;node(cached,"A",0);node(cached,"B",150);
assert(cached.PlanAdaptiveRoute(&start,"B",1,200,route,done,endKey,why)&&done);
auto calls=PathGenerator::probes;auto size=route.size();
assert(cached.PlanAdaptiveRoute(&start,"B",1,200,route,done,endKey,why)&&done&&route.size()==size);
assert(PathGenerator::probes==calls&&cached._positionProbes.Hits>0);
std::unordered_set<std::string> forbidden{"A->B"};
assert(cached.PlanAdaptiveRoute(&start,"B",1,200,route,done,endKey,why,nullptr,&forbidden)&&!done);
cached._positionProbes.Clear();cached._bridgeNeighborhoods.clear();PathGenerator::available=false;
assert(cached.PlanAdaptiveRoute(&start,"B",1,200,route,done,endKey,why)&&!done);
std::cout<<"ground planner regressions and dynamic flight/node/location/virtual-exit integration passed\n";
}
'''
@@ -115,5 +130,5 @@ tests=tests.replace('r=plan(g,p,goal,1);assert(r.back().GroundStartIndex<0); //
with tempfile.TemporaryDirectory(prefix="vcore-flight-planner-") as folder:
cpp=Path(folder)/"test.cpp";binary=Path(folder)/"test"
cpp.write_text(preamble+structs+cls+method+tests)
subprocess.run(["c++","-std=c++17","-O0",str(cpp),"-o",str(binary)],check=True)
subprocess.run(["c++","-std=c++17","-O0","-I"+str(root/"src/server/game/World"),str(cpp),"-o",str(binary)],check=True)
subprocess.run([str(binary)],check=True)
@@ -0,0 +1,28 @@
"""Static MMAP proof cache isolation, failure handling and bounded lifetime."""
from pathlib import Path
import subprocess,tempfile
root=Path(__file__).resolve().parents[2]
code=r'''
#include "ClientlessGraphProbeCache.h"
#include <cassert>
#include <limits>
int main(){
ClientlessGraphProbeCache c;auto key=c.MakeKey(0,1,1,2,3,4,5,6);
assert(!c.Find(key));c.Record(key,false,10,0,10);assert(!c.Find(key));
c.Record(key,true,10,2,10);assert(!c.Find(key));
c.Record(key,true,std::numeric_limits<float>::infinity(),0,10);assert(!c.Find(key));
c.Record(key,true,10,0,9);assert(c.Find(key)&&c.Find(key)->Length==10);
assert(!c.Find(c.MakeKey(1,1,1,2,3,4,5,6))); // map isolation
assert(!c.Find(c.MakeKey(0,2,1,2,3,4,5,6))); // instance isolation
assert(!c.Find(c.MakeKey(0,1,4,5,6,1,2,3))); // directed connection
assert(!c.Find(c.MakeKey(0,1,1.0000001f,2,3,4,5,6))); // exact coordinates
c.Clear();assert(!c.Find(key)&&c.Size()==0);
for(unsigned i=0;i<32769;++i)c.Record(c.MakeKey(i,1,1,2,3,4,5,6),true,10,0,9);
assert(c.Size()==1&&c.Find(c.MakeKey(32768,1,1,2,3,4,5,6)));
}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'test.cpp').write_text(code)
subprocess.run(['c++','-std=c++17','-I'+str(root/'src/server/game/World'),str(p/'test.cpp'),'-o',str(p/'test')],check=True)
subprocess.run([str(p/'test')],check=True)
print('Graph probe cache: exact directed/map/instance keys, successful geometry only, invalidation and bounded storage passed')