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
3 changes: 2 additions & 1 deletion .github/workflows/core-tip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ jobs:
}
manifest_path.write_text(json.dumps(manifest, indent=2) + "\n")
PY
echo "PLAYERBOTS_CATALOG_PRECEDING_WASM=$RUNNER_TEMP/playerbots-pb002-preceding.wasm" >> "$GITHUB_ENV"
echo "PLAYERBOTS_COMPANION_PRECEDING_WASM=$RUNNER_TEMP/playerbots-pb002-preceding.wasm" >> "$GITHUB_ENV"
echo "PLAYERBOTS_PB002_WASM=$RUNNER_TEMP/playerbots-pb002-preceding.wasm" >> "$GITHUB_ENV"
echo "PLAYERBOTS_COMPANION_PRECEDING_MANIFEST=$RUNNER_TEMP/playerbots-pb002-preceding-inputs.json" >> "$GITHUB_ENV"
Expand All @@ -284,7 +285,7 @@ jobs:
-p lyracore-module --features=debug_reducers
cargo test --manifest-path "$GITHUB_WORKSPACE/lyracore/Cargo.toml" \
-p lyracore-module --test playerbots_rewrite --test playerbots_companion \
--test playerbots_provisioning \
--test playerbots_provisioning --test playerbots_quest_catalog \
--no-fail-fast -- --ignored --test-threads=1
'
- name: Upload fixture inputs and Standalone logs
Expand Down
7 changes: 7 additions & 0 deletions playerbots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ unchanged. The fixture covers an invalid reward choice, full inventory, successf
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.

The quest catalog fixture runs only on a private Standalone with an empty Import Catalogue. Its first
stage refuses if a required Northshire row or Fixture-Reserved Identifier already exists, then records
private fixture ownership. Repeating that stage is a no-op. Any later import makes every quest fixture
operation refuse before mutation. The low quest and world entries retain their Northshire meaning, but
the fixture definitions are synthetic stand-ins and do not prove an imported-world run. Static
relation, objective, and loot rows use the project-wide Fixture-Reserved Identifier band.

`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
Expand Down
44 changes: 44 additions & 0 deletions playerbots/fixtures/quest-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"fixture": "playerbots-quest-catalog-v1",
"catalog": "northshire-elwynn-supported-v1",
"catalog_revision": 1,
"blueprint_revision": "classicdb:d2083bcd2670451279cbf93af138eadae04c6d183a4cd0ff0357047e4a565de6",
"reference_source_revision": "unknown",
"observed_content_revision": "computed from staged quest, relation, objective, loot, item, and spawn rows",
"starter_classes": [
{ "class": 1, "name": "warrior", "seed": 783001 },
{ "class": 5, "name": "priest", "seed": 783005 },
{ "class": 8, "name": "mage", "seed": 783008 }
],
"quest_order": [783, 7, 5261, 33, 18, 3903, 3904, 3905, 40, 35, 37, 45],
"caught_refusals": [
"inventory-full take preserves carried inventory and GameObject loot"
],
"held_admission": [
"provided delivery item destroyed after accept waits with missing capability",
"provided delivery item banked after accept waits with missing capability"
],
"synthetic_destinations": {
"creature_6": "0xf130000006000001",
"creature_299": "0xf13000012b000001",
"gameobject_55": "0xf110000000000037",
"gameobject_56": "0xf110000000000038",
"gameobject_161557": "0xf110000000027715"
},
"source_inspection": {
"path": ".import/classic-db-full.sql",
"size_bytes": 73294017,
"sha256": "d2083bcd2670451279cbf93af138eadae04c6d183a4cd0ff0357047e4a565de6",
"imported_world_run": false,
"client_geometry": null
},
"fixture_boundary": {
"import_catalogue_required_empty": true,
"semantic_entries_required_absent": true,
"semantic_entries_replaced": false,
"static_surrogate_id_band": "5090000-5099999",
"repeat_stage": "no-op for the same owned fixture revision",
"later_import": "refused before mutation"
},
"provenance": "Private Standalone rows shaped from the inspected ClassicDB schema. Coordinates, item drops, and action outcomes in this fixture are synthetic."
}
73 changes: 73 additions & 0 deletions playerbots/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub enum ActionKind {
Move,
AcceptQuest,
TurnInQuest,
UseGameObject,
OpenLoot,
TakeLoot,
}

#[derive(spacetimedb::SpacetimeType, Clone, Debug)]
Expand Down Expand Up @@ -223,6 +226,76 @@ pub(super) fn turn_in_quest(
)
}

#[cfg_attr(
not(feature = "debug_reducers"),
allow(
dead_code,
reason = "the catalog executor is driven by its durable debug_reducers fixture"
)
)]
pub(super) fn use_gameobject(
ctx: &ReducerContext,
guid: u64,
go_guid: u64,
quest: u32,
) -> Result<(), crate::actor::ActionRefusal> {
interaction(
ctx,
guid,
go_guid,
quest,
ActionKind::UseGameObject,
crate::actor::request_use_gameobject(ctx, guid, go_guid),
)
}

#[cfg_attr(
not(feature = "debug_reducers"),
allow(
dead_code,
reason = "the catalog executor is driven by its durable debug_reducers fixture"
)
)]
pub(super) fn open_creature_loot(
ctx: &ReducerContext,
guid: u64,
corpse_guid: u64,
quest: u32,
) -> Result<(), crate::actor::ActionRefusal> {
interaction(
ctx,
guid,
corpse_guid,
quest,
ActionKind::OpenLoot,
crate::actor::request_open_creature_loot(ctx, guid, corpse_guid),
)
}

#[cfg_attr(
not(feature = "debug_reducers"),
allow(
dead_code,
reason = "the catalog executor is driven by its durable debug_reducers fixture"
)
)]
pub(super) fn take_loot(
ctx: &ReducerContext,
guid: u64,
source_guid: u64,
loot_slot: u8,
quest: u32,
) -> Result<(), crate::actor::ActionRefusal> {
interaction(
ctx,
guid,
source_guid,
quest,
ActionKind::TakeLoot,
crate::actor::request_take_loot(ctx, guid, source_guid, loot_slot),
)
}

/// Planning evidence plus progress measured at the next request, never at a proposed endpoint.
#[derive(spacetimedb::SpacetimeType, Clone, Debug)]
pub struct MovementObservation {
Expand Down
1 change: 1 addition & 0 deletions playerbots/src/decision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub enum Reason {
Resurrection,
PartyUnavailable,
Provisioning,
Quest,
}

#[derive(spacetimedb::SpacetimeType, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
Expand Down
5 changes: 5 additions & 0 deletions playerbots/src/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ mod companion;
mod decision;
mod goals;
mod provisioning;
mod quest_catalog;
mod runner;
pub(crate) use actions::*;
pub(crate) use provisioning::*;
pub(crate) use quest_catalog::*;
pub(crate) use runner::*;
#[cfg(feature = "debug_reducers")]
mod fixture;
#[cfg(feature = "debug_reducers")]
mod quest_catalog_fixture;
pub(crate) use goals::*;

use crate::package_config::game_package_config;
Expand Down Expand Up @@ -376,6 +380,7 @@ pub(crate) fn ensure_defaults(ctx: &ReducerContext) {
for (key, value) in CONFIG_DEFAULTS {
crate::package_config::ensure_package_config_default(ctx, PACKAGE, key, value);
}
quest_catalog::ensure_catalog(ctx);
if ctx.db.pkg_playerbots_kit().count() > 0 {
return;
}
Expand Down
Loading
Loading