Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/core-tip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,57 @@ jobs:
run: |
./collection/.github/check-core-tip.sh "$GITHUB_WORKSPACE/lyracore" \
"$GITHUB_WORKSPACE/collection/.github/check-datascripts.sh" "$GITHUB_WORKSPACE/lyracore"

playerbots-durable:
needs: firewall
runs-on: ubuntu-latest
timeout-minutes: 30
env:
RUSTUP_TOOLCHAIN: 1.93.0
SPACETIME_VERSION: 2.7.1
SPACETIME_ARCHIVE_SHA256: 9b58192135733083479f30aba47dbbbc79b51db368c46cc221baa663e9c3a2c1
steps:
- name: Check out Packages
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: collection
persist-credentials: false
- name: Check out LyraCore main
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: LyraCoreProject/LyraCore
ref: main
path: lyracore
persist-credentials: false
- name: Install the Rust toolchain and Wasm target
run: |
rustup toolchain install 1.93.0 --profile minimal
rustup target add wasm32-unknown-unknown --toolchain 1.93.0
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
workspaces: lyracore
- name: Install the pinned SpacetimeDB CLI
run: |
archive_path="$RUNNER_TEMP/spacetime.tar.gz"
cli_dir="$RUNNER_TEMP/spacetime-$SPACETIME_VERSION"
curl --fail --location --retry 3 \
"https://github.com/clockworklabs/SpacetimeDB/releases/download/v$SPACETIME_VERSION/spacetime-x86_64-unknown-linux-gnu.tar.gz" \
--output "$archive_path"
printf '%s %s\n' "$SPACETIME_ARCHIVE_SHA256" "$archive_path" | sha256sum --check --strict
mkdir -p "$cli_dir"
tar --extract --gzip --file "$archive_path" --directory "$cli_dir"
ln -s spacetimedb-cli "$cli_dir/spacetime"
echo "$cli_dir" >> "$GITHUB_PATH"
- name: Run the real Module and Package action fixture
run: |
cargo clean --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" -p lyracore-module
./collection/.github/check-core-tip.sh "$GITHUB_WORKSPACE/lyracore" \
cargo test --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" \
-p lyracore-module --test playerbots_rewrite -- --ignored --test-threads=1
- name: Upload fixture inputs and Standalone logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: playerbots-durable-evidence
path: /tmp/lyracore-standalone-logs
if-no-files-found: ignore
55 changes: 55 additions & 0 deletions playerbots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,58 @@ request, not a record: nothing refuses it and nothing retries it, so the deadlin
the bot at all. Both leave the bot grinding with a kill objective it cannot serve, so a healthy
bot in a thin spawn area can warn at a minute. Read its `game_character_quest` rows before acting
on the warning; the fix would need a respawn timetable the Package has no read of.

## Action fixture

`module/tests/playerbots_rewrite.rs` in LyraCore drives real Package requests through a private
Standalone. Install this Package into that core checkout, then run:

```sh
cargo clean -p lyracore-module
cargo test -p lyracore-module --test playerbots_rewrite -- --ignored --test-threads=1
```

The input record is `fixtures/actions.json`. Each run records the tested core and collection commits,
whether either worktree is dirty, the Package Content Identity, and the Module wasm identity under
`/tmp/lyracore-standalone-logs`. Successful cases also save action, quest, cast, and position observations there. Content comes from core seeds and reserved fixture rows. Obstructions
come from synthetic navigation cells. No imported client geometry is present, and these cases do not
prove imported-world routing or real-client appearance.

The fixture uses the existing gameplay operations. A Cast Handle correlates a scheduled spell with
its terminal outcome; accepting an attack does not certify a hit or quest credit. The bounded
`pkg_playerbots_action` table retains the latest observation of each action kind per Character.

