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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ jobs:
- run: ./gradlew build
- uses: actions/upload-artifact@v4
with:
name: Voidwell
name: OneVoid
path: build/libs/*.jar
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
50 changes: 25 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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.

Expand All @@ -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 <player> <points>` | admins | Set a meter, for support |
| `/voidwell offer <player> <rewards…>` | admins | Offer particular rewards, for support and tests |
| `/voidwell bell <player>` | 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 <player> <points>` | admins | Set a meter, for support |
| `/onevoid offer <player> <rewards…>` | admins | Offer particular rewards, for support and tests |
| `/onevoid bell <player>` | 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/<uuid>.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/<uuid>.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

Expand All @@ -88,16 +88,16 @@ 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

```bash
./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=<path to Waystation-0.4.0.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=<path to Waystation-0.4.0.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.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}

group = "com.extantape"
version = "0.1.3"
version = "0.2.0"

java {
toolchain.languageVersion.set(JavaLanguageVersion.of(25))
Expand Down Expand Up @@ -55,6 +55,6 @@ tasks.test {
}

tasks.jar {
archiveBaseName.set("Voidwell")
archiveBaseName.set("OneVoid")
from("LICENSE")
}
4 changes: 4 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 2 additions & 2 deletions docs/first-public-push-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand Down
13 changes: 13 additions & 0 deletions docs/releases/v0.2.0.md
Original file line number Diff line number Diff line change
@@ -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.
12 changes: 6 additions & 6 deletions docs/test-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
Loading
Loading