Preserve navigation fallbacks after early group departure

This commit is contained in:
Nico committed 2026-10-30 02:36:26 +01:00
1 parent 373818628d
commit 77648c6b53
4 files changed
+97 -6

No files matched your search

+55
View File
@@ -1,3 +1,58 @@
# CURRENT FINDING / FIX IN BUILD: early snapshot repins travel fallbacks
During observation initial full groups began early correctly, but when route
planning failed, UpdateDeparture kept overwriting normal fallback destination
with original copied goal every tick. Repeated GROUP_EARLY_DEPART/INSTANCE_PLAN
were retries, NOT additional successful departures. Preserved state
/tmp/vcore-group-observation-20261030/before-fallback-fix.json. Server never crashed.
User informed and targeted fix+brief planned restart announced, preserving test
plans/groups. Changed ONLY BehaviorMgr.cpp +departure regression: applycopy only
while actual intent still formation/empty; GroupPlan and AdoptGroup use effective
Wanted fallback after application; leaving group keeps fallback within copied
intent. No new schema/header. Real production regression for repeatedmaintenance,
leaderfallback inheritance andkick added; departure+groupplan tests pass, intent
state targetedtest included in build command. Build-j10 running execsession82369,
log/tmp/vcore-group-fallback-build.log. Need wait buildfinish, commit fix, graceful
shutdown387859 andinstall/restart finalfix, no testDBreset. Monitor continues until
04:00CET/03:00UTC, script67325/PID387861; note plannedrestartgap separate fromcrash.
Currentconsole/tmp/vcore-flight-regions-group-test-start-20261030.log; afterrestart
use new uniqueconsole filename and adjust monitor console tracking if needed.
Server.log/navigation/DBErrors monitoring survives truncation automatically.
RotationPercent0 stillmustrestore15 at04:00. Otherobservation instructions below.
# RUNNING OBSERVATION: do not finish before04:00CET Oct30 (03:00UTC)
Commit373818628d contains all requested feature changes. Latest flight-region
binary installed, final server387859 in tmuxvcore-worldserver, freshready10s,
ports8085/8087 good. Console/tmp/vcore-flight-regions-group-test-start-20261030.log.
Do NOT restart/alter gameplay during observation unless critical recovery needed.
Group test applied successfully to92 of110bots:76instance,16raid next block;
18below15 excluded entirely. All targets validated with native eligibility after
logging in candidates as needed. Manifest/tmp/vcore-group-test-20261030/state.json
phaseapplied. Current02:00–03:00groupformation atpoi_guard_22(SW)/poi_guard_179(Org),
next03:00–04:00mixed valid native modes. Offlinecapitalrelocation plus stalevisit,
ghost,corpse,handoff cleanup applied; other22day slots preserved. Loader restored
Enabled1; RotationPercent deliberately0 through observation (original15).
MONITOR ACTIVE: Python/tmp/vcore-observe-groups.py, execsession67325. Writes every
20s to/tmp/vcore-group-observation-20261030/state.json and minute progress to
/tmp/vcore-group-observation-console.log. Deadline04:00Europe/Berlin=03:00UTC.
At deadline it automatically restores onlyRotationPercent to original15, reloads
config/population, writes final.json and exits. First processmissing alert was
initial spawn race before server started, NOT a mid-test crash. Script snapshot
loops capture server PID/RSS/CPU, native event counters, errors, groups/membership,
visits and handoffs every120s; saveall every300s for positions. Raw backups include
worldserver.conf.before containingcredentials, NEVER print/copy it into repo.
Next: check monitor state/logs periodically, investigate anomalies read-only,
recover testserver only if genuinely down. Keep turn active until04:00then
self-contained report withcounts,commit373818628d, findings andunverifiedparts.
Copy safe evidence +write report/checkpoint thenlocaldoccommit if useful; no push.
Current feature git tree was clean aftercommit; thisresumeupdate isintentional.
All builds must remain-j10. No pending build/install/test prep operations.
# ACTIVE USER REQUEST: commit flight-region extension, repeat groups, observe until04:00CET
Current dateOct30; user requires flight not only Northrend but also Outland and
@@ -57,3 +57,15 @@ rebuilt with -j1 to limit memory while it runs. Installed binary remains unchang
Final build succeeded Oct30 01:45:11. All67 AdventureBot tests passed; the last
intent-state, departure and native-DBC tests were rechecked after the final change.
No installation, migration application or restart was performed.
## Observation regression: preserve travel fallbacks
The Oct30 live group test exposed that an active early-departure snapshot was
being reapplied on every maintenance tick after a failed journey. It overrode the
normal fallback and repeatedly regenerated the original instance plan. Fix:
apply the copied slot while still in formation; after transition, effective
WantedIntent/WantedLocation own navigation. Group plans and followers inherit
that effective fallback, and a kick retains it. The logical schedule signature
and original next day slot remain unchanged. Added regression executes repeated
maintenance, fallback inheritance and leaving the group. Departure, group-plan
and intent-state tests pass; complete -j10 build passes.
+21 -6
View File
@@ -2178,7 +2178,10 @@ bool AdventureBehaviorMgr::UpdateDeparture(Player* player,Record& r,time_t now)
}
if(!r.Departure.Departed(now))
{r.Deadline=r.Departure.At;return false;}
if(r.WantedIntent!=r.Departure.Intent || r.WantedLocation!=r.Departure.Location)
// Apply the copied slot once on departure. Afterwards normal navigation
// fallbacks own the effective destination; do not pin them back every tick.
if((r.Intent.empty() || r.Intent=="groupformation") &&
(r.WantedIntent!=r.Departure.Intent || r.WantedLocation!=r.Departure.Location))
{
SetWanted(player,r,r.Departure.Intent,r.Departure.Location,r.Departure.ActivityEnd);
TC_LOG_INFO("server.adventurebot","GROUP_EARLY_DEPART guid=%u intent='%s' goal='%s'",
@@ -2204,7 +2207,12 @@ AdventureGroupPlan AdventureBehaviorMgr::GroupPlan(Player* player)
if(r.Departure.Active(now))
{
if(r.Departure.Departed(now))
{plan.Intent=r.Departure.Intent;plan.Location=r.Departure.Location;plan.Deadline=r.Departure.ActivityEnd;}
{
bool applied=!r.WantedIntent.empty() && r.WantedIntent!="groupformation";
plan.Intent=applied?r.WantedIntent:r.Departure.Intent;
plan.Location=applied?r.WantedLocation:r.Departure.Location;
plan.Deadline=applied?r.Deadline:r.Departure.ActivityEnd;
}
else {plan.Deadline=r.Departure.At;plan.NextIntent=r.Departure.Intent;plan.NextLocation=r.Departure.Location;}
}
if(r.Schedule && local.tm_hour<23)
@@ -2235,9 +2243,11 @@ bool AdventureBehaviorMgr::AdoptGroup(Player* player,Player* leader)
}
if(r.Instance.Active && r.Instance.Stage!=AdventureInstancePolicy::Phase::Travel)return true;
auto now=GameTime::GetGameTime();
auto const& intent=source.Departure.Departed(now)?source.Departure.Intent:source.Intent;
auto const& location=source.Departure.Departed(now)?source.Departure.Location:source.Location;
auto deadline=source.Departure.Departed(now)?source.Departure.ActivityEnd:source.Deadline;
bool early=source.Departure.Departed(now);
bool applied=early && !source.WantedIntent.empty() && source.WantedIntent!="groupformation";
auto const& intent=early?(applied?source.WantedIntent:source.Departure.Intent):source.Intent;
auto const& location=early?(applied?source.WantedLocation:source.Departure.Location):source.Location;
auto deadline=early && !applied?source.Departure.ActivityEnd:source.Deadline;
if(r.WantedIntent!=intent || r.WantedLocation!=location)
SetWanted(player,r,intent,location,deadline);
else r.Deadline=deadline;
@@ -2250,7 +2260,12 @@ void AdventureBehaviorMgr::ResumePersonalPlan(Player* player)
auto& r=it->second;if(!r.GroupOverride)return;r.GroupOverride=false;
auto now=GameTime::GetGameTime();
if(r.Departure.Departed(now))
SetWanted(player,r,r.Departure.Intent,r.Departure.Location,r.Departure.ActivityEnd);
{
// Leaving a group must neither revert to formation nor undo an already
// selected travel fallback within the copied activity block.
if(r.Intent.empty() || r.Intent=="groupformation")
SetWanted(player,r,r.Departure.Intent,r.Departure.Location,r.Departure.ActivityEnd);
}
else if(r.Schedule)
{
auto local=Local(now);if(r.Date!=DateOf(local))Generate(player,r,DateOf(local));
@@ -79,6 +79,15 @@ int main(){setenv("TZ","UTC",1);tzset();GameTime::now=Clock(14,20);AdventureBeha
// Kick/incomplete group cannot roll the copied current slot back.
b.GroupOverride=true;mgr.ResumePersonalPlan(&member);assert(!b.GroupOverride&&b.WantedLocation=="deadmines_d1");
assert(mgr.InteractionSchedule(&member)=="instance:deadmines_d1");
// A failed journey selects a normal fallback. Repeated maintenance must not
// repin it, followers inherit it and a kick retains it in the same intent.
b.Intent="instance";b.Location=b.WantedLocation="fallback_dungeon";unsigned changed=mgr.changes;
assert(mgr.UpdateDeparture(&member,b,GameTime::now));assert(mgr.changes==changed&&b.WantedLocation=="fallback_dungeon");
assert(mgr.GroupPlan(&member).Location=="fallback_dungeon");
b.GroupOverride=true;mgr.ResumePersonalPlan(&member);assert(b.WantedLocation=="fallback_dungeon"&&mgr.changes==changed);
a.Intent="instance";a.WantedIntent="instance";a.Location=a.WantedLocation="leader_fallback";a.Deadline=Clock(16);
mgr.AdoptGroup(&member,&leader);assert(b.WantedLocation=="leader_fallback");
assert(b.Plan[15].Location=="shadowfang_d1");
// Restore independently of any surviving group and continue the same current slot.
AdventureBehaviorMgr restored;auto&c=restored._records[2];Prepare(c,"shadowfang_d1");
restored.RestoreDeparture(&member,c);assert(c.Departure.At==Clock(14,25));