The rewrite adopts AzerothCore's decision grammar in Rust. The reference inventory at
`b949b50bfcdd4fab937781bac2d7765e39330e4b` counts 2,967 lines for the selection kernel and 243,560 for
the whole runtime. Even the kernel retains C++ host pointers and packet-bearing events. Porting that
runtime would require synthetic WotLK World Sessions, packet queues, and host objects before replacing
them with LyraCore's Module operations. Keeping typed decisions and durable identifiers beside the
existing cast, combat, navigation, quest, and item operations is the smaller total implementation.
The counts describe the reference source, not an estimate of the Rust rewrite.

When sharing `CARGO_TARGET_DIR` between checkouts, clean the Module after changing the worktree or
installed Package inventory. Its build script discovers Package files and hooks. A shared cache can
otherwise reuse discovery output from the previous checkout. Dependency artifacts can stay cached.

Cast observations retain the original Cast Handle while waiting. Instant effects resolve in the
request itself, before any scheduled completion callback. `CastResolved` means effects dispatched;
a projectile can still be in flight. Channel requests explicitly return `UnsupportedChannel` until
channel ownership is implemented. Targeted casts currently have no shared line-of-sight Gate; this
fixture does not invent a line-of-sight refusal. Actor requests also retain the existing spellbook
bypass; later capability selection must require known, supported spells.

Movement observations retain complete, partial, blocked, and direct planning status, clipping,
coverage, and a last-advance time measured from successive actual positions. Complete planning is
separate from arrival. Attack acceptance is separate from quest credit; the quest progress clock
resets only when objective counts increase or a synchronous quest operation succeeds.

Quest interactions finish synchronously. The core plans collect-item consumption and all rewards
before changing inventory, so a caught turn-in Refusal leaves items, money, experience, and the quest
unchanged. The fixture covers an invalid reward choice, full inventory, successful retry after a
slot is freed, and a source-item acceptance refusal. Imported item uniqueness limits now apply to
storage and reward exchanges, including bank holdings and other rewards in the same exchange.

`pkg_playerbots_goal.quest_credit` is an end-appended nullable count with a null default. The first
observation establishes its baseline without clearing an existing stall. Later increases count as
progress. The fixture exercises an existing stalled goal with nonzero objective credit and this
migration default; it does not claim to publish an older Package binary before upgrading it.
48 changes: 48 additions & 0 deletions playerbots/fixtures/actions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"fixture": "playerbots-actions-v1",
"baseline_core": "95e6ad8c61540f74471e3087897e8c3ef7e065d1",
"baseline_collection": "c32b2fb7aa405190728034b63ce6eb9a3c0dd6be",
"reference": "b949b50bfcdd4fab937781bac2d7765e39330e4b",
"content": {
"revision": "playerbots-seeded-actions-v1",
"provenance": "core seeded templates and reserved fixture rows",
"heal_source_spell": 2050,
"creature_source_entry": 51000,
"item_source": "first starter item held by the seeded role-1 bot"
},
"imported_content": null,
"geometry": {
"revision": "playerbots-synthetic-nav-v1",
"provenance": "synthetic walk and obstruction arrays",
"client_geometry": null,
"blocked": "3 by 3 navigation cells, walk bytes 0, obs bytes 20, base_z 50",
"partial": "9 cells along y, one nonwalkable x sub-cell at 1210, other walk bits 1, obs bytes 255"
},
"spacetimedb": "2.7.1",
"rust": "1.93.0",
"map": 0,
"instance": 0,
"position": [
1200,
1200,
50
],
"heal": {
"spell": 5090100,
"source_spell": 2050,
"cast_time_ms": 5000,
"cost": 0
},
"poor_range_target_x": 1400,
"quest": {
"hunt": 50909,
"target_entry": 5090101,
"required_kills": 2,
"interaction": 50910,
"collect_item": 5090120,
"guaranteed_reward": 5090121,
"choice_reward": 5090122,
"filler_item": 5090123,
"full_inventory_slots": 16
}
}
Loading
Loading