Skip to content

fix(creatures): start a renewed path where the client draws the mover - #612

Merged
Mathih13 merged 1 commit into
mainfrom
fix/creature-path-renewal-start
Oct 5, 2026
Merged

Mathih13 merged 1 commit into
mainfrom
fix/creature-path-renewal-start

Conversation

@Mathih13

@Mathih13 Mathih13 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

A bot that gets a new Route Path while it walks can jump back on the client. The new path starts at the mover's stored position. That position can lag the point the client draws by up to 4 yd for an out-of-combat creature, and by one 500 ms firing for a Character. So the new spline starts behind the mover and the client moves it back. #603 fixed this for a stop. A renewal through emit_creature_path still had the gap.

emit_creature_path now starts the path at the same point stop_where_rendered stops at. It uses the same stop_on_leg rule, with the obstruction check. The two functions share a small helper, place_where_rendered. The new leg also takes a spline id newer than the leg it replaces, so the client does not drop a renewal made in the same millisecond.

Only the playerbots runner calls emit_creature_path, so the test needs a way in. I added the debug reducer debug_creature_path and regenerated its Gateway binding. Creature legs that the behavior cycle sends already start at the right point, because the leg advance runs first in the same firing.

Verification (macOS, local SpacetimeDB 2.7.1):

  • creature_path_renewal::a_path_renewed_mid_leg_starts_where_the_client_renders_the_mover (new durable test). Before the fix it failed: the renewed path started at x = -8949.176 and the client drew the wolf at -8949.447. With the fix it passes.
  • creature_death_stop passes.
  • cargo test -p lyracore-module --lib --features=debug_reducers creatures::: 389 passed.
  • cargo clippy -p lyracore-module --all-targets --features debug_reducers -- -D warnings and cargo fmt --all -- --check are clean.
  • scripts/check-gateway-bindings.py on the regenerated tree: all 1166 binding files are current.

Packages needs no change. The runner's begin() still plans the route from the stored position. The first waypoint can be a short distance behind the new start, but the client no longer jumps back.

Closes #608

Model and harness: Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code

emit_creature_path started the new leg at the mover's stored position.
The stored row can lag the leg by up to 4 yd for an out-of-combat
creature and by one firing for a Character, so a renewal between two
advance firings sent the client back along the old leg.

The path now starts at the point stop_where_rendered would stop the
mover at, including the obstruction check, and takes a spline id newer
than the leg it replaces. Both share place_where_rendered.

debug_creature_path drives emit_creature_path on a test shard, and
creature_path_renewal renews a path mid-leg and checks the new start.

Closes #608

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 47 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d35396e8-3fb7-48f2-a5e2-9729279cfa20
📥 Commits

Reviewing files that changed from the base of the PR and between f454a98 and 8b4095a.

📒 Files selected for processing (7)
  • CONTEXT.md
  • docs/package-api.md
  • gateway/src/stdb/bindings/debug_creature_path_reducer.rs
  • gateway/src/stdb/bindings/mod.rs
  • module/src/creatures/tick/mod.rs
  • module/src/debug/mod.rs
  • module/tests/creature_path_renewal.rs
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Mathih13 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Code review: 8b4095a against main

I found no blocking issues. Every finding is P3 (nit) except one P2 judgement call on the test.

Standards

Sources: CODING_STANDARDS.md, AGENTS.md, CONTEXT.md, and the Fowler smell baseline. I skipped the generated Gateway bindings.

  • P2, Duplicated Code (judgement call), module/tests/creature_path_renewal.rs. type Row, fn number<T> and const LEG_YD are copied from creature_death_stop.rs. creature_advance_persist.rs has the same Row and LEG_YD, and its yd is another copy of number. This is the third copy. Moving them into module/tests/support would touch other test files, so a follow-up is fine.
  • P3, Mysterious Name (judgement call), place_where_rendered. It moves mover and also returns the old leg's spline id. The name does not show the return value, and it reads close to stop_where_rendered. The doc comment covers it.
  • P3, Duplicated Code (judgement call). emit_creature_path and stop_where_rendered both build next_spline_id(ctx.timestamp.to_micros_since_unix_epoch() as u64, previous). A small shared helper is optional.
  • No glossary _Avoid_ words are used. CONTEXT.md (Route Path) and docs/package-api.md are updated in the same change, as AGENTS.md asks.
  • The allow(dead_code) on emit_creature_path is still needed, because mod debug is gated behind debug_reducers.

Spec (#608)

  • P3, partial: "including the obstruction check". stop_on_stored_leg is reused, so path_obstruction runs. The test walks open ground, so the halted-short branch is not exercised for a renewal. The rule is shared with stop_where_rendered, so the risk is low.
  • P3, test strength: "asserts the new spline's start equals the rendered point". The test asserts this, but it does not check that the stored row lagged before the renewal. A firing that lands a few ms before the renewal would let it pass without the fix. That is rare. Asserting that the stored x differs from the rendered x before the renewal would make the test prove the bug.
  • P3, new edge case. The zero-length check now measures from the rendered point. A renewal whose points all equal that point returns without a write, and the old leg keeps going. Before this change it sent a leg from the stored position. This is a rare corner that the spec does not cover.
  • P3, scope. debug_creature_path sends a raw (x, y, z) with no navigation check, but emit_creature_path expects an already checked path. That is fine for an operator-only debug reducer. A doc line saying the path is unchecked would help.
  • The spline-id change is outside the issue's wording but justified: a renewal now replaces a live leg, and the PR text explains it.
  • The test geometry is sound. With one waypoint, the linear lerp matches the client sample. walked comes from the stored start_micros, not the wall clock, so the sleep is not flaky.

Summary: Standards has 3 findings, the worst is the P2 copy of the test helpers. Spec has 4 findings, the worst is the untested obstruction branch (P3).


Generated by Claude Code

@Mathih13

Mathih13 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

An independent Opus review and the routine review found nothing that blocks merge. I moved the low findings to follow-ups so this PR doesn't need another CI round:

@Mathih13
Mathih13 merged commit 1a47b8b into main Oct 5, 2026
10 of 11 checks passed
@Mathih13
Mathih13 deleted the fix/creature-path-renewal-start branch October 11, 2026 18:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(creatures): a renewed path starts from the stored point, not where the client draws the mover

1 participant