diff --git a/.github/workflows/core-tip.yml b/.github/workflows/core-tip.yml index 6238b40..b645698 100644 --- a/.github/workflows/core-tip.yml +++ b/.github/workflows/core-tip.yml @@ -71,7 +71,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false @@ -136,7 +136,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false @@ -202,7 +202,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install the Rust toolchain and Wasm target @@ -753,7 +753,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install the Rust toolchain and Wasm target @@ -975,7 +975,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install the Rust toolchain and Wasm target @@ -1174,7 +1174,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install the Rust toolchain and Wasm target diff --git a/.github/workflows/playerbots-capacity.yml b/.github/workflows/playerbots-capacity.yml index a1b6086..a96f4bf 100644 --- a/.github/workflows/playerbots-capacity.yml +++ b/.github/workflows/playerbots-capacity.yml @@ -42,7 +42,7 @@ jobs: with: repository: LyraCoreProject/LyraCore # Core supplies the shared private integration fixtures. - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/playerbots-class-behavior.yml b/.github/workflows/playerbots-class-behavior.yml index 853c1f3..1ec0189 100644 --- a/.github/workflows/playerbots-class-behavior.yml +++ b/.github/workflows/playerbots-class-behavior.yml @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install pinned Rust and SpacetimeDB diff --git a/.github/workflows/playerbots-target-claims.yml b/.github/workflows/playerbots-target-claims.yml index 44165ef..ac5d077 100644 --- a/.github/workflows/playerbots-target-claims.yml +++ b/.github/workflows/playerbots-target-claims.yml @@ -48,7 +48,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: LyraCoreProject/LyraCore - ref: 7e83dc2cfe7af2df8a475cd02d489b7647e853ae + ref: f91066df4aef5c8d753dbe1d2203c6a669f485fa path: lyracore persist-credentials: false - name: Install pinned Rust and SpacetimeDB diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7d645a..c98ea43 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,5 +16,12 @@ its `script.identity` Build Identity sidecar may be committed under a Package's names and refuses any other committed file there. `lyracore packages check` verifies the Build Identity against the current core checkout. +Runtime Scripts declare a named function that takes its typed event and register it with +`events.player.onLogin`, another built-in event, or `events.package.on` for a Package Event. +Each source has one Event Binding. The Runtime Script Toolchain writes stable numeric IDs to the +Package-root `script-ids.json`; new sources need no `@id` directive. Commit that ledger with the +sources, Script Artifact and Build Identity. Keep entries for removed sources so later sources +cannot reuse their IDs. + Pull requests must pass the `module` core-tip compatibility check before merge. Maintainers may use their GitHub branch-protection bypass only to recover the repository or repair CI. diff --git a/README.md b/README.md index b2c4f93..327e52b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ This repository is LyraCore's Official Package Collection. Each visible top-level directory is one independently installable Package. There is no separate registry or index file. -Each Package API version has a tag, such as `api-v1`. After the compatibility checks pass on +The typed Runtime Script examples require Package API version 2. Each Package API version has a +tag, such as `api-v2`. After the compatibility checks pass on `main`, CI moves the tag for the checked Core revision's Package API version to that collection commit. Tags for older API versions stay at their last compatible commit. diff --git a/example-all/README.md b/example-all/README.md index 68b4d6d..abf163b 100644 --- a/example-all/README.md +++ b/example-all/README.md @@ -1,16 +1,18 @@ # Rust asks a Runtime Script On login, Rust calls `ask()` for Package Event `example-all.welcome`. `scripts/welcome.lua` -answers `1`, so Rust sends a welcome through `actor::system_message`. Change the Script Answer -to `0` to suppress it. +registers its `welcome(event)` function with `events.package.on("welcome", welcome)` and answers +`1`, so Rust sends a welcome through `actor::system_message`. Change the Script Answer to `0` to +suppress it. When no script answers, Rust reads Package Config key `welcome`. `false` suppresses the greeting; `true`, a missing value, or an invalid value sends it. The default is `true`. Package tests run -the authored Lua in the Runtime Script Host and check the fallback. +the compiled Script Artifact Lua in the Runtime Script Host and check the fallback. Install with `./lyracore packages add example-all`, then run `./lyracore packages apply` on your development topology. It builds artifacts when needed, publishes the Module, repairs schedules, and applies the Script Artifact. -After editing the Runtime Script, run `./lyracore packages build` and commit its Script -Artifact and Build Identity together. Its Script ID is 100302. Give copies distinct IDs before -installing them together. +After editing the Runtime Script, run `./lyracore packages build`. Commit the sources, +`script-ids.json`, Script Artifact and its Build Identity together. The Runtime Script Toolchain +manages IDs in `script-ids.json`; keep its entries when you remove a source. Use +`./lyracore packages new NAME --from example-all` to make a copy with new IDs. diff --git a/example-all/data/.generated/example-all.script.json b/example-all/data/.generated/example-all.script.json index dbc2c2f..1b7b148 100644 --- a/example-all/data/.generated/example-all.script.json +++ b/example-all/data/.generated/example-all.script.json @@ -2,7 +2,7 @@ "kind": "script", "version": 1, "package": "example-all", - "source_hash": "bd88e41c6f9976c287287db30ed0ce0b07d0b64fca7398d1093f5987dacc9dfb", + "source_hash": "da52243f0368fd7089dab7de331069ec91a3d18356c5f6104414ebed5dfe4695", "scripts": [ { "script_id": 100302, @@ -10,7 +10,7 @@ "event": "example-all.welcome", "priority": 0, "enabled": true, - "source": "-- @event example-all.welcome\n-- @id 100302\n\n-- A positive Script Answer sends the welcome. Zero suppresses it.\nreturn 1\n" + "source": "local ____lyracore_handler\nlocal events = { package = { on = function(name, handler) ____lyracore_handler = handler end } }\n-- A positive Script Answer sends the welcome. Zero suppresses it.\nlocal function welcome(event)\n return 1\nend\n\nevents.package.on(\"welcome\", welcome)\nassert(event.name == \"example-all.welcome\", \"Event Binding does not match the Invocation\")\nreturn ____lyracore_handler(event)\n" } ] } diff --git a/example-all/data/.generated/script.identity b/example-all/data/.generated/script.identity index f4ca595..e8a01b1 100644 --- a/example-all/data/.generated/script.identity +++ b/example-all/data/.generated/script.identity @@ -1 +1 @@ -{"artifact_hash":"sha256-v1:7e6c882d9086c81c9bb49d1a676b8d96cd7f2c08d9dc5e4662d72eeb95f9a816","bun_lock_hash":"sha256-v1:a3dc4c9ef1ff2b0b3502de7fc828c237f16df8a817e14a3412a08f8b052c0252","bun_version":"1.3.7","source_hash":"sha256-script-sources-v1:bd88e41c6f9976c287287db30ed0ce0b07d0b64fca7398d1093f5987dacc9dfb","toolchain_hash":"sha256-dir-v1:f53d4056ac988e2966186bcc407b34a9ed525b385e53cc7135d2fa866dab69f4","version":1} \ No newline at end of file +{"artifact_hash":"sha256-v1:33fbf39669bdd50c1dd1663a0d99e1ce3685f4b955a36d9dce978a1a5470aecb","bun_lock_hash":"sha256-v1:204b5c8c24eb4aa5256713ba8a0d321e06bb60a3adf7889b839932cd895bf079","bun_version":"1.3.7","source_hash":"sha256-script-sources-v1:da52243f0368fd7089dab7de331069ec91a3d18356c5f6104414ebed5dfe4695","toolchain_hash":"sha256-dir-v1:8210555afb9a86ad523c1d19f93dd7440c14c509262493637ca79a0ff115aa08","version":1} \ No newline at end of file diff --git a/example-all/script-ids.json b/example-all/script-ids.json new file mode 100644 index 0000000..6466105 --- /dev/null +++ b/example-all/script-ids.json @@ -0,0 +1,7 @@ +{ + "version": 1, + "package": "example-all", + "ids": { + "welcome": 100302 + } +} diff --git a/example-all/scripts/welcome.lua b/example-all/scripts/welcome.lua index d962a53..acc4213 100644 --- a/example-all/scripts/welcome.lua +++ b/example-all/scripts/welcome.lua @@ -1,5 +1,6 @@ --- @event example-all.welcome --- @id 100302 - -- A positive Script Answer sends the welcome. Zero suppresses it. -return 1 +local function welcome(event) + return 1 +end + +events.package.on("welcome", welcome) diff --git a/example-all/src/tests.rs b/example-all/src/tests.rs index 5dd6659..232c77c 100644 --- a/example-all/src/tests.rs +++ b/example-all/src/tests.rs @@ -1,17 +1,14 @@ #![cfg(test)] -use crate::package_test::{ask_offline, RuntimeScript}; +use crate::package_test::{ask_artifact_offline, ask_offline}; #[test] fn the_script_answer_overrides_config() { - let answer = ask_offline( + let answer = ask_artifact_offline( super::WELCOME_EVENT, None, None, - &[RuntimeScript { - name: "example-all.welcome", - source: include_str!("../scripts/welcome.lua"), - }], + include_str!("../data/.generated/example-all.script.json"), ) .unwrap(); assert_eq!(answer, Some(1.0)); diff --git a/example-script/README.md b/example-script/README.md index b207d4c..72168cd 100644 --- a/example-script/README.md +++ b/example-script/README.md @@ -1,11 +1,14 @@ # Welcome with Runtime Scripts -`welcome.ts` sends one chat line on login. `ding.lua` sends one on level-up. Both use -`send_chat` on the Character carried by the event. This Package needs no Rust. +`welcome.ts` registers `welcome` with `events.player.onLogin`. `ding.lua` registers `ding` with +`events.player.onLevelUp`. Both send one chat line to `event.player`, the Character the typed event +guarantees. This Package needs no Rust. Install with `./lyracore packages add example-script`, then apply the committed Script Artifact -with `./lyracore packages apply` on your development topology. It builds missing or stale artifacts when needed. After editing -either source, run -`./lyracore packages build` and commit the Script Artifact and its Build Identity together. +with `./lyracore packages apply` on your development topology. It builds missing or stale artifacts +when needed. After editing either source, run `./lyracore packages build`. Commit the sources, +`script-ids.json`, Script Artifact and its Build Identity together. -The Script IDs are 100300 and 100301. Give copies distinct IDs before installing them together. +The Runtime Script Toolchain manages IDs in `script-ids.json`. Keep the ledger, including entries +for removed sources. Each Runtime Script keeps the name `.` and its ID when +you rename its handler. Use `./lyracore packages new NAME` to make a copy with new IDs. diff --git a/example-script/data/.generated/example-script.script.json b/example-script/data/.generated/example-script.script.json index d4c82d6..ab67ae3 100644 --- a/example-script/data/.generated/example-script.script.json +++ b/example-script/data/.generated/example-script.script.json @@ -2,7 +2,7 @@ "kind": "script", "version": 1, "package": "example-script", - "source_hash": "24b601f2db72799e6c3879c59b1bfd03d4ee92e10dde5ebc94920fb91cea9f72", + "source_hash": "b0ac07be3c3f6367321bec3fa9294fa6bc5be30da36edd4357029446c37e8fbd", "scripts": [ { "script_id": 100300, @@ -10,7 +10,7 @@ "event": "on_login", "priority": 0, "enabled": true, - "source": "local function ____tbl(t)\n return t\nend\nlocal function script()\n if event.actor and event.actor.is_player then\n send_chat(event.actor, \"Welcome from example-script!\")\n end\nend\nreturn script()\n" + "source": "local ____lyracore_handler\nlocal events = { player = { onLogin = function(handler) ____lyracore_handler = handler end } }\nlocal function ____tbl(t)\n return t\nend\nlocal function welcome(event)\n send_chat(event.player, \"Welcome from example-script!\")\nend\nevents.player.onLogin(welcome)\nassert(event.name == \"on_login\", \"Event Binding does not match the Invocation\")\nassert(event.player and event.player.is_player, \"on_login requires a Character\")\nreturn ____lyracore_handler(event)\n" }, { "script_id": 100301, @@ -18,7 +18,7 @@ "event": "on_levelup", "priority": 0, "enabled": true, - "source": "-- @event on_levelup\n-- @id 100301\n\nif event.actor and event.actor.is_player then\n send_chat(event.actor, \"Welcome to your new level from example-script!\")\nend\n" + "source": "local ____lyracore_handler\nlocal events = { player = { onLevelUp = function(handler) ____lyracore_handler = handler end } }\nlocal function ding(event)\n send_chat(event.player, \"Welcome to your new level from example-script!\")\nend\n\nevents.player.onLevelUp(ding)\nassert(event.name == \"on_levelup\", \"Event Binding does not match the Invocation\")\nassert(event.player and event.player.is_player, \"on_levelup requires a Character\")\nreturn ____lyracore_handler(event)\n" } ] } diff --git a/example-script/data/.generated/script.identity b/example-script/data/.generated/script.identity index cecf6cc..3604f8c 100644 --- a/example-script/data/.generated/script.identity +++ b/example-script/data/.generated/script.identity @@ -1 +1 @@ -{"artifact_hash":"sha256-v1:8f8a8b9d8d9b029091c7478912c35d1b7a0a74bda9b9fbbb8c8ed9672fd35a07","bun_lock_hash":"sha256-v1:a3dc4c9ef1ff2b0b3502de7fc828c237f16df8a817e14a3412a08f8b052c0252","bun_version":"1.3.7","source_hash":"sha256-script-sources-v1:24b601f2db72799e6c3879c59b1bfd03d4ee92e10dde5ebc94920fb91cea9f72","toolchain_hash":"sha256-dir-v1:f53d4056ac988e2966186bcc407b34a9ed525b385e53cc7135d2fa866dab69f4","version":1} \ No newline at end of file +{"artifact_hash":"sha256-v1:6664b08332c285da3a50665d73321c8ebff4ad53160c57606690261a2e616907","bun_lock_hash":"sha256-v1:204b5c8c24eb4aa5256713ba8a0d321e06bb60a3adf7889b839932cd895bf079","bun_version":"1.3.7","source_hash":"sha256-script-sources-v1:b0ac07be3c3f6367321bec3fa9294fa6bc5be30da36edd4357029446c37e8fbd","toolchain_hash":"sha256-dir-v1:8210555afb9a86ad523c1d19f93dd7440c14c509262493637ca79a0ff115aa08","version":1} \ No newline at end of file diff --git a/example-script/script-ids.json b/example-script/script-ids.json new file mode 100644 index 0000000..e80466c --- /dev/null +++ b/example-script/script-ids.json @@ -0,0 +1,8 @@ +{ + "version": 1, + "package": "example-script", + "ids": { + "ding": 100301, + "welcome": 100300 + } +} diff --git a/example-script/scripts/ding.lua b/example-script/scripts/ding.lua index b18f08c..a89ead0 100644 --- a/example-script/scripts/ding.lua +++ b/example-script/scripts/ding.lua @@ -1,6 +1,5 @@ --- @event on_levelup --- @id 100301 - -if event.actor and event.actor.is_player then - send_chat(event.actor, "Welcome to your new level from example-script!") +local function ding(event) + send_chat(event.player, "Welcome to your new level from example-script!") end + +events.player.onLevelUp(ding) diff --git a/example-script/scripts/welcome.ts b/example-script/scripts/welcome.ts index a6fccb5..20d93aa 100644 --- a/example-script/scripts/welcome.ts +++ b/example-script/scripts/welcome.ts @@ -1,8 +1,5 @@ -// @event on_login -// @id 100300 - -function script(): void { - if (event.actor && event.actor.is_player) { - send_chat(event.actor, "Welcome from example-script!"); - } +function welcome(event: PlayerLoginEvent): void { + send_chat(event.player, "Welcome from example-script!"); } + +events.player.onLogin(welcome); diff --git a/playerbots/testsuite/Cargo.lock b/playerbots/testsuite/Cargo.lock index afba991..713dc85 100644 --- a/playerbots/testsuite/Cargo.lock +++ b/playerbots/testsuite/Cargo.lock @@ -171,6 +171,7 @@ version = "0.1.0" name = "lyracore-test-support" version = "0.1.0" dependencies = [ + "rustc_lexer", "serde_json", ] @@ -265,6 +266,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rustc_lexer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" +dependencies = [ + "unicode-xid", +] + [[package]] name = "serde" version = "1.0.229" @@ -364,6 +374,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "version_check" version = "0.9.5"