From 644b2d671fae97e7a066c49e7de142eabf5eb50b Mon Sep 17 00:00:00 2001 From: Michael Gilardi <11632652+mgilardi@users.noreply.github.com> Date: Sat, 14 Nov 2026 12:40:01 -0700 Subject: [PATCH] Rename Voidwell to OneVoid (0.2.0) D194, with no old names kept (D196): package, plugin, jar, commands, permissions, data folder, tests and docs. It also follows Mayor (D198), WelcomeWagon (D197) and Sheriff by their new names. The first-public audit's search-terms row now describes the terms instead of listing them. Unit tests pass. Checked with the other renamed plugins on a throwaway server before release. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/build.yml | 2 +- .github/workflows/release.yml | 4 +- README.md | 50 +++++++-------- build.gradle.kts | 4 +- docs/decisions.md | 4 ++ docs/first-public-push-audit.md | 4 +- docs/releases/v0.2.0.md | 13 ++++ docs/test-audit.md | 12 ++-- settings.gradle.kts | 2 +- .../{voidwell => onevoid}/CommandGuard.java | 8 +-- .../OneVoidCommand.java} | 44 ++++++------- .../OneVoidPlugin.java} | 52 ++++++++-------- .../{voidwell => onevoid}/RewildKeeps.java | 2 +- .../{voidwell => onevoid}/Settings.java | 2 +- .../extantape/{voidwell => onevoid}/Text.java | 6 +- .../bell/BellListener.java | 12 ++-- .../{voidwell => onevoid}/bell/WayBells.java | 12 ++-- .../menu/IslandMenus.java | 14 ++--- .../{voidwell => onevoid}/menu/Menu.java | 2 +- .../menu/MenuListener.java | 2 +- .../{voidwell => onevoid}/meter/Meter.java | 2 +- .../meter/ThrowListener.java | 8 +-- .../meter/ValueTable.java | 2 +- .../meter/VoidMeter.java | 16 ++--- .../oneblock/OneBlockBridge.java | 16 ++--- .../{voidwell => onevoid}/reward/Powers.java | 12 ++-- .../{voidwell => onevoid}/reward/Reward.java | 2 +- .../{voidwell => onevoid}/reward/Rewards.java | 14 ++--- .../{voidwell => onevoid}/social/Social.java | 36 +++++------ .../social/VisitorGuard.java | 14 ++--- .../store/IslandStore.java | 4 +- .../store/PlayerData.java | 6 +- .../store/PlayerStore.java | 8 +-- .../trip/DeathListener.java | 16 ++--- .../{voidwell => onevoid}/trip/Trips.java | 14 ++--- src/main/resources/config.yml | 8 +-- src/main/resources/paper-plugin.yml | 20 +++--- .../CommandGuardTest.java | 4 +- .../RewildKeepsTest.java | 4 +- .../meter/MeterTest.java | 2 +- .../social/ShareCircleTest.java | 6 +- test/README.md | 6 +- test/fetch.mjs | 6 +- test/lib.mjs | 26 ++++---- test/package.json | 2 +- .../extantape/waystation/StandinPlugin.java | 2 +- test/suite.mjs | 62 +++++++++---------- 47 files changed, 293 insertions(+), 276 deletions(-) create mode 100644 docs/releases/v0.2.0.md rename src/main/java/com/extantape/{voidwell => onevoid}/CommandGuard.java (90%) rename src/main/java/com/extantape/{voidwell/VoidwellCommand.java => onevoid/OneVoidCommand.java} (78%) rename src/main/java/com/extantape/{voidwell/VoidwellPlugin.java => onevoid/OneVoidPlugin.java} (81%) rename src/main/java/com/extantape/{voidwell => onevoid}/RewildKeeps.java (99%) rename src/main/java/com/extantape/{voidwell => onevoid}/Settings.java (99%) rename src/main/java/com/extantape/{voidwell => onevoid}/Text.java (88%) rename src/main/java/com/extantape/{voidwell => onevoid}/bell/BellListener.java (96%) rename src/main/java/com/extantape/{voidwell => onevoid}/bell/WayBells.java (95%) rename src/main/java/com/extantape/{voidwell => onevoid}/menu/IslandMenus.java (97%) rename src/main/java/com/extantape/{voidwell => onevoid}/menu/Menu.java (97%) rename src/main/java/com/extantape/{voidwell => onevoid}/menu/MenuListener.java (96%) rename src/main/java/com/extantape/{voidwell => onevoid}/meter/Meter.java (98%) rename src/main/java/com/extantape/{voidwell => onevoid}/meter/ThrowListener.java (92%) rename src/main/java/com/extantape/{voidwell => onevoid}/meter/ValueTable.java (99%) rename src/main/java/com/extantape/{voidwell => onevoid}/meter/VoidMeter.java (93%) rename src/main/java/com/extantape/{voidwell => onevoid}/oneblock/OneBlockBridge.java (87%) rename src/main/java/com/extantape/{voidwell => onevoid}/reward/Powers.java (95%) rename src/main/java/com/extantape/{voidwell => onevoid}/reward/Reward.java (92%) rename src/main/java/com/extantape/{voidwell => onevoid}/reward/Rewards.java (97%) rename src/main/java/com/extantape/{voidwell => onevoid}/social/Social.java (93%) rename src/main/java/com/extantape/{voidwell => onevoid}/social/VisitorGuard.java (92%) rename src/main/java/com/extantape/{voidwell => onevoid}/store/IslandStore.java (96%) rename src/main/java/com/extantape/{voidwell => onevoid}/store/PlayerData.java (90%) rename src/main/java/com/extantape/{voidwell => onevoid}/store/PlayerStore.java (94%) rename src/main/java/com/extantape/{voidwell => onevoid}/trip/DeathListener.java (95%) rename src/main/java/com/extantape/{voidwell => onevoid}/trip/Trips.java (94%) rename src/test/java/com/extantape/{voidwell => onevoid}/CommandGuardTest.java (83%) rename src/test/java/com/extantape/{voidwell => onevoid}/RewildKeepsTest.java (95%) rename src/test/java/com/extantape/{voidwell => onevoid}/meter/MeterTest.java (98%) rename src/test/java/com/extantape/{voidwell => onevoid}/social/ShareCircleTest.java (78%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c720a82..d6d13a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,5 +28,5 @@ jobs: - run: ./gradlew build - uses: actions/upload-artifact@v4 with: - name: Voidwell + name: OneVoid path: build/libs/*.jar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff1c44b..66e3a3f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,5 +38,5 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - gh release create "$GITHUB_REF_NAME" build/libs/Voidwell-*.jar \ - --title "Voidwell $GITHUB_REF_NAME" --notes-file "docs/releases/$GITHUB_REF_NAME.md" + gh release create "$GITHUB_REF_NAME" build/libs/OneVoid-*.jar \ + --title "OneVoid $GITHUB_REF_NAME" --notes-file "docs/releases/$GITHUB_REF_NAME.md" diff --git a/README.md b/README.md index 3b37ded..322ab74 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# Voidwell +# OneVoid A OneBlock add-on for Paper. Players walk into OneBlock through the Waystation, ring their island's bell to leave, and get something back for whatever they lose to the void. -**Status:** 0.1.2. Its full bot suite passed 86/86 for 0.1.1 on a throwaway Paper 26.2 server, and 0.1.2's respawn, void-death and way-bell sections pass with Waystation 0.7.0; tested with OneBlock 1.6.4, Multiverse-Core 5.8.2, Multiverse-Inventories 5.3.6, LuckPerms and HouseRules 0.1.1. The bots walk through Waystation's real OneBlock gate. The bots are 26.1 clients connecting through ViaVersion. On Paper 26.3 it loads, sets up and reports no problems, but no bot could play there: 26.3 disconnects clients that come through ViaVersion ("Invalid move player packet"), even ones standing still. Nothing has been seen in a real game client yet. See [Tested](#tested) for the details. +**Status:** 0.2.0, a new name. Its full bot suite passed 86/86 for 0.1.1 on a throwaway Paper 26.2 server, and 0.1.2's respawn, void-death and way-bell sections pass with Waystation 0.7.0; tested with OneBlock 1.6.4, Multiverse-Core 5.8.2, Multiverse-Inventories 5.3.6, LuckPerms and Mayor 0.1.1. The bots walk through Waystation's real OneBlock gate. The bots are 26.1 clients connecting through ViaVersion. On Paper 26.3 it loads, sets up and reports no problems, but no bot could play there: 26.3 disconnects clients that come through ViaVersion ("Invalid move player packet"), even ones standing still. Nothing has been seen in a real game client yet. See [Tested](#tested) for the details. ## What it does -**In and out.** The Waystation's OneBlock gate hands the player to Voidwell. The first time, OneBlock makes their island and they land on it with an empty OneBlock inventory. After that, they come back to the exact spot where they last rang their way bell. Players never type an `/ob` command. +**In and out.** The Waystation's OneBlock gate hands the player to OneVoid. The first time, OneBlock makes their island and they land on it with an empty OneBlock inventory. After that, they come back to the exact spot where they last rang their way bell. Players never type an `/ob` command. **The way bell.** Every island gets a bell on a crying obsidian post, two blocks from the one block. It never replaces one of the player's blocks: if that spot is taken, the bell goes to the nearest free one. A label above it says what it's for. Ringing it three times within 6 seconds takes the player to the Waystation, outside the OneBlock gate. One ring does nothing. Two rings, or rings too far apart, do nothing. Rings closer together than 8 ticks don't count, so holding the button down rings it only slowly: holding it for about a second does count, which is still a deliberate act. Hitting it, explosions, projectiles, redstone and other players' rings don't count. Nobody can break it, move it or blow it up, operators included. Sneaking and ringing opens the island menu. @@ -20,7 +20,7 @@ A OneBlock add-on for Paper. Players walk into OneBlock through the Waystation, - **Void-safe:** for 2 minutes, falling into the void lifts the player back to their island with everything they carry. - **Bountiful block:** their one block drops double for 5 minutes. - **The void gives back:** a stated 1 in 3 chance that half of the weapons and armour they've given the void come back, each with one enchantment a level past the usual most (Sharpness VI, Protection V and so on). If not, the meter starts again 25% full and the gear stays for another try. Offered only when there's gear to give back. -- **Island travel:** for 5 minutes, visit the islands of players who are online, share a HouseRules chat circle with them, and have turned visits on. +- **Island travel:** for 5 minutes, visit the islands of players who are online, share a Mayor chat circle with them, and have turned visits on. Powers run in real time, survive a restart, and say when they end. @@ -30,45 +30,45 @@ Powers run in real time, survive a restart, and say when they end. ## Needs -Paper 26.1 or later, Java 25. Waystation 0.4.0 or later and OneBlock 1.6.4 (plugin name `Oneblock`) are required. Multiverse-Inventories keeps the OneBlock inventory in the OneBlock world. HouseRules circles are needed for travel and teams. +Paper 26.1 or later, Java 25. Waystation 0.4.0 or later and OneBlock 1.6.4 (plugin name `Oneblock`) are required. Multiverse-Inventories keeps the OneBlock inventory in the OneBlock world. Mayor circles are needed for travel and teams. ## Install With the server stopped: -1. Copy `Voidwell-0.1.3.jar` to `plugins/`. -2. In OneBlock, turn off two settings that fight Voidwell: `/ob autojoin false` and `/ob rebirth_on_the_island false`. With autojoin on, OneBlock cancels the trip back to a player's bell. +1. Copy `OneVoid-0.1.3.jar` to `plugins/`. +2. In OneBlock, turn off two settings that fight OneVoid: `/ob autojoin false` and `/ob rebirth_on_the_island false`. With autojoin on, OneBlock cancels the trip back to a player's bell. 3. In Waystation, set the OneBlock world's gate to `hand-over: true` and turn island posts off (`island-posts.enabled: false`). The bell replaces them. 4. Put the OneBlock world in its own Multiverse-Inventories group, and the Waystation's world in a group with the lobby, so a death in OneBlock is a plain OneBlock-to-lobby swap. -5. If Lantern Graves is installed, add the OneBlock world to its `disabled-worlds`. Otherwise it puts island deaths in graves. Voidwell takes void-death items before Lantern Graves sees them, so the two never both take the same items. -6. Start the server and run `/voidwell status`. It lists anything still wrong. +5. If Lantern Graves is installed, add the OneBlock world to its `disabled-worlds`. Otherwise it puts island deaths in graves. OneVoid takes void-death items before Lantern Graves sees them, so the two never both take the same items. +6. Start the server and run `/onevoid status`. It lists anything still wrong. -Players keep OneBlock's `oneblock.join` permission. Voidwell refuses a typed `/ob` and hides it from tab-complete, but runs OneBlock's commands for players when they need them. +Players keep OneBlock's `oneblock.join` permission. OneVoid refuses a typed `/ob` and hides it from tab-complete, but runs OneBlock's commands for players when they need them. ## Commands | Command | Who | What | |---|---|---| -| `/voidwell` | everyone | Your meter, or your reward choice when it's full | -| `/voidwell reward` | everyone | The reward menu. The chat button uses it | -| `/voidwell team accept/decline` | everyone | Used by the invite's chat buttons | -| `/voidwell status` | admins | What's set up and what isn't | -| `/voidwell reload` | admins | Reload `config.yml` | -| `/voidwell meter ` | admins | Set a meter, for support | -| `/voidwell offer ` | admins | Offer particular rewards, for support and tests | -| `/voidwell bell ` | admins | Put an island's bell back, or show where it is | +| `/onevoid` | everyone | Your meter, or your reward choice when it's full | +| `/onevoid reward` | everyone | The reward menu. The chat button uses it | +| `/onevoid team accept/decline` | everyone | Used by the invite's chat buttons | +| `/onevoid status` | admins | What's set up and what isn't | +| `/onevoid reload` | admins | Reload `config.yml` | +| `/onevoid meter ` | admins | Set a meter, for support | +| `/onevoid offer ` | admins | Offer particular rewards, for support and tests | +| `/onevoid bell ` | admins | Put an island's bell back, or show where it is | ## Permissions | Node | Default | What | |---|---|---| -| `voidwell.use` | everyone | `/voidwell`. The bell needs no permission | -| `voidwell.admin` | op | Admin commands, and changing things on any island | -| `voidwell.oneblock-commands` | op | Typing OneBlock's `/ob` commands | +| `onevoid.use` | everyone | `/onevoid`. The bell needs no permission | +| `onevoid.admin` | op | Admin commands, and changing things on any island | +| `onevoid.oneblock-commands` | op | Typing OneBlock's `/ob` commands | ## Files -`plugins/Voidwell/config.yml` holds the settings, with notes. `players/.yml` holds each player's meter, rewards, powers and last bell spot. `islands.yml` records where each bell is. All of them are plain YAML. Each save writes a temporary file and renames it, so a crash leaves the old file or the new one, never half of each. +`plugins/OneVoid/config.yml` holds the settings, with notes. `players/.yml` holds each player's meter, rewards, powers and last bell spot. `islands.yml` records where each bell is. All of them are plain YAML. Each save writes a temporary file and renames it, so a crash leaves the old file or the new one, never half of each. ## Tested @@ -88,7 +88,7 @@ Not tested yet: ## Troubleshooting -- **A player respawns on their island after a OneBlock death.** Voidwell sets the respawn at the Waystation's OneBlock gate and checks half a second later that they're within a block of it. If another plugin has moved them, Voidwell puts them back and writes a console warning saying where they'd been moved. Multiverse-Inventories' `apply-last-location-for-all-teleports` is the known cause: it can restore the step into the gate. Use Waystation 0.7.0 or later too. To find any other cause, start the server with `-Dvoidwell.trace=true`: every teleport and respawn is then logged with the code that caused it. Leave it off otherwise. +- **A player respawns on their island after a OneBlock death.** OneVoid sets the respawn at the Waystation's OneBlock gate and checks half a second later that they're within a block of it. If another plugin has moved them, OneVoid puts them back and writes a console warning saying where they'd been moved. Multiverse-Inventories' `apply-last-location-for-all-teleports` is the known cause: it can restore the step into the gate. Use Waystation 0.7.0 or later too. To find any other cause, start the server with `-Donevoid.trace=true`: every teleport and respawn is then logged with the code that caused it. Leave it off otherwise. ## Build @@ -96,8 +96,8 @@ Not tested yet: ./gradlew build ``` -The jar is `build/libs/Voidwell-0.1.3.jar`. To run the bot tests: `cd test && npm install && node fetch.mjs && VOIDWELL_WAYSTATION_JAR= node suite.mjs 26.2`. Without `VOIDWELL_WAYSTATION_JAR` they use a small stand-in for Waystation (`test/standin`) instead. +The jar is `build/libs/OneVoid-0.1.3.jar`. To run the bot tests: `cd test && npm install && node fetch.mjs && ONEVOID_WAYSTATION_JAR= node suite.mjs 26.2`. Without `ONEVOID_WAYSTATION_JAR` they use a small stand-in for Waystation (`test/standin`) instead. ## License -MIT. See `LICENSE`. OneBlock is MrMarL's, also MIT. Voidwell calls it but includes none of its code. +MIT. See `LICENSE`. OneBlock is MrMarL's, also MIT. OneVoid calls it but includes none of its code. diff --git a/build.gradle.kts b/build.gradle.kts index 3bcc55d..b1c2be0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } group = "com.extantape" -version = "0.1.3" +version = "0.2.0" java { toolchain.languageVersion.set(JavaLanguageVersion.of(25)) @@ -55,6 +55,6 @@ tasks.test { } tasks.jar { - archiveBaseName.set("Voidwell") + archiveBaseName.set("OneVoid") from("LICENSE") } diff --git a/docs/decisions.md b/docs/decisions.md index 164b584..398b24e 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -44,3 +44,7 @@ The owner's decisions for Voidwell, with dates. Later work follows these without - Powers run in real time, so logging out or a restart neither stops nor stretches them. - After a trip out by the bell, Voidwell saves the OneBlock world as well as the player, as it does after a death (`crash-safety.save-world`). Otherwise a crash could bring back, on the ground, items the player had already picked up and carried out: found with the real Waystation 0.4.0, 2026-11-09. - "The void gives back" with no gear in the pool keeps the meter full and offers again, rather than spending it on nothing. + +## 2026-11-14 + +- **Name (owner, D194, D196):** the plugin is renamed OneVoid. The owner chose "OneVoid" and asked that no old names be kept. Released as 0.2.0. diff --git a/docs/first-public-push-audit.md b/docs/first-public-push-audit.md index 2d275ff..98146d8 100644 --- a/docs/first-public-push-audit.md +++ b/docs/first-public-push-audit.md @@ -14,8 +14,8 @@ Done on 2026-11-09, before the repo goes public, as `~/Code/CLAUDE.md` asks for | Server addresses | Every IPv4 address in history | Only `127.0.0.1`, the throwaway test servers | | Hosts and URLs | Every `.com` host in history | github.com, api.modrinth.com, example.com, anthropic.com (commit trailers), patreon.com (npm funding fields in `test/package-lock.json`) | | Email addresses | Every address in history | Only the GitHub noreply commit address and Claude's `noreply@anthropic.com` co-author trailer | -| Personal names and paths | `mgilardi`, the owner's names, `/Users/` | Only in git's author field, which `CLAUDE.md` allows. No home paths | -| Server, world and player names | The live servers' names and worlds, and the test players | None of the live names. Test worlds are `world`, `oneblock` and `waystation`, test players are made up (Ash, Birch, Cedar, Dell), and HouseRules circles in tests are `kids` and `adults` | +| Personal names and paths | the owner's GitHub username, the owner's names, and home-folder paths | Only in git's author field, which `CLAUDE.md` allows. No home paths | +| Server, world and player names | The live servers' names and worlds, and the test players | None of the live names. Test worlds are `world`, `oneblock` and `waystation`, test players are made up (Ash, Birch, Cedar, Dell), and Mayor circles in tests are `kids` and `adults` | | Build output | Every file ever committed | Source, tests, docs, scripts, workflows and the Gradle wrapper only. No jars, `build/`, `test/work/` or `node_modules/` | | Leak check in CI | `.github/workflows/build.yml` and `release.yml` | Both run `scripts/leak-check.sh` | | License | `LICENSE` | MIT, `Copyright (c) 2026 EXTANT APE` | diff --git a/docs/releases/v0.2.0.md b/docs/releases/v0.2.0.md new file mode 100644 index 0000000..ebb6e66 --- /dev/null +++ b/docs/releases/v0.2.0.md @@ -0,0 +1,13 @@ +A new name (D194): OneVoid, the OneBlock add-on. How it works is unchanged. As the owner asked (D196), it keeps no old names. + +## Installing over the previous version + +With the server stopped: +1. Rename its plugin folder to `plugins/OneVoid`. Islands, bells and teams are inside. +2. Move its LuckPerms permissions to the matching `onevoid.*` nodes. +3. Use `/onevoid` for its admin commands. +4. Install Mayor 0.5.0 at the same time: team invites check circles through Mayor. + +## Tested + +Unit tests pass. The rename was checked with the other plugins on a throwaway server. diff --git a/docs/test-audit.md b/docs/test-audit.md index 6d21768..fcc36d8 100644 --- a/docs/test-audit.md +++ b/docs/test-audit.md @@ -9,26 +9,26 @@ Kept by this repo's owning lead (Minecraft: Plugins Lead), per `~/Code/CLAUDE.md | Promise | Covered by | | --- | --- | | A respawned player put on the step into the gate ends at the landing, not on the island | bots "put on the step into the gate after the respawn, they end at the landing…", "and the gate did not take them" (the console plays Multiverse-Inventories) | -| Voidwell's check needs them within a block of the landing, not merely out of OneBlock | the same check: 0.1.1's rule let the gate step pass, because it's two blocks away | +| OneVoid's check needs them within a block of the landing, not merely out of OneBlock | the same check: 0.1.1's rule let the gate step pass, because it's two blocks away | The bot tests found one more thing: right after a teleport, a bot's position can bounce back to where it was once, which is why the check runs at half a second, before any step, and why Waystation 0.7.0's step-clear rule is the second line, not the only one. ## 2026-11-10: the respawn after a bell trip (0.1.1) -The server session's rehearsal on a copy of the real server (Paper 26.2, Waystation 0.6.0, OneBlock 1.6.4) found a void death after a bell trip and a return putting the player on their island while Voidwell said "You're back at the Waystation", in 3 of 3 runs. In this repo's suite the same steps respawn at the gate; a teleport trace showed only Voidwell's respawn there. So something on the real server moves the player afterwards. +The server session's rehearsal on a copy of the real server (Paper 26.2, Waystation 0.6.0, OneBlock 1.6.4) found a void death after a bell trip and a return putting the player on their island while OneVoid said "You're back at the Waystation", in 3 of 3 runs. In this repo's suite the same steps respawn at the gate; a teleport trace showed only OneVoid's respawn there. So something on the real server moves the player afterwards. | Promise | Covered by | | --- | --- | | After a bell trip and back, a void death still respawns outside the gate, and says so | bots "way bell: after a bell trip and back, a void death still respawns outside the gate", "and says so" (the rehearsal's repro) | -| If another plugin moves the player back into OneBlock after the respawn, Voidwell still ends with them at the gate and the console says so | bots "if another plugin moves them back after the respawn…", "and the console says what happened" (the console plays the other plugin) | +| If another plugin moves the player back into OneBlock after the respawn, OneVoid still ends with them at the gate and the console says so | bots "if another plugin moves them back after the respawn…", "and the console says what happened" (the console plays the other plugin) | -Gap: which plugin on the real server does it isn't known yet. `-Dvoidwell.trace=true` logs every teleport with its cause, for the server session's next rehearsal. +Gap: which plugin on the real server does it isn't known yet. `-Donevoid.trace=true` logs every teleport with its cause, for the server session's next rehearsal. Taken over from code-44 with its agreement on 2026-11-10. ## 2026-11-10: first full audit (at 0.1.0) -What Voidwell promises (README "What it does" and "Tested", `docs/decisions.md`), and what proves it. "Bots" is `test/suite.mjs` on a throwaway Paper 26.2 server with the real Waystation, OneBlock, Multiverse, LuckPerms and HouseRules; "unit" is `src/test`. +What OneVoid promises (README "What it does" and "Tested", `docs/decisions.md`), and what proves it. "Bots" is `test/suite.mjs` on a throwaway Paper 26.2 server with the real Waystation, OneBlock, Multiverse, LuckPerms and Mayor; "unit" is `src/test`. ### Covered @@ -65,4 +65,4 @@ After the refactor, the bot suite's 82 checks all passed on Paper 26.2 (2026-11- ### Skipped, with reasons - **Each visitor action separately (place, open, hurt, buckets, hanging items).** They share `guarded()` with breaking, which is tested. A bot can't reliably right-click blocks through ViaBackwards. -- **Admins with `voidwell.admin` not being held back on islands.** It's convenience for support, and protects nothing. +- **Admins with `onevoid.admin` not being held back on islands.** It's convenience for support, and protects nothing. diff --git a/settings.gradle.kts b/settings.gradle.kts index 393088c..311e9ae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "Voidwell" +rootProject.name = "OneVoid" // Test-only stand-in for Waystation 0.4.0's hand-over API, until that release exists. Never shipped. include("waystation-standin") diff --git a/src/main/java/com/extantape/voidwell/CommandGuard.java b/src/main/java/com/extantape/onevoid/CommandGuard.java similarity index 90% rename from src/main/java/com/extantape/voidwell/CommandGuard.java rename to src/main/java/com/extantape/onevoid/CommandGuard.java index 213a26d..47c9a85 100644 --- a/src/main/java/com/extantape/voidwell/CommandGuard.java +++ b/src/main/java/com/extantape/onevoid/CommandGuard.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import java.util.Locale; import java.util.Set; @@ -10,11 +10,11 @@ /** * Players don't type OneBlock commands: the gate, the way bell and its menu do everything. Typed /ob is - * refused with a pointer to what to do instead, and it's hidden from tab-complete. Commands Voidwell runs on a - * player's behalf aren't typed, so they still work. Admins with voidwell.oneblock-commands keep /ob. + * refused with a pointer to what to do instead, and it's hidden from tab-complete. Commands OneVoid runs on a + * player's behalf aren't typed, so they still work. Admins with onevoid.oneblock-commands keep /ob. */ public final class CommandGuard implements Listener { - static final String BYPASS = "voidwell.oneblock-commands"; + static final String BYPASS = "onevoid.oneblock-commands"; private static final Set LABELS = Set.of("ob", "oneblock", "oneblock:ob", "oneblock:oneblock", "ob j", "oneblock:ob j"); static boolean isOneBlock(String message) { diff --git a/src/main/java/com/extantape/voidwell/VoidwellCommand.java b/src/main/java/com/extantape/onevoid/OneVoidCommand.java similarity index 78% rename from src/main/java/com/extantape/voidwell/VoidwellCommand.java rename to src/main/java/com/extantape/onevoid/OneVoidCommand.java index cf97dfb..dc72477 100644 --- a/src/main/java/com/extantape/voidwell/VoidwellCommand.java +++ b/src/main/java/com/extantape/onevoid/OneVoidCommand.java @@ -1,6 +1,6 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; -import com.extantape.voidwell.store.PlayerData; +import com.extantape.onevoid.store.PlayerData; import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.tree.LiteralCommandNode; @@ -12,15 +12,15 @@ import org.bukkit.entity.Player; /** - * /voidwell. For players it shows the meter and opens the reward menu; the clickable chat buttons use it too. + * /onevoid. For players it shows the meter and opens the reward menu; the clickable chat buttons use it too. * Everything else is for admins. */ -final class VoidwellCommand { - private VoidwellCommand() {} +final class OneVoidCommand { + private OneVoidCommand() {} - static LiteralCommandNode build(VoidwellPlugin plugin) { - return Commands.literal("voidwell") - .requires(s -> s.getSender().hasPermission("voidwell.use")) + static LiteralCommandNode build(OneVoidPlugin plugin) { + return Commands.literal("onevoid") + .requires(s -> s.getSender().hasPermission("onevoid.use")) .executes(c -> { if (c.getSource().getExecutor() instanceof Player p) { PlayerData d = plugin.store.get(p.getUniqueId()); @@ -43,15 +43,15 @@ static LiteralCommandNode build(VoidwellPlugin plugin) { .executes(c -> accept(plugin, c.getSource(), StringArgumentType.getString(c, "owner"), false)) .then(Commands.literal("confirm").executes(c -> accept(plugin, c.getSource(), StringArgumentType.getString(c, "owner"), true)))))) - .then(Commands.literal("reload").requires(s -> s.getSender().hasPermission("voidwell.admin")) + .then(Commands.literal("reload").requires(s -> s.getSender().hasPermission("onevoid.admin")) .executes(c -> { plugin.reload(); status(plugin, c.getSource().getSender()); return 1; })) - .then(Commands.literal("status").requires(s -> s.getSender().hasPermission("voidwell.admin")) + .then(Commands.literal("status").requires(s -> s.getSender().hasPermission("onevoid.admin")) .executes(c -> { status(plugin, c.getSource().getSender()); return 1; })) - .then(Commands.literal("meter").requires(s -> s.getSender().hasPermission("voidwell.admin")) + .then(Commands.literal("meter").requires(s -> s.getSender().hasPermission("onevoid.admin")) .then(Commands.argument("player", ArgumentTypes.player()) .then(Commands.argument("points", DoubleArgumentType.doubleArg(0)) .executes(c -> { @@ -62,12 +62,12 @@ static LiteralCommandNode build(VoidwellPlugin plugin) { d.meter.points = Math.min(DoubleArgumentType.getDouble(c, "points"), plugin.settings.full * 2); if (!wasFull && d.meter.isFull(plugin.settings.full) && d.offer.isEmpty()) plugin.rewards.rollOffer(d); plugin.store.save(d); - c.getSource().getSender().sendMessage("Voidwell: " + p.getName() + "'s meter is now " + plugin.meter.status(d) + c.getSource().getSender().sendMessage("OneVoid: " + p.getName() + "'s meter is now " + plugin.meter.status(d) + (d.offer.isEmpty() ? "" : ", offering " + String.join(", ", d.offer))); if (!d.offer.isEmpty()) plugin.meter.announceFull(p); return 1; })))) - .then(Commands.literal("offer").requires(s -> s.getSender().hasPermission("voidwell.admin")) + .then(Commands.literal("offer").requires(s -> s.getSender().hasPermission("onevoid.admin")) .then(Commands.argument("player", ArgumentTypes.player()) .then(Commands.argument("rewards", StringArgumentType.greedyString()).executes(c -> { Player p = c.getArgument("player", PlayerSelectorArgumentResolver.class).resolve(c.getSource()).getFirst(); @@ -75,39 +75,39 @@ static LiteralCommandNode build(VoidwellPlugin plugin) { d.offer.clear(); var allowed = plugin.rewards.eligible(d); for (String id : StringArgumentType.getString(c, "rewards").split(" ")) { - var r = com.extantape.voidwell.reward.Reward.byId(id); + var r = com.extantape.onevoid.reward.Reward.byId(id); if (r != null && allowed.contains(r) && d.offer.size() < 3) d.offer.add(id); } if (d.offer.isEmpty()) { - c.getSource().getSender().sendMessage("Voidwell: none of those can be offered to " + p.getName() + " now. Rewards: featherfall, void-safe, bountiful-block, void-gives-back (needs gear given to the void), island-travel (needs HouseRules circles). Turned-off rewards are never offered."); + c.getSource().getSender().sendMessage("OneVoid: none of those can be offered to " + p.getName() + " now. Rewards: featherfall, void-safe, bountiful-block, void-gives-back (needs gear given to the void), island-travel (needs Mayor circles). Turned-off rewards are never offered."); return 0; } d.meter.points = Math.max(d.meter.points, plugin.settings.full); plugin.store.save(d); plugin.meter.announceFull(p); - c.getSource().getSender().sendMessage("Voidwell: offered " + p.getName() + " " + String.join(", ", d.offer) + "."); + c.getSource().getSender().sendMessage("OneVoid: offered " + p.getName() + " " + String.join(", ", d.offer) + "."); return 1; })))) - .then(Commands.literal("bell").requires(s -> s.getSender().hasPermission("voidwell.admin")) + .then(Commands.literal("bell").requires(s -> s.getSender().hasPermission("onevoid.admin")) .then(Commands.argument("player", ArgumentTypes.player()).executes(c -> { Player p = c.getArgument("player", PlayerSelectorArgumentResolver.class).resolve(c.getSource()).getFirst(); int island = plugin.bridge.islandOf(p.getUniqueId()); var pos = island < 0 ? null : plugin.bells.ensure(island); c.getSource().getSender().sendMessage(pos == null - ? "Voidwell: " + p.getName() + " has no island, or its bell can't be placed (is the island loaded?)." - : "Voidwell: island " + island + "'s way bell is at " + pos.x() + " " + pos.y() + " " + pos.z() + "."); + ? "OneVoid: " + p.getName() + " has no island, or its bell can't be placed (is the island loaded?)." + : "OneVoid: island " + island + "'s way bell is at " + pos.x() + " " + pos.y() + " " + pos.z() + "."); return 1; }))) .build(); } - private static int accept(VoidwellPlugin plugin, CommandSourceStack src, String owner, boolean confirm) { + private static int accept(OneVoidPlugin plugin, CommandSourceStack src, String owner, boolean confirm) { if (src.getExecutor() instanceof Player p) plugin.social.accept(p, owner, confirm); return 1; } - static void status(VoidwellPlugin plugin, CommandSender to) { - to.sendMessage("Voidwell " + plugin.getPluginMeta().getVersion() + ":"); + static void status(OneVoidPlugin plugin, CommandSender to) { + to.sendMessage("OneVoid " + plugin.getPluginMeta().getVersion() + ":"); for (String line : plugin.health()) to.sendMessage(" - " + line); } } diff --git a/src/main/java/com/extantape/voidwell/VoidwellPlugin.java b/src/main/java/com/extantape/onevoid/OneVoidPlugin.java similarity index 81% rename from src/main/java/com/extantape/voidwell/VoidwellPlugin.java rename to src/main/java/com/extantape/onevoid/OneVoidPlugin.java index 8f74540..9145976 100644 --- a/src/main/java/com/extantape/voidwell/VoidwellPlugin.java +++ b/src/main/java/com/extantape/onevoid/OneVoidPlugin.java @@ -1,21 +1,21 @@ -package com.extantape.voidwell; - -import com.extantape.voidwell.bell.BellListener; -import com.extantape.voidwell.bell.WayBells; -import com.extantape.voidwell.menu.IslandMenus; -import com.extantape.voidwell.menu.MenuListener; -import com.extantape.voidwell.meter.ThrowListener; -import com.extantape.voidwell.meter.VoidMeter; -import com.extantape.voidwell.oneblock.OneBlockBridge; -import com.extantape.voidwell.reward.Powers; -import com.extantape.voidwell.reward.Rewards; -import com.extantape.voidwell.social.Social; -import com.extantape.voidwell.social.VisitorGuard; -import com.extantape.voidwell.store.IslandStore; -import com.extantape.voidwell.store.PlayerData; -import com.extantape.voidwell.store.PlayerStore; -import com.extantape.voidwell.trip.DeathListener; -import com.extantape.voidwell.trip.Trips; +package com.extantape.onevoid; + +import com.extantape.onevoid.bell.BellListener; +import com.extantape.onevoid.bell.WayBells; +import com.extantape.onevoid.menu.IslandMenus; +import com.extantape.onevoid.menu.MenuListener; +import com.extantape.onevoid.meter.ThrowListener; +import com.extantape.onevoid.meter.VoidMeter; +import com.extantape.onevoid.oneblock.OneBlockBridge; +import com.extantape.onevoid.reward.Powers; +import com.extantape.onevoid.reward.Rewards; +import com.extantape.onevoid.social.Social; +import com.extantape.onevoid.social.VisitorGuard; +import com.extantape.onevoid.store.IslandStore; +import com.extantape.onevoid.store.PlayerData; +import com.extantape.onevoid.store.PlayerStore; +import com.extantape.onevoid.trip.DeathListener; +import com.extantape.onevoid.trip.Trips; import com.extantape.waystation.WaystationHandOverEvent; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import java.util.ArrayList; @@ -32,7 +32,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; -public final class VoidwellPlugin extends JavaPlugin implements Listener { +public final class OneVoidPlugin extends JavaPlugin implements Listener { public Settings settings; public final OneBlockBridge bridge = new OneBlockBridge(); public PlayerStore store; @@ -82,7 +82,7 @@ public void onEnable() { } getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, e -> - e.registrar().register(VoidwellCommand.build(this), "Your void meter and rewards", List.of())); + e.registrar().register(OneVoidCommand.build(this), "Your void meter and rewards", List.of())); Bukkit.getScheduler().runTaskTimer(this, () -> { powers.tick(); @@ -110,7 +110,7 @@ public void reload() { bells.removeAllLabels(); } - /** Problems an admin should fix, in words. Shown at startup and in /voidwell status. */ + /** Problems an admin should fix, in words. Shown at startup and in /onevoid status. */ public List warnings() { List out = new ArrayList<>(bridge.conflicts()); World w = bridge.world(); @@ -123,7 +123,7 @@ public List warnings() { out.add("Lantern Graves is making graves in the OneBlock world. Add " + w.getName() + " to its disabled-worlds, so island deaths drop items as they should."); if (!social.circlesExist()) - out.add("No HouseRules circles exist, so island travel and team invites are off."); + out.add("No Mayor circles exist, so island travel and team invites are off."); return out; } @@ -159,7 +159,7 @@ private void onJoin(Player p) { rewards.applyFeatherfall(p, d); Bukkit.getScheduler().runTaskLater(this, () -> { if (!p.isOnline()) return; - if (d.travelReturn != null && d.powerLeft(com.extantape.voidwell.reward.Reward.ISLAND_TRAVEL.id, System.currentTimeMillis()) <= 0) + if (d.travelReturn != null && d.powerLeft(com.extantape.onevoid.reward.Reward.ISLAND_TRAVEL.id, System.currentTimeMillis()) <= 0) social.endTravel(p, "Island travel ended while you were away, so you're back home."); rewards.deliver(p); }, 40L); @@ -171,17 +171,17 @@ public void onWorldChange(PlayerChangedWorldEvent e) { Bukkit.getScheduler().runTaskLater(this, () -> rewards.deliver(e.getPlayer()), 20L); } - // Troubleshooting: with -Dvoidwell.trace=true, log every teleport and respawn with the plugin code that caused it. + // Troubleshooting: with -Donevoid.trace=true, log every teleport and respawn with the plugin code that caused it. @EventHandler(priority = EventPriority.MONITOR) public void traceTp(org.bukkit.event.player.PlayerTeleportEvent e) { - if (!Boolean.getBoolean("voidwell.trace")) return; + if (!Boolean.getBoolean("onevoid.trace")) return; StringBuilder sb = new StringBuilder(); for (StackTraceElement el : new Throwable().getStackTrace()) { String c = el.getClassName(); if (!c.startsWith("java.") && !c.startsWith("jdk.")) sb.append(" <").append(c.replaceAll("^.*\\.", "")).append('.').append(el.getMethodName()); if (sb.length() > 900) break; } getLogger().info("TRACE tp " + e.getPlayer().getName() + " " + e.getCause() + " -> " + e.getTo().getWorld().getName() + " " + e.getTo().getBlockX() + "," + e.getTo().getBlockY() + "," + e.getTo().getBlockZ() + " cancelled=" + e.isCancelled() + sb); } @EventHandler(priority = EventPriority.MONITOR) public void traceRespawn(org.bukkit.event.player.PlayerRespawnEvent e) { - if (Boolean.getBoolean("voidwell.trace")) getLogger().info("TRACE respawn " + e.getPlayer().getName() + " -> " + e.getRespawnLocation().getWorld().getName() + " " + e.getRespawnLocation().getBlockX() + "," + e.getRespawnLocation().getBlockY() + "," + e.getRespawnLocation().getBlockZ()); + if (Boolean.getBoolean("onevoid.trace")) getLogger().info("TRACE respawn " + e.getPlayer().getName() + " -> " + e.getRespawnLocation().getWorld().getName() + " " + e.getRespawnLocation().getBlockX() + "," + e.getRespawnLocation().getBlockY() + "," + e.getRespawnLocation().getBlockZ()); } @EventHandler diff --git a/src/main/java/com/extantape/voidwell/RewildKeeps.java b/src/main/java/com/extantape/onevoid/RewildKeeps.java similarity index 99% rename from src/main/java/com/extantape/voidwell/RewildKeeps.java rename to src/main/java/com/extantape/onevoid/RewildKeeps.java index 8b74b1a..c1cc220 100644 --- a/src/main/java/com/extantape/voidwell/RewildKeeps.java +++ b/src/main/java/com/extantape/onevoid/RewildKeeps.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import org.bukkit.Bukkit; import org.bukkit.World; diff --git a/src/main/java/com/extantape/voidwell/Settings.java b/src/main/java/com/extantape/onevoid/Settings.java similarity index 99% rename from src/main/java/com/extantape/voidwell/Settings.java rename to src/main/java/com/extantape/onevoid/Settings.java index f4ebf55..2479088 100644 --- a/src/main/java/com/extantape/voidwell/Settings.java +++ b/src/main/java/com/extantape/onevoid/Settings.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/extantape/voidwell/Text.java b/src/main/java/com/extantape/onevoid/Text.java similarity index 88% rename from src/main/java/com/extantape/voidwell/Text.java rename to src/main/java/com/extantape/onevoid/Text.java index cfd7f85..b2b2ba5 100644 --- a/src/main/java/com/extantape/voidwell/Text.java +++ b/src/main/java/com/extantape/onevoid/Text.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -9,12 +9,12 @@ import org.bukkit.entity.Player; /** - * Chat and labels. Every message starts with "Voidwell:" in words, so it's clear where it came from, and never + * Chat and labels. Every message starts with "OneVoid:" in words, so it's clear where it came from, and never * relies on colour alone: what happened is always in the text. */ public final class Text { private static final MiniMessage MM = MiniMessage.miniMessage(); - private static final Component PREFIX = Component.text("Voidwell: ", NamedTextColor.DARK_AQUA); + private static final Component PREFIX = Component.text("OneVoid: ", NamedTextColor.DARK_AQUA); private Text() {} diff --git a/src/main/java/com/extantape/voidwell/bell/BellListener.java b/src/main/java/com/extantape/onevoid/bell/BellListener.java similarity index 96% rename from src/main/java/com/extantape/voidwell/bell/BellListener.java rename to src/main/java/com/extantape/onevoid/bell/BellListener.java index 94f2a12..6e31019 100644 --- a/src/main/java/com/extantape/voidwell/bell/BellListener.java +++ b/src/main/java/com/extantape/onevoid/bell/BellListener.java @@ -1,7 +1,7 @@ -package com.extantape.voidwell.bell; +package com.extantape.onevoid.bell; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,13 +33,13 @@ * players, not hitting it. Nothing can break it, move it or blow it up. */ public final class BellListener implements Listener { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; private final Map rings = new HashMap<>(); private final Map lastNotice = new HashMap<>(); private record Rings(int island, int count, long firstTick, long lastTick) {} - public BellListener(VoidwellPlugin plugin) { + public BellListener(OneVoidPlugin plugin) { this.plugin = plugin; } @@ -106,7 +106,7 @@ public void forget(UUID id) { lastNotice.remove(id); } - // Protection. Nobody breaks or moves a way bell, operators included. /voidwell bell puts it right. + // Protection. Nobody breaks or moves a way bell, operators included. /onevoid bell puts it right. @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onBreak(BlockBreakEvent e) { diff --git a/src/main/java/com/extantape/voidwell/bell/WayBells.java b/src/main/java/com/extantape/onevoid/bell/WayBells.java similarity index 95% rename from src/main/java/com/extantape/voidwell/bell/WayBells.java rename to src/main/java/com/extantape/onevoid/bell/WayBells.java index 3364a64..22f3628 100644 --- a/src/main/java/com/extantape/voidwell/bell/WayBells.java +++ b/src/main/java/com/extantape/onevoid/bell/WayBells.java @@ -1,8 +1,8 @@ -package com.extantape.voidwell.bell; +package com.extantape.onevoid.bell; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.store.IslandStore.BellPos; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.store.IslandStore.BellPos; import java.util.HashMap; import java.util.Map; import org.bukkit.Color; @@ -23,10 +23,10 @@ * redraws any that are missing near a player. */ public final class WayBells { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; private final Map labels = new HashMap<>(); - public WayBells(VoidwellPlugin plugin) { + public WayBells(OneVoidPlugin plugin) { this.plugin = plugin; } diff --git a/src/main/java/com/extantape/voidwell/menu/IslandMenus.java b/src/main/java/com/extantape/onevoid/menu/IslandMenus.java similarity index 97% rename from src/main/java/com/extantape/voidwell/menu/IslandMenus.java rename to src/main/java/com/extantape/onevoid/menu/IslandMenus.java index 29de54e..4c8e5b5 100644 --- a/src/main/java/com/extantape/voidwell/menu/IslandMenus.java +++ b/src/main/java/com/extantape/onevoid/menu/IslandMenus.java @@ -1,9 +1,9 @@ -package com.extantape.voidwell.menu; +package com.extantape.onevoid.menu; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.reward.Reward; -import com.extantape.voidwell.store.PlayerData; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.reward.Reward; +import com.extantape.onevoid.store.PlayerData; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -18,9 +18,9 @@ /** What sneaking and ringing a way bell opens. Every choice says what it does in words. */ public final class IslandMenus { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; - public IslandMenus(VoidwellPlugin plugin) { + public IslandMenus(OneVoidPlugin plugin) { this.plugin = plugin; } diff --git a/src/main/java/com/extantape/voidwell/menu/Menu.java b/src/main/java/com/extantape/onevoid/menu/Menu.java similarity index 97% rename from src/main/java/com/extantape/voidwell/menu/Menu.java rename to src/main/java/com/extantape/onevoid/menu/Menu.java index 78aaae7..b4bd877 100644 --- a/src/main/java/com/extantape/voidwell/menu/Menu.java +++ b/src/main/java/com/extantape/onevoid/menu/Menu.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.menu; +package com.extantape.onevoid.menu; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/com/extantape/voidwell/menu/MenuListener.java b/src/main/java/com/extantape/onevoid/menu/MenuListener.java similarity index 96% rename from src/main/java/com/extantape/voidwell/menu/MenuListener.java rename to src/main/java/com/extantape/onevoid/menu/MenuListener.java index 7bceae9..3776659 100644 --- a/src/main/java/com/extantape/voidwell/menu/MenuListener.java +++ b/src/main/java/com/extantape/onevoid/menu/MenuListener.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.menu; +package com.extantape.onevoid.menu; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/src/main/java/com/extantape/voidwell/meter/Meter.java b/src/main/java/com/extantape/onevoid/meter/Meter.java similarity index 98% rename from src/main/java/com/extantape/voidwell/meter/Meter.java rename to src/main/java/com/extantape/onevoid/meter/Meter.java index 020d8d1..9007039 100644 --- a/src/main/java/com/extantape/voidwell/meter/Meter.java +++ b/src/main/java/com/extantape/onevoid/meter/Meter.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.meter; +package com.extantape.onevoid.meter; import java.time.LocalDate; import java.util.HashMap; diff --git a/src/main/java/com/extantape/voidwell/meter/ThrowListener.java b/src/main/java/com/extantape/onevoid/meter/ThrowListener.java similarity index 92% rename from src/main/java/com/extantape/voidwell/meter/ThrowListener.java rename to src/main/java/com/extantape/onevoid/meter/ThrowListener.java index 00c07f8..0df9ab2 100644 --- a/src/main/java/com/extantape/voidwell/meter/ThrowListener.java +++ b/src/main/java/com/extantape/onevoid/meter/ThrowListener.java @@ -1,6 +1,6 @@ -package com.extantape.voidwell.meter; +package com.extantape.onevoid.meter; -import com.extantape.voidwell.VoidwellPlugin; +import com.extantape.onevoid.OneVoidPlugin; import java.util.List; import java.util.Objects; import java.util.UUID; @@ -19,9 +19,9 @@ * dropped by dying, such as drops from the one block, don't count. */ public final class ThrowListener implements Listener { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; - public ThrowListener(VoidwellPlugin plugin) { + public ThrowListener(OneVoidPlugin plugin) { this.plugin = plugin; } diff --git a/src/main/java/com/extantape/voidwell/meter/ValueTable.java b/src/main/java/com/extantape/onevoid/meter/ValueTable.java similarity index 99% rename from src/main/java/com/extantape/voidwell/meter/ValueTable.java rename to src/main/java/com/extantape/onevoid/meter/ValueTable.java index c15c379..5e5b14b 100644 --- a/src/main/java/com/extantape/voidwell/meter/ValueTable.java +++ b/src/main/java/com/extantape/onevoid/meter/ValueTable.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.meter; +package com.extantape.onevoid.meter; import java.util.Locale; import java.util.Map; diff --git a/src/main/java/com/extantape/voidwell/meter/VoidMeter.java b/src/main/java/com/extantape/onevoid/meter/VoidMeter.java similarity index 93% rename from src/main/java/com/extantape/voidwell/meter/VoidMeter.java rename to src/main/java/com/extantape/onevoid/meter/VoidMeter.java index 9a8594d..d461029 100644 --- a/src/main/java/com/extantape/voidwell/meter/VoidMeter.java +++ b/src/main/java/com/extantape/onevoid/meter/VoidMeter.java @@ -1,8 +1,8 @@ -package com.extantape.voidwell.meter; +package com.extantape.onevoid.meter; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.store.PlayerData; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.store.PlayerData; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.item.BundleContents; import io.papermc.paper.datacomponent.item.ItemContainerContents; @@ -25,9 +25,9 @@ /** Turns items given to the void into meter points, and tells the player what happened. */ public final class VoidMeter { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; - public VoidMeter(VoidwellPlugin plugin) { + public VoidMeter(OneVoidPlugin plugin) { this.plugin = plugin; } @@ -127,10 +127,10 @@ private String pct(PlayerData d) { public void announceFull(Player p) { p.playSound(p.getLocation(), Sound.BLOCK_BEACON_ACTIVATE, 0.8f, 1.4f); - p.sendMessage(Text.mm("Voidwell: Your void meter is full! " + p.sendMessage(Text.mm("OneVoid: Your void meter is full! " + "Choose one of three rewards. ") .append(Text.mm("[Choose a reward]") - .clickEvent(ClickEvent.runCommand("/voidwell reward")))); + .clickEvent(ClickEvent.runCommand("/onevoid reward")))); } /** On arriving: if a reward is waiting, say so once. */ diff --git a/src/main/java/com/extantape/voidwell/oneblock/OneBlockBridge.java b/src/main/java/com/extantape/onevoid/oneblock/OneBlockBridge.java similarity index 87% rename from src/main/java/com/extantape/voidwell/oneblock/OneBlockBridge.java rename to src/main/java/com/extantape/onevoid/oneblock/OneBlockBridge.java index 652d454..1d6a284 100644 --- a/src/main/java/com/extantape/voidwell/oneblock/OneBlockBridge.java +++ b/src/main/java/com/extantape/onevoid/oneblock/OneBlockBridge.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.oneblock; +package com.extantape.onevoid.oneblock; import java.util.ArrayList; import java.util.List; @@ -11,7 +11,7 @@ import org.bukkit.entity.Player; /** - * Every call Voidwell makes into OneBlock 1.6.4, in one place. Reads use OneBlock's public static getters. + * Every call OneVoid makes into OneBlock 1.6.4, in one place. Reads use OneBlock's public static getters. * Islands are made, joined and left with OneBlock's own commands, run as the player, so OneBlock keeps * its own files. The single exception is {@link #leaveTeam}, explained there. */ @@ -103,7 +103,7 @@ public void join(Player player) { player.performCommand("oneblock join"); } - /** OneBlock's invite, run as the owner. It opens OneBlock's own accept menu, which Voidwell closes again. */ + /** OneBlock's invite, run as the owner. It opens OneBlock's own accept menu, which OneVoid closes again. */ public void invite(Player owner, Player invitee) { owner.performCommand("oneblock invite " + invitee.getName()); } @@ -120,24 +120,24 @@ public void kick(Player owner, String memberName) { /** * Takes a teammate off their island. {@code /ob idreset} would do the same, then send them to OneBlock's - * leave spot, so Voidwell calls the same public method that command uses and moves them itself. + * leave spot, so OneVoid calls the same public method that command uses and moves them itself. */ public void leaveTeam(Player member) { CommandHandler.idresetCommand(member); } - /** Whether OneBlock clears the inventory when a player leaves an island. Voidwell restores it either way. */ + /** Whether OneBlock clears the inventory when a player leaves an island. OneVoid restores it either way. */ public boolean clearsInventoryOnReset() { return !OneBlock.saveplayerinventory; } - /** OneBlock settings that fight Voidwell, as readable warnings. Empty when all is well. */ + /** OneBlock settings that fight OneVoid, as readable warnings. Empty when all is well. */ public List conflicts() { List out = new ArrayList<>(); if (OneBlock.autojoin) - out.add("OneBlock's autojoin is on. It cancels Voidwell's trip back to a player's bell. Run /ob autojoin false."); + out.add("OneBlock's autojoin is on. It cancels OneVoid's trip back to a player's bell. Run /ob autojoin false."); if (OneBlock.rebirth) - out.add("OneBlock's rebirth_on_the_island is on. Voidwell overrides it, but set it off: /ob rebirth_on_the_island false."); + out.add("OneBlock's rebirth_on_the_island is on. OneVoid overrides it, but set it off: /ob rebirth_on_the_island false."); if (OneBlock.getOffset() == 0) out.add("OneBlock has no island grid yet. An admin needs to run /ob set first."); return out; diff --git a/src/main/java/com/extantape/voidwell/reward/Powers.java b/src/main/java/com/extantape/onevoid/reward/Powers.java similarity index 95% rename from src/main/java/com/extantape/voidwell/reward/Powers.java rename to src/main/java/com/extantape/onevoid/reward/Powers.java index f8972fb..feb26cd 100644 --- a/src/main/java/com/extantape/voidwell/reward/Powers.java +++ b/src/main/java/com/extantape/onevoid/reward/Powers.java @@ -1,8 +1,8 @@ -package com.extantape.voidwell.reward; +package com.extantape.onevoid.reward; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.store.PlayerData; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.store.PlayerData; import java.util.ArrayList; import java.util.List; import org.bukkit.Bukkit; @@ -25,9 +25,9 @@ * them, and each ends with a message saying so. */ public final class Powers implements Listener { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; - public Powers(VoidwellPlugin plugin) { + public Powers(OneVoidPlugin plugin) { this.plugin = plugin; } diff --git a/src/main/java/com/extantape/voidwell/reward/Reward.java b/src/main/java/com/extantape/onevoid/reward/Reward.java similarity index 92% rename from src/main/java/com/extantape/voidwell/reward/Reward.java rename to src/main/java/com/extantape/onevoid/reward/Reward.java index 89b0ed7..2a688ff 100644 --- a/src/main/java/com/extantape/voidwell/reward/Reward.java +++ b/src/main/java/com/extantape/onevoid/reward/Reward.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.reward; +package com.extantape.onevoid.reward; /** The rewards a full meter can offer. The id is what's saved. */ public enum Reward { diff --git a/src/main/java/com/extantape/voidwell/reward/Rewards.java b/src/main/java/com/extantape/onevoid/reward/Rewards.java similarity index 97% rename from src/main/java/com/extantape/voidwell/reward/Rewards.java rename to src/main/java/com/extantape/onevoid/reward/Rewards.java index 0807c47..93f68f3 100644 --- a/src/main/java/com/extantape/voidwell/reward/Rewards.java +++ b/src/main/java/com/extantape/onevoid/reward/Rewards.java @@ -1,9 +1,9 @@ -package com.extantape.voidwell.reward; +package com.extantape.onevoid.reward; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.menu.Menu; -import com.extantape.voidwell.store.PlayerData; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.menu.Menu; +import com.extantape.onevoid.store.PlayerData; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; @@ -26,12 +26,12 @@ * them. The player picks one. The only chance involved, "the void gives back", says its odds up front. */ public final class Rewards { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; private final Random random = new Random(); private final NamespacedKey deliveryKey; private final java.util.Map armed = new java.util.HashMap<>(); - public Rewards(VoidwellPlugin plugin) { + public Rewards(OneVoidPlugin plugin) { this.plugin = plugin; this.deliveryKey = new NamespacedKey(plugin, "delivery"); } diff --git a/src/main/java/com/extantape/voidwell/social/Social.java b/src/main/java/com/extantape/onevoid/social/Social.java similarity index 93% rename from src/main/java/com/extantape/voidwell/social/Social.java rename to src/main/java/com/extantape/onevoid/social/Social.java index e367a54..b3a9433 100644 --- a/src/main/java/com/extantape/voidwell/social/Social.java +++ b/src/main/java/com/extantape/onevoid/social/Social.java @@ -1,11 +1,11 @@ -package com.extantape.voidwell.social; +package com.extantape.onevoid.social; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.menu.Menu; -import com.extantape.voidwell.reward.Reward; -import com.extantape.voidwell.store.PlayerData; -import com.extantape.voidwell.trip.Trips; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.menu.Menu; +import com.extantape.onevoid.reward.Reward; +import com.extantape.onevoid.store.PlayerData; +import com.extantape.onevoid.trip.Trips; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -22,18 +22,18 @@ import org.bukkit.permissions.Permission; /** - * Island travel and teams. Both only ever connect two players who are online and share a HouseRules circle, + * Island travel and teams. Both only ever connect two players who are online and share a Mayor circle, * so kids reach only kids and adults only adults. If there are no circles, or a check can't be made, the * answer is no. */ public final class Social { - private static final String CIRCLE = "houserules.circle."; - private final VoidwellPlugin plugin; + private static final String CIRCLE = "mayor.circle."; + private final OneVoidPlugin plugin; private final Map invites = new HashMap<>(); private record Invite(UUID owner, int island, long expires) {} - public Social(VoidwellPlugin plugin) { + public Social(OneVoidPlugin plugin) { this.plugin = plugin; } @@ -178,7 +178,7 @@ public void tick() { var w = plugin.bridge.world(); if (w == null) return; for (Player p : w.getPlayers()) { - if (!isVisiting(p) || p.hasPermission("voidwell.admin")) continue; + if (!isVisiting(p) || p.hasPermission("onevoid.admin")) continue; int island = plugin.bridge.islandAt(p.getLocation()); Player owner = ownerOnline(island); boolean travelling = plugin.store.get(p.getUniqueId()).powerLeft(Reward.ISLAND_TRAVEL.id, System.currentTimeMillis()) > 0; @@ -216,13 +216,13 @@ public void invite(Player owner, Player invitee) { invites.put(invitee.getUniqueId(), new Invite(owner.getUniqueId(), island, System.currentTimeMillis() + plugin.settings.inviteSeconds * 1000L)); Text.tell(owner, "Invite sent to " + invitee.getName() + ". It lasts " + plugin.settings.inviteSeconds + " seconds."); - invitee.sendMessage(Text.mm("Voidwell: " + owner.getName() + " invites you " + invitee.sendMessage(Text.mm("OneVoid: " + owner.getName() + " invites you " + "to share their OneBlock island. ") .append(Text.mm("[Join]") - .clickEvent(ClickEvent.runCommand("/voidwell team accept " + owner.getName()))) + .clickEvent(ClickEvent.runCommand("/onevoid team accept " + owner.getName()))) .append(Text.mm(" ")) .append(Text.mm("[No thanks]") - .clickEvent(ClickEvent.runCommand("/voidwell team decline")))); + .clickEvent(ClickEvent.runCommand("/onevoid team decline")))); } public void decline(Player p) { @@ -250,14 +250,14 @@ public void accept(Player p, String ownerName, boolean confirmed) { int own = plugin.bridge.islandOf(p.getUniqueId()); if (own >= 0 && !confirmed) { boolean teammates = plugin.bridge.members(own).size() > 1; - p.sendMessage(Text.mm("Voidwell: Joining means leaving your own island for good. " + p.sendMessage(Text.mm("OneVoid: Joining means leaving your own island for good. " + (teammates ? "Your teammates keep it." : "Its blocks stay, but you won't be able to go back to it.") + " Your OneBlock inventory comes with you. ") .append(Text.mm("[Yes, join]") - .clickEvent(ClickEvent.runCommand("/voidwell team accept " + owner.getName() + " confirm"))) + .clickEvent(ClickEvent.runCommand("/onevoid team accept " + owner.getName() + " confirm"))) .append(Text.mm(" ")) .append(Text.mm("[Cancel]") - .clickEvent(ClickEvent.runCommand("/voidwell team decline")))); + .clickEvent(ClickEvent.runCommand("/onevoid team decline")))); return; } invites.remove(p.getUniqueId()); diff --git a/src/main/java/com/extantape/voidwell/social/VisitorGuard.java b/src/main/java/com/extantape/onevoid/social/VisitorGuard.java similarity index 92% rename from src/main/java/com/extantape/voidwell/social/VisitorGuard.java rename to src/main/java/com/extantape/onevoid/social/VisitorGuard.java index 22d59db..92935d1 100644 --- a/src/main/java/com/extantape/voidwell/social/VisitorGuard.java +++ b/src/main/java/com/extantape/onevoid/social/VisitorGuard.java @@ -1,7 +1,7 @@ -package com.extantape.voidwell.social; +package com.extantape.onevoid.social; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -27,18 +27,18 @@ /** * On someone else's island, a player can look but not touch: no breaking, placing, opening, hurting or * picking up what isn't theirs. Players can still pick up items they threw, and their own death drops. - * Admins with voidwell.admin aren't held back. + * Admins with onevoid.admin aren't held back. */ public final class VisitorGuard implements Listener { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; private final Map lastNotice = new HashMap<>(); - public VisitorGuard(VoidwellPlugin plugin) { + public VisitorGuard(OneVoidPlugin plugin) { this.plugin = plugin; } private boolean guarded(Player p) { - return !p.hasPermission("voidwell.admin") && plugin.social.isVisiting(p); + return !p.hasPermission("onevoid.admin") && plugin.social.isVisiting(p); } private void stop(Player p, Cancellable e) { diff --git a/src/main/java/com/extantape/voidwell/store/IslandStore.java b/src/main/java/com/extantape/onevoid/store/IslandStore.java similarity index 96% rename from src/main/java/com/extantape/voidwell/store/IslandStore.java rename to src/main/java/com/extantape/onevoid/store/IslandStore.java index f314bb4..92f2b82 100644 --- a/src/main/java/com/extantape/voidwell/store/IslandStore.java +++ b/src/main/java/com/extantape/onevoid/store/IslandStore.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.store; +package com.extantape.onevoid.store; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -12,7 +12,7 @@ import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.YamlConfiguration; -/** Where each island's way bell is, in plugins/Voidwell/islands.yml. Island ids are OneBlock's. */ +/** Where each island's way bell is, in plugins/OneVoid/islands.yml. Island ids are OneBlock's. */ public final class IslandStore { public record BellPos(int x, int y, int z) {} diff --git a/src/main/java/com/extantape/voidwell/store/PlayerData.java b/src/main/java/com/extantape/onevoid/store/PlayerData.java similarity index 90% rename from src/main/java/com/extantape/voidwell/store/PlayerData.java rename to src/main/java/com/extantape/onevoid/store/PlayerData.java index 44b8c8a..ed20ea1 100644 --- a/src/main/java/com/extantape/voidwell/store/PlayerData.java +++ b/src/main/java/com/extantape/onevoid/store/PlayerData.java @@ -1,13 +1,13 @@ -package com.extantape.voidwell.store; +package com.extantape.onevoid.store; -import com.extantape.voidwell.meter.Meter; +import com.extantape.onevoid.meter.Meter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -/** Everything Voidwell keeps about one player. Saved to plugins/Voidwell/players/.yml. */ +/** Everything OneVoid keeps about one player. Saved to plugins/OneVoid/players/.yml. */ public final class PlayerData { public final UUID id; public final Meter meter = new Meter(); diff --git a/src/main/java/com/extantape/voidwell/store/PlayerStore.java b/src/main/java/com/extantape/onevoid/store/PlayerStore.java similarity index 94% rename from src/main/java/com/extantape/voidwell/store/PlayerStore.java rename to src/main/java/com/extantape/onevoid/store/PlayerStore.java index 1aab067..65f61a0 100644 --- a/src/main/java/com/extantape/voidwell/store/PlayerStore.java +++ b/src/main/java/com/extantape/onevoid/store/PlayerStore.java @@ -1,6 +1,6 @@ -package com.extantape.voidwell.store; +package com.extantape.onevoid.store; -import com.extantape.voidwell.store.PlayerData.Spot; +import com.extantape.onevoid.store.PlayerData.Spot; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.AtomicMoveNotSupportedException; @@ -81,7 +81,7 @@ private PlayerData load(UUID id) { /** Writes the player's file now. Called at every moment a crash would matter. */ public void save(PlayerData d) { YamlConfiguration y = new YamlConfiguration(); - y.options().setHeader(List.of("Voidwell player data. Safe to read; edit only with the server stopped.")); + y.options().setHeader(List.of("OneVoid player data. Safe to read; edit only with the server stopped.")); y.set("meter.points", round(d.meter.points)); if (!d.meter.day.equals(LocalDate.MIN)) y.set("meter.day", d.meter.day.toString()); y.set("meter.charged-today", round(d.meter.chargedToday)); @@ -104,7 +104,7 @@ public void save(PlayerData d) { Files.move(tmp, file(d.id), StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { - log.severe("Couldn't save Voidwell data for " + d.id + ": " + e.getMessage()); + log.severe("Couldn't save OneVoid data for " + d.id + ": " + e.getMessage()); } } diff --git a/src/main/java/com/extantape/voidwell/trip/DeathListener.java b/src/main/java/com/extantape/onevoid/trip/DeathListener.java similarity index 95% rename from src/main/java/com/extantape/voidwell/trip/DeathListener.java rename to src/main/java/com/extantape/onevoid/trip/DeathListener.java index c51b477..832cd91 100644 --- a/src/main/java/com/extantape/voidwell/trip/DeathListener.java +++ b/src/main/java/com/extantape/onevoid/trip/DeathListener.java @@ -1,7 +1,7 @@ -package com.extantape.voidwell.trip; +package com.extantape.onevoid.trip; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; import java.util.HashSet; import java.util.Optional; import java.util.Set; @@ -28,14 +28,14 @@ * and last longer. Either way the player respawns outside the OneBlock gate at the Waystation, bed or not. */ public final class DeathListener implements Listener { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; private final Set diedHere = new HashSet<>(); private final NamespacedKey lives, dropOwner; /** Who just died where, so the items that spawn from that death this tick can be marked as theirs. */ private UUID dying; private Location dyingAt; - public DeathListener(VoidwellPlugin plugin) { + public DeathListener(OneVoidPlugin plugin) { this.plugin = plugin; this.lives = new NamespacedKey(plugin, "despawn-count"); this.dropOwner = new NamespacedKey(plugin, "death-drop-of"); @@ -110,7 +110,7 @@ public void onRespawn(PlayerRespawnEvent e) { }); // Another plugin can still move a player after the respawn (seen once on a real server's rehearsal, not // in this repo's tests). The promise is the gate, so put them there, and say so in the console, so an - // admin can find which plugin did it (start Java with -Dvoidwell.trace=true to log every teleport). + // admin can find which plugin did it (start Java with -Donevoid.trace=true to log every teleport). Location promised = gate.get().clone(); Bukkit.getScheduler().runTaskLater(plugin, () -> { if (!p.isOnline() || atLanding(p.getLocation(), promised)) return; @@ -118,8 +118,8 @@ public void onRespawn(PlayerRespawnEvent e) { // Seen on a real server (2026-11-10): Multiverse-Inventories with apply-last-location-for-all-teleports // put respawned players back on their last spot in the station, the step into the OneBlock gate. plugin.getLogger().warning("Something moved " + p.getName() + " away from the Waystation's OneBlock gate after their respawn (to " - + at.getWorld().getName() + " " + at.getBlockX() + ", " + at.getBlockY() + ", " + at.getBlockZ() + "). Putting them back, as Voidwell promised." - + " Multiverse-Inventories' apply-last-location-for-all-teleports does this; -Dvoidwell.trace=true shows any other cause."); + + at.getWorld().getName() + " " + at.getBlockX() + ", " + at.getBlockY() + ", " + at.getBlockZ() + "). Putting them back, as OneVoid promised." + + " Multiverse-Inventories' apply-last-location-for-all-teleports does this; -Donevoid.trace=true shows any other cause."); p.teleportAsync(promised, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.PLUGIN); }, 10L); } else { diff --git a/src/main/java/com/extantape/voidwell/trip/Trips.java b/src/main/java/com/extantape/onevoid/trip/Trips.java similarity index 94% rename from src/main/java/com/extantape/voidwell/trip/Trips.java rename to src/main/java/com/extantape/onevoid/trip/Trips.java index c33fe3e..5850318 100644 --- a/src/main/java/com/extantape/voidwell/trip/Trips.java +++ b/src/main/java/com/extantape/onevoid/trip/Trips.java @@ -1,9 +1,9 @@ -package com.extantape.voidwell.trip; +package com.extantape.onevoid.trip; -import com.extantape.voidwell.Text; -import com.extantape.voidwell.VoidwellPlugin; -import com.extantape.voidwell.store.PlayerData; -import com.extantape.voidwell.store.PlayerData.Spot; +import com.extantape.onevoid.Text; +import com.extantape.onevoid.OneVoidPlugin; +import com.extantape.onevoid.store.PlayerData; +import com.extantape.onevoid.store.PlayerData.Spot; import com.extantape.waystation.LandingService; import java.util.Optional; import org.bukkit.Bukkit; @@ -16,9 +16,9 @@ /** Getting into OneBlock from the Waystation, and back out by the way bell. */ public final class Trips { - private final VoidwellPlugin plugin; + private final OneVoidPlugin plugin; - public Trips(VoidwellPlugin plugin) { + public Trips(OneVoidPlugin plugin) { this.plugin = plugin; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 01ee493..d2237e5 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,4 +1,4 @@ -# Voidwell settings. After editing, run /voidwell reload. +# OneVoid settings. After editing, run /onevoid reload. config-version: 1 # The way bell: how players leave their island for the Waystation. @@ -59,8 +59,8 @@ rewards: enabled: true minutes: 5 -# Visiting other islands, and teams. Both need HouseRules circles: two players must share one. -# If HouseRules has no circles, or either player is offline, the answer is no. +# Visiting other islands, and teams. Both need Mayor circles: two players must share one. +# If Mayor has no circles, or either player is offline, the answer is no. social: invite-seconds: 60 # Most players on one island, the owner included. @@ -68,7 +68,7 @@ social: # Saves after a death or a bell trip, so a crash can't roll a player back into a duplicate or a loss. # With Rewild installed, tells it to leave every OneBlock island alone. OneBlock's world is void, so a rewild there -# would erase what the one block built. Rewild listens once an admin respects Voidwell with /rewild plugins. +# would erase what the one block built. Rewild listens once an admin respects OneVoid with /rewild plugins. rewild: keep-islands: true diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml index ef2471f..bf684ba 100644 --- a/src/main/resources/paper-plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -1,10 +1,10 @@ -name: Voidwell +name: OneVoid version: '${version}' -main: com.extantape.voidwell.VoidwellPlugin +main: com.extantape.onevoid.OneVoidPlugin api-version: '26.1' description: A OneBlock add-on. Walk in through the Waystation, ring your island's bell to leave, and turn what the void takes into rewards. -website: https://github.com/ExtantApe/Voidwell -# /voidwell is registered with Brigadier in code, so there is no commands section. +website: https://github.com/ExtantApe/OneVoid +# /onevoid is registered with Brigadier in code, so there is no commands section. dependencies: server: # The OneBlock gate and the landing spot outside it. @@ -18,16 +18,16 @@ dependencies: required: true join-classpath: true # Optional. Its circle permissions decide who may visit or team up with whom. - HouseRules: + Mayor: load: BEFORE required: false permissions: - voidwell.use: - description: Use /voidwell to see the void meter and choose rewards. The way bell needs no permission. + onevoid.use: + description: Use /onevoid to see the void meter and choose rewards. The way bell needs no permission. default: true - voidwell.admin: - description: /voidwell reload, status, meter and bell. Also lets an admin change things on any island. + onevoid.admin: + description: /onevoid reload, status, meter and bell. Also lets an admin change things on any island. default: op - voidwell.oneblock-commands: + onevoid.oneblock-commands: description: Type OneBlock's /ob commands. Players without it are pointed to the gate and the way bell instead. default: op diff --git a/src/test/java/com/extantape/voidwell/CommandGuardTest.java b/src/test/java/com/extantape/onevoid/CommandGuardTest.java similarity index 83% rename from src/test/java/com/extantape/voidwell/CommandGuardTest.java rename to src/test/java/com/extantape/onevoid/CommandGuardTest.java index f3618f5..10f6d87 100644 --- a/src/test/java/com/extantape/voidwell/CommandGuardTest.java +++ b/src/test/java/com/extantape/onevoid/CommandGuardTest.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import static org.junit.jupiter.api.Assertions.*; @@ -12,6 +12,6 @@ void catchesEveryFormOfOb() { assertTrue(CommandGuard.isOneBlock("/OB visit someone")); assertTrue(CommandGuard.isOneBlock("/oneblock:oneblock j")); assertFalse(CommandGuard.isOneBlock("/obey")); - assertFalse(CommandGuard.isOneBlock("/voidwell")); + assertFalse(CommandGuard.isOneBlock("/onevoid")); } } diff --git a/src/test/java/com/extantape/voidwell/RewildKeepsTest.java b/src/test/java/com/extantape/onevoid/RewildKeepsTest.java similarity index 95% rename from src/test/java/com/extantape/voidwell/RewildKeepsTest.java rename to src/test/java/com/extantape/onevoid/RewildKeepsTest.java index 5ae7509..4f40e01 100644 --- a/src/test/java/com/extantape/voidwell/RewildKeepsTest.java +++ b/src/test/java/com/extantape/onevoid/RewildKeepsTest.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell; +package com.extantape.onevoid; import org.bukkit.World; import org.junit.jupiter.api.Test; @@ -52,7 +52,7 @@ static World world(String name) { } @Test void anIslandsSquareCoversItsChunks() { - var c = com.extantape.voidwell.oneblock.OneBlockBridge.squareChunks(0, 0, 100); + var c = com.extantape.onevoid.oneblock.OneBlockBridge.squareChunks(0, 0, 100); // 100-block spacing: 50 each way from 0,0, so chunks -4..3 on each axis. assertEquals(64, c.size()); assertTrue(c.stream().anyMatch(a -> a[0] == -4 && a[1] == 3)); diff --git a/src/test/java/com/extantape/voidwell/meter/MeterTest.java b/src/test/java/com/extantape/onevoid/meter/MeterTest.java similarity index 98% rename from src/test/java/com/extantape/voidwell/meter/MeterTest.java rename to src/test/java/com/extantape/onevoid/meter/MeterTest.java index d1ef1fb..ae53bb7 100644 --- a/src/test/java/com/extantape/voidwell/meter/MeterTest.java +++ b/src/test/java/com/extantape/onevoid/meter/MeterTest.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.meter; +package com.extantape.onevoid.meter; import static org.junit.jupiter.api.Assertions.*; diff --git a/src/test/java/com/extantape/voidwell/social/ShareCircleTest.java b/src/test/java/com/extantape/onevoid/social/ShareCircleTest.java similarity index 78% rename from src/test/java/com/extantape/voidwell/social/ShareCircleTest.java rename to src/test/java/com/extantape/onevoid/social/ShareCircleTest.java index 2edcdf5..fcb9327 100644 --- a/src/test/java/com/extantape/voidwell/social/ShareCircleTest.java +++ b/src/test/java/com/extantape/onevoid/social/ShareCircleTest.java @@ -1,4 +1,4 @@ -package com.extantape.voidwell.social; +package com.extantape.onevoid.social; import org.junit.jupiter.api.Test; @@ -9,8 +9,8 @@ /** Kids first: travel and teams only connect two online players who share a circle; anything else is no. */ class ShareCircleTest { - static final List CIRCLES = List.of("houserules.circle.kids", "houserules.circle.adults"); - static final Set KID = Set.of("houserules.circle.kids"), OTHER_KID = Set.of("houserules.circle.kids"), ADULT = Set.of("houserules.circle.adults"); + static final List CIRCLES = List.of("mayor.circle.kids", "mayor.circle.adults"); + static final Set KID = Set.of("mayor.circle.kids"), OTHER_KID = Set.of("mayor.circle.kids"), ADULT = Set.of("mayor.circle.adults"); @Test void controlTwoOnlineKidsInOneCircleShareIt() { assertTrue(Social.shareCircle(CIRCLES, true, KID::contains, true, OTHER_KID::contains)); diff --git a/test/README.md b/test/README.md index fa82255..58c9ec1 100644 --- a/test/README.md +++ b/test/README.md @@ -5,8 +5,8 @@ Bot tests on a throwaway Paper server on 127.0.0.1:25621. Each run makes a fresh ```bash npm install node fetch.mjs # Paper, OneBlock, Multiverse, LuckPerms, Via: each checked against its published hash -gh release download v0.1.1 -R ExtantApe/HouseRules -p '*.jar' -D work/cache -(cd .. && ./gradlew build) # Voidwell and the Waystation stand-in +gh release download v0.1.1 -R ExtantApe/Mayor -p '*.jar' -D work/cache +(cd .. && ./gradlew build) # OneVoid and the Waystation stand-in node suite.mjs 26.2 # everything node suite.mjs 26.2 payouts # one test SERVER_ONLY=1 node suite.mjs 26.3 # checks without players @@ -14,7 +14,7 @@ SERVER_ONLY=1 node suite.mjs 26.3 # checks without players The bots are mineflayer 26.1 clients. On 26.2 they connect through ViaVersion and ViaBackwards. Paper 26.3 disconnects them as soon as they join, so 26.3 gets the server-only checks. -Set `VOIDWELL_WAYSTATION_JAR` to a real Waystation jar (0.4.0 or later, checked against its release's SHA-256) to test against it. The harness writes Waystation's own config with `oneblock: {hand-over: true}` and island posts off, puts its station world in the Lobby inventory group, and the bots walk through the real OneBlock gate. `VOIDWELL_TEST_LOG=` keeps the server console after the run. +Set `ONEVOID_WAYSTATION_JAR` to a real Waystation jar (0.4.0 or later, checked against its release's SHA-256) to test against it. The harness writes Waystation's own config with `oneblock: {hand-over: true}` and island posts off, puts its station world in the Lobby inventory group, and the bots walk through the real OneBlock gate. `ONEVOID_TEST_LOG=` keeps the server console after the run. Without it, `test/standin` stands in for Waystation's hand-over event and landing service, with the same class names and signatures. `/standin gate oneblock` plays the part of walking through the OneBlock gate, and the landing spot is a stone pad in the main world. It's never shipped. diff --git a/test/fetch.mjs b/test/fetch.mjs index 67e9aab..567d47e 100644 --- a/test/fetch.mjs +++ b/test/fetch.mjs @@ -7,7 +7,7 @@ import path from 'node:path' const CACHE = new URL('./work/cache/', import.meta.url).pathname mkdirSync(CACHE, { recursive: true }) -const UA = { 'User-Agent': 'voidwell-live-tests (ExtantApe/Voidwell)' } +const UA = { 'User-Agent': 'onevoid-live-tests (ExtantApe/OneVoid)' } async function json(url) { const r = await fetch(url, { headers: UA }) @@ -58,5 +58,5 @@ const out = { } writeFileSync(path.join(CACHE, 'manifest.json'), JSON.stringify(out, null, 2)) console.log('all jars checked') -// HouseRules isn't on Modrinth yet. Fetch its release jar with: gh release download v0.1.1 -R ExtantApe/HouseRules -p '*.jar' -D test/work/cache -if (!existsSync(path.join(CACHE, 'HouseRules-0.1.1.jar'))) console.log('Missing HouseRules-0.1.1.jar: see the note at the end of fetch.mjs') +// Mayor isn't on Modrinth yet. Fetch its release jar with: gh release download v0.1.1 -R ExtantApe/Mayor -p '*.jar' -D test/work/cache +if (!existsSync(path.join(CACHE, 'Mayor-0.1.1.jar'))) console.log('Missing Mayor-0.1.1.jar: see the note at the end of fetch.mjs') diff --git a/test/lib.mjs b/test/lib.mjs index 39928e1..ae7e9e0 100644 --- a/test/lib.mjs +++ b/test/lib.mjs @@ -8,13 +8,13 @@ import mineflayer from 'mineflayer' export const PORT = 25621 export const CLIENT = '26.1' -export const JAVA = process.env.VOIDWELL_TEST_JAVA ?? '/Library/Java/JavaVirtualMachines/openjdk-25.jdk/Contents/Home/bin/java' +export const JAVA = process.env.ONEVOID_TEST_JAVA ?? '/Library/Java/JavaVirtualMachines/openjdk-25.jdk/Contents/Home/bin/java' export const ROOT = new URL('../', import.meta.url).pathname const CACHE = path.join(ROOT, 'test/work/cache') export const sleep = ms => new Promise(r => setTimeout(r, ms)) -// Set VOIDWELL_WAYSTATION_JAR to a real Waystation jar to test against it instead of the stand-in. Bots then walk +// Set ONEVOID_WAYSTATION_JAR to a real Waystation jar to test against it instead of the stand-in. Bots then walk // through the station's real OneBlock gate. -export const REAL_WAYSTATION = process.env.VOIDWELL_WAYSTATION_JAR ?? null +export const REAL_WAYSTATION = process.env.ONEVOID_WAYSTATION_JAR ?? null /** Every bot made by bot(), by name, so helpers that get only a name can walk it through the gate. */ export const bots = new Map() @@ -25,9 +25,9 @@ function jar(dir, re) { } export class Server { - constructor(version, base = process.env.VOIDWELL_TEST_TMP ?? os.tmpdir()) { + constructor(version, base = process.env.ONEVOID_TEST_TMP ?? os.tmpdir()) { this.version = version - this.dir = path.join(base, `voidwell-live-${version}-${process.pid}`) + this.dir = path.join(base, `onevoid-live-${version}-${process.pid}`) this.log = '' this.proc = null } @@ -38,13 +38,13 @@ export class Server { prepare({ config = {}, extraPlugins = [] } = {}) { const manifest = JSON.parse(readFileSync(path.join(CACHE, 'manifest.json'), 'utf8')) rmSync(this.dir, { recursive: true, force: true }) - mkdirSync(this.path('plugins/Voidwell'), { recursive: true }) + mkdirSync(this.path('plugins/OneVoid'), { recursive: true }) copyFileSync(manifest.paper[this.version], this.path('paper.jar')) // Paper's downloaded libraries are kept between runs (not a server copy: no worlds or player data). const libs = path.join(CACHE, `libs-${this.version}`) if (existsSync(libs)) execSync(`cp -cR "${libs}/." "${this.dir}/"`) for (const p of [...manifest.plugins, ...manifest.via]) copyFileSync(p, this.path('plugins', path.basename(p))) - copyFileSync(jar(path.join(ROOT, 'build/libs'), /^Voidwell-.*\.jar$/), this.path('plugins/Voidwell.jar')) + copyFileSync(jar(path.join(ROOT, 'build/libs'), /^OneVoid-.*\.jar$/), this.path('plugins/OneVoid.jar')) if (REAL_WAYSTATION) { copyFileSync(REAL_WAYSTATION, this.path('plugins/Waystation.jar')) // Its own default config, with the OneBlock world handed over and island posts off, as the README says. @@ -57,8 +57,8 @@ export class Server { mkdirSync(this.path('plugins/Waystation'), { recursive: true }) writeFileSync(this.path('plugins/Waystation/config.yml'), ws) } else copyFileSync(jar(path.join(ROOT, 'test/standin/build/libs'), /^WaystationStandin.*\.jar$/), this.path('plugins/WaystationStandin.jar')) - // HouseRules 0.1.1, from its GitHub release (see fetch.mjs). - copyFileSync(path.join(CACHE, 'HouseRules-0.1.1.jar'), this.path('plugins/HouseRules.jar')) + // Mayor 0.1.1, from its GitHub release (see fetch.mjs). + copyFileSync(path.join(CACHE, 'Mayor-0.1.1.jar'), this.path('plugins/Mayor.jar')) for (const p of extraPlugins) copyFileSync(p, this.path('plugins', path.basename(p))) writeFileSync(this.path('eula.txt'), 'eula=true\n') writeFileSync(this.path('server.properties'), [ @@ -66,8 +66,8 @@ export class Server { 'spawn-protection=0', 'enable-rcon=false', 'white-list=false', 'enforce-whitelist=false', 'enable-query=false', 'max-players=10', 'view-distance=4', 'simulation-distance=4', 'gamemode=survival', 'difficulty=easy', 'spawn-monsters=false', 'allow-flight=true', ].join('\n') + '\n') - mkdirSync(this.path('plugins/HouseRules'), { recursive: true }) - writeFileSync(this.path('plugins/HouseRules/config.yml'), 'config-version: 1\ncircles:\n - kids\n - adults\n') + mkdirSync(this.path('plugins/Mayor'), { recursive: true }) + writeFileSync(this.path('plugins/Mayor/config.yml'), 'config-version: 1\ncircles:\n - kids\n - adults\n') // Test settings: short powers, so they can be seen ending. const vw = readFileSync(path.join(ROOT, 'src/main/resources/config.yml'), 'utf8') let text = vw @@ -75,12 +75,12 @@ export class Server { if (!text.includes(from)) throw new Error(`config.yml has no "${from}"`) text = text.replace(from, to) } - writeFileSync(this.path('plugins/Voidwell/config.yml'), text) + writeFileSync(this.path('plugins/OneVoid/config.yml'), text) } async start(timeout = 240000) { this.log = '' - this.proc = spawn(JAVA, ['-Xms1G', '-Xmx2G', '-Dpaper.disableChannelLimit=true', ...(process.env.VOIDWELL_TRACE ? ['-Dvoidwell.trace=true'] : []), '-jar', 'paper.jar', '--nogui'], { cwd: this.dir }) + this.proc = spawn(JAVA, ['-Xms1G', '-Xmx2G', '-Dpaper.disableChannelLimit=true', ...(process.env.ONEVOID_TRACE ? ['-Donevoid.trace=true'] : []), '-jar', 'paper.jar', '--nogui'], { cwd: this.dir }) this.proc.stdout.on('data', d => { this.log += d.toString().replace(/\x1b\[[0-9;]*m/g, '') }) this.proc.stderr.on('data', d => { this.log += d.toString() }) this.exited = new Promise(r => this.proc.on('exit', r)) diff --git a/test/package.json b/test/package.json index e30e46a..3177885 100644 --- a/test/package.json +++ b/test/package.json @@ -1 +1 @@ -{ "name": "voidwell-tests", "private": true, "type": "module", "dependencies": { "mineflayer": "^4.39.0" } } +{ "name": "onevoid-tests", "private": true, "type": "module", "dependencies": { "mineflayer": "^4.39.0" } } diff --git a/test/standin/src/main/java/com/extantape/waystation/StandinPlugin.java b/test/standin/src/main/java/com/extantape/waystation/StandinPlugin.java index 3226524..7da24bb 100644 --- a/test/standin/src/main/java/com/extantape/waystation/StandinPlugin.java +++ b/test/standin/src/main/java/com/extantape/waystation/StandinPlugin.java @@ -12,7 +12,7 @@ import org.bukkit.plugin.java.JavaPlugin; /** - * Stands in for Waystation in Voidwell's live tests. The "station" is a stone pad in the main world. + * Stands in for Waystation in OneVoid's live tests. The "station" is a stone pad in the main world. * "/standin gate " plays the part of walking through that world's gate. * "/standin landing on|off" makes landing() answer or come back empty, to test the fallback. */ diff --git a/test/suite.mjs b/test/suite.mjs index 1f943e5..726413c 100644 --- a/test/suite.mjs +++ b/test/suite.mjs @@ -1,4 +1,4 @@ -// Voidwell acceptance suite. Usage: node suite.mjs <26.2|26.3> [test names...] +// OneVoid acceptance suite. Usage: node suite.mjs <26.2|26.3> [test names...] // Runs on a fresh throwaway server on 127.0.0.1:25621, which is deleted afterwards. import { writeFileSync, readFileSync, existsSync } from 'node:fs' import { Server, bot, bots, heard, count, summary, sleep, REAL_WAYSTATION } from './lib.mjs' @@ -35,7 +35,7 @@ async function where(name) { } async function bellOf(name) { - const m = await s.run(`voidwell bell ${name}`, /way bell is at (-?\d+) (-?\d+) (-?\d+)|has no island/) + const m = await s.run(`onevoid bell ${name}`, /way bell is at (-?\d+) (-?\d+) (-?\d+)|has no island/) return m[1] === undefined ? null : { x: +m[1], y: +m[2], z: +m[3] } } @@ -45,7 +45,7 @@ async function isBlock(x, y, z, block, world = 'oneblock') { } function meterOf(b) { - const f = s.path(`plugins/Voidwell/players/${b.player.uuid}.yml`) + const f = s.path(`plugins/OneVoid/players/${b.player.uuid}.yml`) if (!existsSync(f)) return 0 const m = readFileSync(f, 'utf8').match(/points: ([\d.]+)/) return m ? +m[1] : 0 @@ -129,8 +129,8 @@ async function setup() { LANDING = { dim: `minecraft:${GATE.world}`, x: GATE.x + 0.5 + dx * 2, z: GATE.z + 0.5 + dz * 2 } console.log('real Waystation: gate', JSON.stringify(GATE), 'landing', JSON.stringify(LANDING)) } - const status = await s.run('voidwell status', /No problems found|Waystation|OneBlock|Lantern|circles/) - console.log('status:', s.log.slice(-800).split('\n').filter(l => /Voidwell|- /.test(l)).slice(-5).join(' / ')) + const status = await s.run('onevoid status', /No problems found|Waystation|OneBlock|Lantern|circles/) + console.log('status:', s.log.slice(-800).split('\n').filter(l => /OneVoid|- /.test(l)).slice(-5).join(' / ')) } function uuidInts(u) { @@ -182,9 +182,9 @@ async function sneakRing(b, bell) { } async function takeReward(b, id) { - await s.run(`voidwell offer ${b.username} ${id}`, /offered/) + await s.run(`onevoid offer ${b.username} ${id}`, /offered/) const w = window(b) - b.chat('/voidwell reward') + b.chat('/onevoid reward') await w await click(b, 11) const again = window(b).catch(() => null) @@ -206,9 +206,9 @@ async function invData(name) { const tests = { /** Server-only checks, for versions bots can't stay connected to (26.3 through ViaVersion). */ async serverOnly() { - check('server: Voidwell enabled', /Enabling Voidwell v/.test(s.log) && !/Error occurred while enabling Voidwell/.test(s.log)) + check('server: OneVoid enabled', /Enabling OneVoid v/.test(s.log) && !/Error occurred while enabling OneVoid/.test(s.log)) await sleep(12000) // OneBlock loads its world a few seconds after startup - const m = s.mark(); s.cmd('voidwell status'); await sleep(2000) + const m = s.mark(); s.cmd('onevoid status'); await sleep(2000) const out = s.since(m) check('server: OneBlock world found and Waystation landing ready', /OneBlock world: oneblock/.test(out) && /Waystation landing: ready/.test(out), out.split('\n').filter(l => / - /.test(l)).join(' / ')) check('server: no problems reported', /No problems found/.test(out)) @@ -216,7 +216,7 @@ const tests = { const r = await s.run('standin gate Nobody oneblock', /no such player|handled=/) check('server: hand-over command path loads', !!r) } else check('server: the real Waystation made the OneBlock gate', !!GATE, JSON.stringify(GATE)) - const startup = s.log.split('\n').filter(l => /\[Voidwell\]/.test(l) && /WARN/.test(l)) + const startup = s.log.split('\n').filter(l => /\[OneVoid\]/.test(l) && /WARN/.test(l)) check('server: no startup warnings once set up', startup.length === 0, startup.join(' / ')) }, @@ -254,7 +254,7 @@ const tests = { check('island death: respawned outside the gate despite the respawn point', atLanding(w), JSON.stringify(w)) check('island death: lobby inventory, no OneBlock items', summary(a).diamond === 5 && !summary(a).dirt && !summary(a).stone_axe, JSON.stringify(summary(a))) const n = await itemsNear(0.5, 101, 0.5, 8) - const probe = async label => { const m = s.mark(); s.cmd('execute as @e[type=item] run data get entity @s'); await sleep(1500); console.log(' ' + label + ':\n' + s.since(m).split('\n').filter(l => /entity data/.test(l)).map(l => ' ' + (l.match(/Pos: \[[^\]]*\]/)?.[0] ?? '') + ' ' + (l.match(/Age: -?\d+s/)?.[0] ?? '') + ' ' + (l.match(/id: "minecraft:[a-z_]+"/)?.[0] ?? '') + ' ' + (l.match(/voidwell:[a-z-]+": [^,}]+/)?.[0] ?? '')).join('\n')) } + const probe = async label => { const m = s.mark(); s.cmd('execute as @e[type=item] run data get entity @s'); await sleep(1500); console.log(' ' + label + ':\n' + s.since(m).split('\n').filter(l => /entity data/.test(l)).map(l => ' ' + (l.match(/Pos: \[[^\]]*\]/)?.[0] ?? '') + ' ' + (l.match(/Age: -?\d+s/)?.[0] ?? '') + ' ' + (l.match(/id: "minecraft:[a-z_]+"/)?.[0] ?? '') + ' ' + (l.match(/onevoid:[a-z-]+": [^,}]+/)?.[0] ?? '')).join('\n')) } if (process.env.PROBE) await probe('after death') check('island death: both items dropped on the island, and no extra copies', n === 2, `${n} item entities`) const m = s.mark(); s.cmd('tick sprint 30000'); await s.waitFor(/Sprint completed/, 600000, m) @@ -366,13 +366,13 @@ const tests = { check('commands: /ob did nothing', Math.hypot(after.x - before.x, after.z - before.z) < 1 && after.dim === before.dim) const roots = a.rootCommands.filter(c => /^(oneblock:)?(ob|oneblock)/.test(c)) check('commands: /ob hidden from the client\'s command list', a.rootCommands.length > 0 && roots.length === 0, `${a.rootCommands.length} commands sent; OneBlock ones: ${JSON.stringify(roots)}`) - await s.run('lp user Ash permission set voidwell.oneblock-commands true', /Set|already/) + await s.run('lp user Ash permission set onevoid.oneblock-commands true', /Set|already/) await sleep(1000) const m2 = a.chatLog.length a.chat('/ob help') await sleep(1500) check('commands: an admin can still use /ob', !a.chatLog.slice(m2).some(l => /no commands here/.test(l)), a.chatLog.slice(m2).join(' | ').slice(0, 200)) - await s.run('lp user Ash permission unset voidwell.oneblock-commands', /Unset|does not have/) + await s.run('lp user Ash permission unset onevoid.oneblock-commands', /Unset|does not have/) a.quit(); await sleep(1000) }, @@ -383,8 +383,8 @@ const tests = { await s.run('execute in minecraft:oneblock run tp Ash 0.5 101 0.5 0 0', /Teleported/) await sleep(800) // The menu: three choices, a click to choose and a second to confirm. - await s.run('voidwell offer Ash featherfall void-safe bountiful-block', /offered/) - let w = window(a); a.chat('/voidwell reward'); const menu = await w + await s.run('onevoid offer Ash featherfall void-safe bountiful-block', /offered/) + let w = window(a); a.chat('/onevoid reward'); const menu = await w const names = [11, 13, 15].map(i => JSON.stringify(menu.slots[i]?.customName ?? '').match(/"text":\{"type":"string","value":"([^"]+)"/g)?.map(x => x.split('"').at(-2)).join(' ') ?? '') check('payouts: menu offers three rewards', names.filter(Boolean).length === 3, names.join(' | ').slice(0, 200)) await click(a, 11) @@ -436,10 +436,10 @@ const tests = { await platform(true) // First the losing side. The odds go to 1 in 100 for this one take (the most the config allows), so it // loses 99 times in 100. A win here is reported as such, not as a pass. - const cfg = s.path('plugins/Voidwell/config.yml') + const cfg = s.path('plugins/OneVoid/config.yml') writeFileSync(cfg, readFileSync(cfg, 'utf8').replace(' one-in: 1\n', ' one-in: 100\n')) - await s.run('voidwell reload', /Voidwell/); await sleep(500) - await s.run('voidwell meter Ash 0', /meter is now/) + await s.run('onevoid reload', /OneVoid/); await sleep(500) + await s.run('onevoid meter Ash 0', /meter is now/) const lossBefore = count(a) await takeReward(a, 'void-gives-back') const lost = a.chatLog.some(l => /Not this time/.test(l)) @@ -449,7 +449,7 @@ const tests = { check('payouts: "not this time" starts the meter again 25% full', Math.abs(meterOf(a) - 25) < 0.01, `meter ${meterOf(a)}`) } writeFileSync(cfg, readFileSync(cfg, 'utf8').replace(' one-in: 100\n', ' one-in: 1\n')) - await s.run('voidwell reload', /Voidwell/); await sleep(500) + await s.run('onevoid reload', /OneVoid/); await sleep(500) // Then the winning side, with the same gear: after a loss it's still there for another try. const gearBefore = count(a) await takeReward(a, 'void-gives-back') @@ -465,7 +465,7 @@ const tests = { async travelAndTeams() { const a = await bot('Ash'); const b = await bot('Birch'); const c = await bot('Cedar'); const d = await bot('Dell') for (const [n, circle] of [['Ash', 'kids'], ['Birch', 'kids'], ['Dell', 'kids'], ['Cedar', 'adults']]) - await s.run(`lp user ${n} permission set houserules.circle.${circle} true`, /Set|already/) + await s.run(`lp user ${n} permission set mayor.circle.${circle} true`, /Set|already/) await sleep(1500) await home(a); await home(b); await home(c) await platform(true) @@ -576,7 +576,7 @@ const tests = { check('teams: a kid in the same circle can be invited', di >= 0) if (di >= 0) await click(b, di) await heard(d, /Birch.*invites you/, 5000).then(() => check('teams: the invite arrives, with buttons', true)).catch(e => check('teams: the invite arrives, with buttons', false, e.message)) - d.chat('/voidwell team accept Birch') + d.chat('/onevoid team accept Birch') await sleep(4000) pos = await where('Dell') check('teams: Dell joined Birch\'s island', pos.dim === 'minecraft:oneblock' && Math.hypot(pos.x - bPos.x, pos.z - bPos.z) < 20, JSON.stringify(pos)) @@ -652,15 +652,15 @@ const tests = { await s.run('execute in minecraft:oneblock run tp Ash 0.5 101 0.5 0 0', /Teleported/); await sleep(500) await a.toss(a.registry.itemsByName.netherite_sword.id, null, 1) await sleep(11000) - await s.run('voidwell offer Ash void-gives-back', /offered/) - const w = window(a); a.chat('/voidwell reward'); await w + await s.run('onevoid offer Ash void-gives-back', /offered/) + const w = window(a); a.chat('/onevoid reward'); await w await click(a, 11); await a.clickWindow(11, 0, 0) await sleep(150) await s.kill9(); await s.start(); await sleep(2000) a = await bot('Ash'); await sleep(1500) await home(a); await sleep(3000) const gear = a.inventory.items().filter(i => /sword|chestplate/.test(i.name)).length - const file = readFileSync(s.path(`plugins/Voidwell/players/${a.player.uuid}.yml`), 'utf8') + const file = readFileSync(s.path(`plugins/OneVoid/players/${a.player.uuid}.yml`), 'utf8') check('crash mid-payout: the returned gear arrives exactly once', gear === 1 && !/deliveries:\s*\n\s+\S/.test(file), `${gear} pieces; ${JSON.stringify(summary(a))}`) a.quit(); await sleep(1000) }, @@ -668,9 +668,9 @@ const tests = { async restarts() { let a = await bot('Ash') await home(a) - await s.run('voidwell meter Ash 40', /meter is now/) + await s.run('onevoid meter Ash 40', /meter is now/) await takeReward(a, 'featherfall').catch(() => {}) - await s.run('voidwell meter Ash 40', /meter is now/) + await s.run('onevoid meter Ash 40', /meter is now/) const bell = await bellOf('Ash') a.quit(); await sleep(1000) await s.stop(); await s.start(); await sleep(2000) @@ -744,7 +744,7 @@ const tests = { check('way bell: after a bell trip and back, a void death still respawns outside the gate', atLanding(died), JSON.stringify(died)) await heard(a, /back at the Waystation/, 3000, m).then(() => check('way bell: and says so', true)).catch(e => check('way bell: and says so', false, e.message)) // What the real server's rehearsal saw: something moves the player back onto the island right after the respawn. - // Played here by the console, within the first tick or two. Voidwell must still end with them at the gate. + // Played here by the console, within the first tick or two. OneVoid must still end with them at the gate. await s.run('execute in minecraft:oneblock run tp Ash 2.5 101 0.5', /Teleported/) const mark = s.mark() await s.run('execute in minecraft:oneblock run tp Ash 0.5 -75 0.5', /Teleported/) @@ -752,10 +752,10 @@ const tests = { s.cmd('execute in minecraft:oneblock run tp Ash 2.5 101 0.5') await sleep(3000) const moved = await where('Ash') - check('way bell: if another plugin moves them back after the respawn, Voidwell still puts them at the gate', atLanding(moved), JSON.stringify(moved)) + check('way bell: if another plugin moves them back after the respawn, OneVoid still puts them at the gate', atLanding(moved), JSON.stringify(moved)) check('way bell: and the console says what happened', /Something moved Ash away from the Waystation's OneBlock gate after their respawn/.test(s.since(mark))) // What Multiverse-Inventories did on the real server's copy: right after the respawn, it put the player back on their - // last spot in the station, the step into the OneBlock gate. Voidwell puts them back at the landing, and Waystation + // last spot in the station, the step into the OneBlock gate. OneVoid puts them back at the landing, and Waystation // (0.7.0) won't fire a gate for someone a teleport put next to it until they've stepped clear. if (REAL_WAYSTATION && GATE) { const mark2 = s.mark() @@ -765,7 +765,7 @@ const tests = { await sleep(4000) const after = await where('Ash') check('way bell: put on the step into the gate after the respawn, they end at the landing, not on the island', atLanding(after), JSON.stringify(after)) - check('way bell: and the gate did not take them', !/minecraft:oneblock/.test(after.dim) && !s.since(mark2).includes('handed to Voidwell'), JSON.stringify(after)) + check('way bell: and the gate did not take them', !/minecraft:oneblock/.test(after.dim) && !s.since(mark2).includes('handed to OneVoid'), JSON.stringify(after)) } a.quit(); await sleep(1000) }, @@ -785,7 +785,7 @@ try { } finally { const errs = s ? s.errors() : [] console.log('server errors:', errs.length ? '\n' + errs.slice(0, 15).join('\n') : 'none') - if (s && process.env.VOIDWELL_TEST_LOG) writeFileSync(process.env.VOIDWELL_TEST_LOG, s.log) // the console, for debugging + if (s && process.env.ONEVOID_TEST_LOG) writeFileSync(process.env.ONEVOID_TEST_LOG, s.log) // the console, for debugging if (s) { await s.stop(); s.remove() } const failed = results.filter(r => !r.ok) console.log(`\n${version}: ${results.length - failed.length} passed, ${failed.length} failed`)