diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e97e820..33eb74f 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: BlueMinimap + name: BlueMapMini path: build/libs/*.jar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e58d4d8..3cef0f4 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/BlueMinimap-*.jar \ - --title "BlueMinimap $GITHUB_REF_NAME" --notes-file "docs/releases/$GITHUB_REF_NAME.md" + gh release create "$GITHUB_REF_NAME" build/libs/BlueMapMini-*.jar \ + --title "BlueMapMini $GITHUB_REF_NAME" --notes-file "docs/releases/$GITHUB_REF_NAME.md" diff --git a/CLAUDE.md b/CLAUDE.md index 3f79932..cd60409 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ -# BlueMinimap +# BlueMapMini -Registered in the owner's ops process (`~/Code/ops`). Area: `minecraft-plugins` (lead: Minecraft: Plugins Lead). Added 2026-11-09 from the ops starter kit; the repo itself dates from 2026-11-07 (as BlueMapHUD). +Registered in the owner's ops process (`~/Code/ops`). Area: `minecraft-plugins` (lead: Minecraft: Plugins Lead). Added 2026-11-09 from the ops starter kit; the repo itself dates from 2026-11-07. **Before doing anything here, run `~/Code/ops/scripts/repo-context`.** It shows who leads this repo, whether that session is active, what's pending, and which briefs apply. If it says the repo has no active owner, tell the director ("Helm") before starting work. diff --git a/README.md b/README.md index 7b900b0..7be69d9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# BlueMinimap +# BlueMapMini -BlueMinimap: a BlueMap minimap and coordinates HUD for Paper, rendered in game from [BlueMap](https://bluemap.bluecolored.de/)'s own tiles, with a fullscreen map too. It's an add-on to BlueMap, not a separate map: it needs BlueMap on the server and shows what BlueMap has rendered. It uses a small resource pack with its own namespace: no client mods, no shader overrides and no held map items. +BlueMapMini: a BlueMap minimap and coordinates HUD for Paper, rendered in game from [BlueMap](https://bluemap.bluecolored.de/)'s own tiles, with a fullscreen map too. It's an add-on to BlueMap, not a separate map: it needs BlueMap on the server and shows what BlueMap has rendered. It uses a small resource pack with its own namespace: no client mods, no shader overrides and no held map items. It's an unofficial add-on for BlueMap and isn't affiliated with BlueMap's authors. -**Status:** pre-release. It has passed a full test suite on live Paper 26.1.2, 26.2 and 26.3 servers with real BlueMap tiles, using a protocol bot. It hasn't been seen in a real game client yet. See [Testing](#testing). +**Status:** pre-release, version 0.3.0. It has passed a full test suite on live Paper 26.1.2, 26.2 and 26.3 servers with real BlueMap tiles, using a protocol bot. It hasn't been seen in a real game client yet. See [Testing](#testing). - Requires Paper 26.1 or newer, Java 25, and a BlueMap version that matches your server (see below). Java Edition only. Paper 1.21.11 and older aren't supported. - Works alongside other resource packs, because it never overrides a shader and only adds its own files. @@ -19,22 +19,12 @@ These minimums come from BlueMap's release notes. Only BlueMap 5.29 was tested, ## Install -1. Put `BlueMinimap-.jar` in `plugins/`, next to BlueMap. +1. Put `BlueMapMini-.jar` in `plugins/`, next to BlueMap. 2. Open port `8164` so players can download the pack, or set `pack.public-url` to host it elsewhere. Servers sharing a machine each need their own `pack.port`. `pack.bind` picks the address it listens on (empty means every address); `127.0.0.1` keeps it on the server's own machine, for when the pack reaches players another way. -3. Start the server. Settings are in `plugins/BlueMinimap/config.yml`. +3. Start the server. Settings are in `plugins/BlueMapMini/config.yml`. If BlueMap stores its maps in SQL, set `tiles.source: http`. -## Upgrading from BlueMapHUD - -BlueMinimap was called BlueMapHUD up to 0.1.0, and renamed in 0.2.0. Players keep their HUD settings. - -- With the server stopped, swap `BlueMapHUD-0.1.0.jar` for `BlueMinimap-0.2.0.jar`. -- On first start, `plugins/BlueMapHUD/` is copied to `plugins/BlueMinimap/` if that doesn't exist yet, so your config, themes and icons come across. The old folder is left untouched as a backup; nothing is overwritten. The pack is rebuilt as `plugins/BlueMinimap/pack/blueminimap-pack.zip`. If you host the pack yourself (`public-url`), upload the new file. -- For 0.2.x only, the old names still work: `/bmhud` (logged at startup), `/bluemaphud:map`, `/bluemaphud:hud` and the `bluemaphud.*` permissions. They go in the next release. For permissions that are on by default, a "no" on either the old or the new name wins, so a group you'd stopped from sharing stays stopped. Any difference between the two names is logged once per player. Set the `blueminimap.*` names instead. -- If HouseRules is installed, update it to 0.2.0 at the same time. With an older HouseRules, BlueMinimap turns `/hud share` off and logs why, because HouseRules 0.1.x wouldn't see the shares and couldn't keep them inside chat circles. -- Plugins that listen for shares: the event is now `com.extantape.blueminimap.api.CoordinateShareEvent`, with the same methods. - ## Commands | Command | What it does | @@ -52,25 +42,25 @@ BlueMinimap was called BlueMapHUD up to 0.1.0, and renamed in 0.2.0. Players kee | `/hud hide\|show shares` | Stops or restarts receiving coordinates other players share. | | `/hud theme`, `/hud theme \|default` | Lists the themes, with yours marked and each one clickable, or switches to one. `default` goes back to the server's. The choice is saved per player. | | `/hud mode coords\|map` | `coords` shows only the X, Y, Z and facing line, in the same bar, and works in worlds BlueMap doesn't map. `map` brings the minimap back. Both turn the HUD on, and `/hud mode` alone says which one you have. New players start in `hud.default-mode`, which is `map` unless the config says `coords`. | -| `/blueminimap help` | Shows help. | -| `/blueminimap reload` | Reloads the config, and re-sends the pack if it changed. | -| `/blueminimap debug` | Shows cache sizes, build times and update sizes. | -| `/blueminimap debug dump` | Writes your view to a PNG to compare with BlueMap. | -| `/blueminimap debug pattern` | Shows a test pattern. | -| `/blueminimap pack export` | Shows where the pack zip is, its SHA-1, and the address players are sent. | +| `/bluemapmini help` | Shows help. | +| `/bluemapmini reload` | Reloads the config, and re-sends the pack if it changed. | +| `/bluemapmini debug` | Shows cache sizes, build times and update sizes. | +| `/bluemapmini debug dump` | Writes your view to a PNG to compare with BlueMap. | +| `/bluemapmini debug pattern` | Shows a test pattern. | +| `/bluemapmini pack export` | Shows where the pack zip is, its SHA-1, and the address players are sent. | -If another plugin owns a name, BlueMinimap backs off: `/map` to `/worldmap`, then `/blueminimap map`, and `/hud` to `/minimap`, then `/blueminimap hud`. It logs which names it got. `/blueminimap map`, `/blueminimap hud`, `/blueminimap:map` and `/blueminimap:hud` always work. New names apply after a restart. +If another plugin owns a name, BlueMapMini backs off: `/map` to `/worldmap`, then `/bluemapmini map`, and `/hud` to `/minimap`, then `/bluemapmini hud`. It logs which names it got. `/bluemapmini map`, `/bluemapmini hud`, `/bluemapmini:map` and `/bluemapmini:hud` always work. New names apply after a restart. ## Permissions | Permission | Default | Allows | | --- | --- | --- | -| `blueminimap.use` | everyone | Seeing the map at all. Removing it hides everything for that group. | -| `blueminimap.fullscreen` | everyone | The fullscreen map. | -| `blueminimap.seeplayers` | everyone | Other players on the map. | -| `blueminimap.share.send` | everyone | Sharing your coordinates with `/hud share`. | -| `blueminimap.share.receive` | everyone | Receiving coordinates other players share. | -| `blueminimap.admin` | ops | `/blueminimap reload`, `debug` and `pack`. | +| `bluemapmini.use` | everyone | Seeing the map at all. Removing it hides everything for that group. | +| `bluemapmini.fullscreen` | everyone | The fullscreen map. | +| `bluemapmini.seeplayers` | everyone | Other players on the map. | +| `bluemapmini.share.send` | everyone | Sharing your coordinates with `/hud share`. | +| `bluemapmini.share.receive` | everyone | Receiving coordinates other players share. | +| `bluemapmini.admin` | ops | `/bluemapmini reload`, `debug` and `pack`. | ## Themes and the clock @@ -87,7 +77,7 @@ A theme sets the HUD's colours, the plate behind the coordinates and the look of The clock follows the coordinates as a small picture and 24-hour time, such as `18:30`. It changes every `hud.clock.step-minutes` in-game minutes, 5 by default, and its digits are fixed-width, so the line never shifts. It's hidden where time stands still, such as the Nether and the End. `hud.clock.enabled: false` turns it off for everyone, and `/hud hide clock` for one player. -**Your own theme.** Copy one of the files in [`src/main/resources/themes`](src/main/resources/themes) into `plugins/BlueMinimap/themes/`, rename it (lowercase, such as `ocean.json`), change it, and run `/blueminimap reload`. A file with a built-in theme's name replaces it. The file holds: +**Your own theme.** Copy one of the files in [`src/main/resources/themes`](src/main/resources/themes) into `plugins/BlueMapMini/themes/`, rename it (lowercase, such as `ocean.json`), change it, and run `/bluemapmini reload`. A file with a built-in theme's name replaces it. The file holds: - `name`: the name players see. - `colors`: `text`, `facing`, `time` and `legend` for text, `plate` for the plate, and `self`, `player`, `poi`, `death` and `north` for the map's icons. Each is `#RRGGBB`. @@ -101,23 +91,23 @@ Up to 8 themes fit in the pack. Every built-in theme passes the same readability `/hud share` sends your current coordinates to people you choose, as a chat message with the coordinates and the dimension, such as `Alex shared where they are: 120 64 -35 in the Overworld`. Clicking the numbers copies them. Nothing is shared unless a player asks, and there's no teleport link. -- **Who can receive:** by default, players in the sender's world, counting its `_nether` and `_the_end` as the same world, who can see the sender, have `blueminimap.share.receive`, and haven't turned shares off with `/hud hide shares`. +- **Who can receive:** by default, players in the sender's world, counting its `_nether` and `_the_end` as the same world, who can see the sender, have `bluemapmini.share.receive`, and haven't turned shares off with `/hud hide shares`. - **Feedback:** the sender is told exactly who got their coordinates, and who couldn't. - **Limits:** a player waits `share.cooldown-seconds` (30 by default) between shares, and each share is logged to the console. `share.enabled: false` turns sharing off. -**Your server's own rules.** BlueMinimap fires `com.extantape.blueminimap.api.CoordinateShareEvent` on the main thread before each share. It carries the sender, the world, the block coordinates and a mutable set of recipients. A plugin can remove recipients, for example to match who may chat with whom, or cancel the share. With `share.candidates: all-online`, recipients can include every player online, so that such a plugin can follow rules that reach across worlds. BlueMinimap only widens a share like that while a plugin is listening to the event, and logs a warning at startup if nothing is. To build against it, depend on BlueMinimap as a server dependency with `join-classpath: true` in your `paper-plugin.yml`. +**Your server's own rules.** BlueMapMini fires `com.extantape.bluemapmini.api.CoordinateShareEvent` on the main thread before each share. It carries the sender, the world, the block coordinates and a mutable set of recipients. A plugin can remove recipients, for example to match who may chat with whom, or cancel the share. With `share.candidates: all-online`, recipients can include every player online, so that such a plugin can follow rules that reach across worlds. BlueMapMini only widens a share like that while a plugin is listening to the event, and logs a warning at startup if nothing is. To build against it, depend on BlueMapMini as a server dependency with `join-classpath: true` in your `paper-plugin.yml`. ## Resource packs The plugin sends its pack alongside any others using the multi-pack API, and players don't see a map until their client confirms it loaded. With `pack.required`, a player who declines the pack is kicked with `pack.kick-message`. A download that fails never kicks: the player plays without the map and is told why, admins are warned, and the pack is offered again when they change worlds or rejoin. Its only file outside its own namespace is a transparent boss bar texture, in pink by default. If another pack restyles that colour, set `pack.boss-bar-color` to one it leaves alone. -**Using it with Magic.** Magic sends its pack with Bukkit's older one-pack method, which clears every other server pack. BlueMinimap re-sends its pack once when that happens, but it's better to stop the conflict. In `plugins/Magic/config.yml` set `resource_pack: ""`, then add Magic's pack to your main pack. +**Using it with Magic.** Magic sends its pack with Bukkit's older one-pack method, which clears every other server pack. BlueMapMini re-sends its pack once when that happens, but it's better to stop the conflict. In `plugins/Magic/config.yml` set `resource_pack: ""`, then add Magic's pack to your main pack. -**Hosting it elsewhere.** Set `pack.public-url` to where you upload `plugins/BlueMinimap/pack/blueminimap-pack.zip`. Upload it unchanged, because re-zipping changes its SHA-1 and clients reject a pack whose hash doesn't match. `{sha1}` in the address is replaced with the pack's hash, such as `https://example.com/packs/{sha1}.zip`, so the address changes whenever the pack does. The same settings and plugin version always build the same hash. On startup and `/blueminimap reload` the plugin downloads the address once in the background and warns, with both hashes, if it isn't the current pack. It never blocks startup. If the server can't reach the address but players can, set `pack.verify-public-url: false`. `/blueminimap pack export` shows the path, the hash and the address players are sent. +**Hosting it elsewhere.** Set `pack.public-url` to where you upload `plugins/BlueMapMini/pack/bluemapmini-pack.zip`. Upload it unchanged, because re-zipping changes its SHA-1 and clients reject a pack whose hash doesn't match. `{sha1}` in the address is replaced with the pack's hash, such as `https://example.com/packs/{sha1}.zip`, so the address changes whenever the pack does. The same settings and plugin version always build the same hash. On startup and `/bluemapmini reload` the plugin downloads the address once in the background and warns, with both hashes, if it isn't the current pack. It never blocks startup. If the server can't reach the address but players can, set `pack.verify-public-url: false`. `/bluemapmini pack export` shows the path, the hash and the address players are sent. -**Using a merged pack.** Set `pack.send: false`, run `/blueminimap pack export`, and merge that zip into your server's pack. On startup the plugin warns if its files are missing. +**Using a merged pack.** Set `pack.send: false`, run `/bluemapmini pack export`, and merge that zip into your server's pack. On startup the plugin warns if its files are missing. -**Custom icons.** Put 9x9 PNGs in `plugins/BlueMinimap/icons/` and run `/blueminimap reload`. The names are `arrow_00.png` to `arrow_15.png` (clockwise from north), `player.png`, `poi.png`, `death.png` and `north.png`. Draw them in white, because the plugin tints them. +**Custom icons.** Put 9x9 PNGs in `plugins/BlueMapMini/icons/` and run `/bluemapmini reload`. The names are `arrow_00.png` to `arrow_15.png` (clockwise from north), `player.png`, `poi.png`, `death.png` and `north.png`. Draw them in white, because the plugin tints them. ## Known limits @@ -145,7 +135,7 @@ Measured in the test suite on a synthetic map: | Minimap update, 32x32 with 20 players, compressed | about 1.7 KB | 5 KB | | Fullscreen update, 96x54, compressed | about 4.5 KB | none | -Real terrain has more colour variation than the test map, so expect larger updates in play. `/blueminimap debug` reports sizes before compression. +Real terrain has more colour variation than the test map, so expect larger updates in play. `/bluemapmini debug` reports sizes before compression. ## Testing @@ -166,14 +156,14 @@ The live tests are in [`test/live`](test/live/README.md), with what they cover a - **Hiding:** vanish, `hidePlayer`, spectators, invisibility, players hidden in BlueMap, the radius, other dimensions, permissions, other boss bars, the Wither, the Ender Dragon and every `auto-hide` setting. - **Updates:** nothing is sent while idle apart from each clock step, and at most 4 updates a second otherwise. - **Pack handling:** required, optional and declined packs, failed downloads (no kick, a message, an admin warning and a retry on world change), `host`, `public-url` with and without `{sha1}`, the hosted-pack check (matching, stale, missing, unreachable, never answering, invalid and turned off), `send: false`, bar colours, custom icons, and another plugin wiping packs with the old one-pack method. -- **Life cycle:** `/blueminimap reload`, `/bluemap reload`, a full `/reload`, server restarts, saved settings and quick join/quits. +- **Life cycle:** `/bluemapmini reload`, `/bluemap reload`, a full `/reload`, server restarts, saved settings and quick join/quits. - **Bad data:** corrupt tiles, a wrong web root, an unreachable webserver and the far edge of the world. - **Other setups:** the action bar channel, the HTTP source, and command back-off from another plugin's `plugin.yml` commands. **Also passed:** - **SQL storage:** on 26.3, tiles held in SQLite through the HTTP source matched the same world rendered to files on all 1024 cells. -- **Startup:** BlueMap loaded on all 8 of 8 restarts of a 26.3 server with BlueMinimap installed. +- **Startup:** BlueMap loaded on all 8 of 8 restarts of a 26.3 server with BlueMapMini installed. - **Game code:** the Minecraft 26.1.2, 26.2 and 26.3 client code loads the generated pack and fonts, with the game's advances matching this project's for all 18,944 glyphs, the clock pictures and fixed-width time digits included. The 26.1, 26.1.1 and 26.1.2 clients all use resource pack format 84, the pack's minimum. **20 moving players, one minute, on real terrain.** 26.3 is this release, with themes and the clock; 26.1.2 and 26.2 were measured on the build just before them: @@ -195,7 +185,7 @@ These ran on a shared machine with other test servers running, so tick times var - ZigZag loaded alongside the pack in a client. It overlaps only on the pink boss bar textures, which this pack replaces. - A Bedrock join, including Floodgate detection through `paper-plugin.yml`'s classpath sharing, MySQL or PostgreSQL storage, and back-off from another plugin's Brigadier commands. -To check a real client, join as an op and run `/blueminimap debug pattern`. You should see a sharp colour gradient with a white border and no bar behind it. +To check a real client, join as an op and run `/bluemapmini debug pattern`. You should see a sharp colour gradient with a white border and no bar behind it. ## Building diff --git a/build.gradle.kts b/build.gradle.kts index d8476b3..425a366 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } group = "com.extantape" -version = "0.2.1" +version = "0.3.0" java { toolchain.languageVersion.set(JavaLanguageVersion.of(25)) @@ -52,6 +52,6 @@ tasks.test { } tasks.jar { - archiveBaseName.set("BlueMinimap") + archiveBaseName.set("BlueMapMini") from("LICENSE") } diff --git a/docs/26x-audit.md b/docs/26x-audit.md index 8a17715..2979e93 100644 --- a/docs/26x-audit.md +++ b/docs/26x-audit.md @@ -1,6 +1,6 @@ # 26.x audit -BlueMinimap is a Paper plugin for Paper 26.1 and newer only: `paper-plugin.yml`, `api-version: '26.1'`, Java 25, and the Paper 26.1.2 API at compile time. This note records what changed when 1.21.11 support was dropped and which newer Paper features were checked. Checked against docs.papermc.io on 2026-11-07. +BlueMapMini is a Paper plugin for Paper 26.1 and newer only: `paper-plugin.yml`, `api-version: '26.1'`, Java 25, and the Paper 26.1.2 API at compile time. This note records what changed when 1.21.11 support was dropped and which newer Paper features were checked. Checked against docs.papermc.io on 2026-11-07. ## What changed @@ -16,7 +16,7 @@ BlueMinimap is a Paper plugin for Paper 26.1 and newer only: `paper-plugin.yml`, Paper has no 26.1.0 build. Its 26.1 line is 26.1.1 (alpha builds only) and 26.1.2 (stable), so "26.1" in practice means 26.1.2. BlueMap 5.29 itself declares `api-version: 26.1.1`. -**`paper-plugin.yml`.** Paper still marks Paper plugins experimental, and its docs don't say whether one can use a `plugin.yml` plugin's classes. BlueMap is one, so this was tested rather than assumed. BlueMap is declared as a required server dependency that loads first with `join-classpath: true`. Floodgate is declared the same way but optional, because the plugin finds it by reflection. There is no `commands` section: the commands were already Brigadier, registered through `LifecycleEvents.COMMANDS`. Paper plugins get their own classloader, so other plugins can't reach BlueMinimap's classes. None need to. +**`paper-plugin.yml`.** Paper still marks Paper plugins experimental, and its docs don't say whether one can use a `plugin.yml` plugin's classes. BlueMap is one, so this was tested rather than assumed. BlueMap is declared as a required server dependency that loads first with `join-classpath: true`. Floodgate is declared the same way but optional, because the plugin finds it by reflection. There is no `commands` section: the commands were already Brigadier, registered through `LifecycleEvents.COMMANDS`. Paper plugins get their own classloader, so other plugins can't reach BlueMapMini's classes. None need to. **Java 25** found one real compile error: a cache record named `Entry` clashed with `LinkedHashMap.Entry` inside an anonymous subclass. It's renamed to `CachedTile`. @@ -46,10 +46,10 @@ All on 2026-11-07, with BlueMap 5.29. The 31 unit tests pass on Java 25. The tes | Load, 20 players for a minute | 9/9 | 9/9 | 9/9 | | `public-url` and the hosted-pack check | | | 36/36 | | BlueMap on SQLite through the HTTP source | | | 1024/1024 cells | -| BlueMap starting next to BlueMinimap | | | 8/8 starts | +| BlueMap starting next to BlueMapMini | | | 8/8 starts | -The live suite covers BlueMap's classes being reachable from the Paper plugin (tiles, markers, hidden players), commands and their back-off, `/blueminimap reload`, `/bluemap reload` and a full `/reload`. +The live suite covers BlueMap's classes being reachable from the Paper plugin (tiles, markers, hidden players), commands and their back-off, `/bluemapmini reload`, `/bluemap reload` and a full `/reload`. **Mocked or not tested:** the client is a protocol bot speaking 1.21.11 through ViaBackwards, not a real 26.x client. Magic's pack call is simulated with the same Bukkit method. Floodgate was not installed, so the optional `join-classpath` for it is untested. Paper 26.1.1, which only had alpha builds, was not tested. -**Found along the way:** `/blueminimap debug dump` could finish after the plugin was disabled and then try to schedule its reply, which threw an error. It now checks first, as frame building already did. +**Found along the way:** `/bluemapmini debug dump` could finish after the plugin was disabled and then try to schedule its reply, which threw an error. It now checks first, as frame building already did. diff --git a/docs/decisions.md b/docs/decisions.md index 23e7716..7643bf2 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -20,3 +20,7 @@ Owner decisions for BlueMapHUD, newest first. | 2026-11-07 | Add `hud.default-mode: map\|coords` to `config.yml`, defaulting to `map`. | A server replacing a coordinates plugin can start new players on coordinates only. A player's own `/hud mode` choice always wins. | | 2026-11-06 | Add a coordinates-only mode (`/hud mode coords`) in the same single boss bar. | Players can keep coordinates without the map, so a server doesn't need a separate coordinates plugin. | - **Name (2026-11-08, owner):** BlueMapHUD is renamed BlueMinimap, one word in every place: repo, plugin name, jar, package, admin command and prose, described as "a BlueMap minimap and coordinates HUD for Paper, rendered in game", an add-on to BlueMap. Released as 0.2.0 together with HouseRules 0.2.0. Identifiers players' data depends on keep their old values for good: the saved-settings keys `bluemaphud:settings` and `bluemaphud:theme`, and the pack ID from `bluemaphud:pack`. Old commands and permissions work for one release; for default-on permissions a "no" on either name wins, so children's groups that were stopped from sharing stay stopped. With HouseRules older than 0.2, `/hud share` is turned off (fail closed). + +## 2026-11-14 + +- **Name (owner, D194, D196):** the plugin is renamed BlueMapMini, so it starts with BlueMap like BlueMapAuth and the other BlueMap add-ons. Released as 0.3.0. The owner asked that no old names be kept, so the Java package, commands, permissions, pack ID, player settings key and folder all use the new name, with no aliases or copies. Sharing stays off until HouseRules is 0.5.0, which hooks the new share event, so shares can never skip chat circles. diff --git a/docs/releases/v0.2.0.md b/docs/releases/v0.2.0.md index 733336f..6232c64 100644 --- a/docs/releases/v0.2.0.md +++ b/docs/releases/v0.2.0.md @@ -9,4 +9,4 @@ This is an early 0.x release. It has passed bot tests on throwaway servers, but - The pack is now `plugins/BlueMinimap/pack/blueminimap-pack.zip`, and its contents changed, so its SHA-1 changed. If you host it yourself, upload the new file. Players download it once. - Players keep their HUD settings: they're stored under the same keys as before. - **Deprecated, removed in the next release:** `/bmhud`, `/bluemaphud:map`, `/bluemaphud:hud` and the `bluemaphud.*` permissions. For permissions that are on by default, a "no" on either name wins, so a group you stopped from sharing stays stopped. Differences between the old and new names are logged once per player. -- Changed outright: the plugin, jar and folder are `BlueMinimap`, the admin command is `/blueminimap`, and the share event is `com.extantape.blueminimap.api.CoordinateShareEvent` (same methods). +- Changed outright: the plugin, jar and folder are `BlueMinimap`, the admin command is `/blueminimap`, and the share event is `com.extantape.bluemapmini.api.CoordinateShareEvent` (same methods). diff --git a/docs/releases/v0.3.0.md b/docs/releases/v0.3.0.md new file mode 100644 index 0000000..4d1da1e --- /dev/null +++ b/docs/releases/v0.3.0.md @@ -0,0 +1,15 @@ +A new name (D194): BlueMapMini starts with BlueMap, like the other BlueMap add-ons. How it works hasn't changed. As the owner asked (D196), it keeps no old names: no old commands, permissions or folder copy. + +## Installing over the previous version + +With the server stopped: +1. Rename its plugin folder to `plugins/BlueMapMini`. +2. In LuckPerms, move every node of the plugin's old permissions to the matching `bluemapmini.*` node, in every group and for every player. Most are on by default, so a group that had sharing turned off must have `bluemapmini.share.send` (and `.share.receive`) set to false, or it can share again. +3. Install Mayor 0.5.0 at the same time. Sharing follows Mayor's chat rules: until Mayor 0.5.0 or newer is running, `/hud share` stays off, so shares can't skip chat circles. A server without chat rules can set `share.require-mayor: false`. +4. If you host the pack yourself, upload the rebuilt `plugins/BlueMapMini/pack/bluemapmini-pack.zip`. + +Players' HUD settings start fresh once, and clients download the pack once more, because both were stored under the old name. + +## Tested + +Unit tests pass, including sharing staying off without Mayor, and with a Mayor older than 0.5.0. diff --git a/docs/test-audit.md b/docs/test-audit.md index 1ebfcb5..ec2d33a 100644 --- a/docs/test-audit.md +++ b/docs/test-audit.md @@ -19,17 +19,15 @@ The README's Testing section already lists what the live suite covers, check by | Promise | Covered by | | --- | --- | -| **Shares reach only players in the sender's world group who can see the sender, have `blueminimap.share.receive`, and haven't turned shares off** | live `suite.js` share group: one person, world group with the Nether, another world excluded, shares off, receive and send permissions, players hidden from the sender | -| **A rules plugin (HouseRules) can remove recipients or cancel a share** | live share group (stand-in rules plugin); live `houserules.js` with the real HouseRules 0.2.0: shares stay inside circles, a no-circle sender in a circle-only world sends nothing | -| **Fail closed with an older HouseRules: sharing off, admin told** | live `houserules.js` with the real HouseRules 0.1.1; unit `HouseRulesGuardTest` (including an unreadable version) | -| **A server's "no" under an old permission name still stops sharing** | live share group "An old bluemaphud.share.receive/send false still stops…"; unit `PermsTest` (deny wins, admin grant wins, no noise when the old name changed nothing) | +| **Shares reach only players in the sender's world group who can see the sender, have `bluemapmini.share.receive`, and haven't turned shares off** | live `suite.js` share group: one person, world group with the Nether, another world excluded, shares off, receive and send permissions, players hidden from the sender | +| **A rules plugin (Mayor) can remove recipients or cancel a share** | live share group (stand-in rules plugin); live `mayor.js` with the real Mayor 0.2.0: shares stay inside circles, a no-circle sender in a circle-only world sends nothing | +| **Fail closed with an older Mayor: sharing off, admin told** | live `mayor.js` with the real Mayor 0.1.1; unit `MayorGuardTest` (including an unreadable version) | | Sharing limits: cooldown, console log, `share.enabled: false` | live share group | -| Other players hidden by vanish, `hidePlayer`, spectator, invisibility, BlueMap, radius, other dimensions, `blueminimap.seeplayers` | live players group | +| Other players hidden by vanish, `hidePlayer`, spectator, invisibility, BlueMap, radius, other dimensions, `bluemapmini.seeplayers` | live players group | | Players keep their HUD settings across the rename | unit `PlayerSettingsTest` (settings saved under the original keys still load) | -| Upgrade from BlueMapHUD: folder copied, never overwritten | unit `MigrationTest` | | Everything else in the README (map accuracy, icons, clock, themes, one boss bar, updates, pack handling, life cycle, bad data, other setups) | the README's Testing list, check by check, in `test/live/suite.js`, `packurl.js`, `storage.js` and `backoff.js` | -**Gaps added this audit:** none new. The old-name deny checks, the HouseRules joint test and the guard tests were added with 0.2.0 earlier the same day, and all passed on Paper 26.1.2, 26.2 and 26.3. +**Gaps added this audit:** none new. The old-name deny checks, the Mayor joint test and the guard tests were added with 0.2.0 earlier the same day, and all passed on Paper 26.1.2, 26.2 and 26.3. **Skipped, with reasons:** - Pressing the buttons in the `/hud share` dialog: the bot's protocol library can't click a dialog button. The buttons call the same code `/hud share ` and `/hud share everyone` test. diff --git a/settings.gradle.kts b/settings.gradle.kts index 4694de7..195011d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,4 @@ -rootProject.name = "BlueMinimap" +rootProject.name = "BlueMapMini" // Test-only plugins for the live tests in test/live. They're never shipped. include("live-test-helper", "live-test-conflict") diff --git a/src/main/java/com/extantape/blueminimap/BlueMinimapPlugin.java b/src/main/java/com/extantape/bluemapmini/BlueMapMiniPlugin.java similarity index 86% rename from src/main/java/com/extantape/blueminimap/BlueMinimapPlugin.java rename to src/main/java/com/extantape/bluemapmini/BlueMapMiniPlugin.java index c3eedcd..0b45caa 100644 --- a/src/main/java/com/extantape/blueminimap/BlueMinimapPlugin.java +++ b/src/main/java/com/extantape/bluemapmini/BlueMapMiniPlugin.java @@ -1,25 +1,25 @@ -package com.extantape.blueminimap; +package com.extantape.bluemapmini; -import com.extantape.blueminimap.command.HudCommands; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.hud.FrameBuilder; -import com.extantape.blueminimap.hud.HudManager; -import com.extantape.blueminimap.hud.HudSession; -import com.extantape.blueminimap.markers.MarkerService; -import com.extantape.blueminimap.pack.PackBuilder; -import com.extantape.blueminimap.pack.PackService; -import com.extantape.blueminimap.render.HudFonts; -import com.extantape.blueminimap.render.IconSet; -import com.extantape.blueminimap.render.MapComposer; -import com.extantape.blueminimap.share.ShareMenu; -import com.extantape.blueminimap.share.ShareService; -import com.extantape.blueminimap.theme.Theme; -import com.extantape.blueminimap.theme.ThemeSet; -import com.extantape.blueminimap.tiles.FileTileSource; -import com.extantape.blueminimap.tiles.GridCache; -import com.extantape.blueminimap.tiles.HttpTileSource; -import com.extantape.blueminimap.tiles.TileSource; -import com.extantape.blueminimap.tiles.TileStore; +import com.extantape.bluemapmini.command.HudCommands; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.hud.FrameBuilder; +import com.extantape.bluemapmini.hud.HudManager; +import com.extantape.bluemapmini.hud.HudSession; +import com.extantape.bluemapmini.markers.MarkerService; +import com.extantape.bluemapmini.pack.PackBuilder; +import com.extantape.bluemapmini.pack.PackService; +import com.extantape.bluemapmini.render.HudFonts; +import com.extantape.bluemapmini.render.IconSet; +import com.extantape.bluemapmini.render.MapComposer; +import com.extantape.bluemapmini.share.ShareMenu; +import com.extantape.bluemapmini.share.ShareService; +import com.extantape.bluemapmini.theme.Theme; +import com.extantape.bluemapmini.theme.ThemeSet; +import com.extantape.bluemapmini.tiles.FileTileSource; +import com.extantape.bluemapmini.tiles.GridCache; +import com.extantape.bluemapmini.tiles.HttpTileSource; +import com.extantape.bluemapmini.tiles.TileSource; +import com.extantape.bluemapmini.tiles.TileStore; import de.bluecolored.bluemap.api.BlueMapAPI; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import net.kyori.adventure.text.Component; @@ -46,7 +46,7 @@ import java.util.function.Consumer; import java.util.logging.Level; -public final class BlueMinimapPlugin extends JavaPlugin implements Listener { +public final class BlueMapMiniPlugin extends JavaPlugin implements Listener { /** Runs after other plugins, so the command name chains can see what they took. */ private static final int COMMANDS_PRIORITY = 1000; private static final long PACK_SEND_DELAY_TICKS = 20; @@ -65,17 +65,7 @@ public final class BlueMinimapPlugin extends JavaPlugin implements Listener { @Override public void onEnable() { - Perms.logTo(line -> getLogger().warning(line)); java.nio.file.Path folder = getDataFolder().toPath(); - String moved = Migration.copyIfMissing(folder.resolveSibling("BlueMapHUD"), folder); - if (moved != null) { - getLogger().warning(moved); - try { // The old pack file would only confuse whoever hosts the pack; the new one is built below. - java.nio.file.Files.deleteIfExists(folder.resolve("pack/bluemaphud-pack.zip")); - } catch (java.io.IOException e) { - getLogger().warning("Couldn't remove the copied old pack file: " + e.getMessage()); - } - } saveDefaultConfig(); config = HudConfig.from(getConfig()); packs = new PackService(this, getDataFolder().toPath().resolve("pack")); @@ -161,7 +151,7 @@ public void explainIfNoMap(Player player) { /** Coordinates need the pack but not a map, so this is all that can stop them appearing. */ public void explainIfNoPack(Player player) { if (!packs.ready(player)) { - player.sendMessage(Component.text("Your client hasn't loaded the BlueMinimap resource pack yet.", NamedTextColor.YELLOW)); + player.sendMessage(Component.text("Your client hasn't loaded the BlueMapMini resource pack yet.", NamedTextColor.YELLOW)); } } @@ -308,13 +298,13 @@ public void onSwapHands(PlayerSwapHandItemsEvent event) { if (!player.isSneaking() || hud.isBedrock(player)) return; HudSession session = hud.session(player); - if (config.hud().quickHideGesture() && player.getLocation().getPitch() >= LOOK_DOWN_PITCH && com.extantape.blueminimap.Perms.has(player, "blueminimap.use")) { + if (config.hud().quickHideGesture() && player.getLocation().getPitch() >= LOOK_DOWN_PITCH && com.extantape.bluemapmini.Perms.has(player, "bluemapmini.use")) { event.setCancelled(true); session.settings().enabled = !session.settings().enabled; hud.saveSettings(player, session); return; } - if (config.fullscreen().sneakSwapToggle() && config.fullscreen().enabled() && com.extantape.blueminimap.Perms.has(player, "blueminimap.fullscreen")) { + if (config.fullscreen().sneakSwapToggle() && config.fullscreen().enabled() && com.extantape.bluemapmini.Perms.has(player, "bluemapmini.fullscreen")) { event.setCancelled(true); toggleFullscreen(player); } diff --git a/src/main/java/com/extantape/bluemapmini/Perms.java b/src/main/java/com/extantape/bluemapmini/Perms.java new file mode 100644 index 0000000..07c9129 --- /dev/null +++ b/src/main/java/com/extantape/bluemapmini/Perms.java @@ -0,0 +1,12 @@ +package com.extantape.bluemapmini; + +import org.bukkit.permissions.Permissible; + +/** Permission checks for BlueMapMini's own nodes. */ +public final class Perms { + private Perms() {} + + public static boolean has(Permissible who, String node) { + return who.hasPermission(node); + } +} diff --git a/src/main/java/com/extantape/blueminimap/api/CoordinateShareEvent.java b/src/main/java/com/extantape/bluemapmini/api/CoordinateShareEvent.java similarity index 93% rename from src/main/java/com/extantape/blueminimap/api/CoordinateShareEvent.java rename to src/main/java/com/extantape/bluemapmini/api/CoordinateShareEvent.java index 76dc04e..349fe53 100644 --- a/src/main/java/com/extantape/blueminimap/api/CoordinateShareEvent.java +++ b/src/main/java/com/extantape/bluemapmini/api/CoordinateShareEvent.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.api; +package com.extantape.bluemapmini.api; import org.bukkit.World; import org.bukkit.entity.Player; @@ -11,10 +11,10 @@ /** * Fired on the main thread just before a player's coordinates are shared, so that another plugin, such as a * server's chat rules, can decide who may receive them. Remove recipients to narrow the share, or cancel it - * to send nothing. Players who turned shares off, or lack {@code blueminimap.share.receive}, are already gone. + * to send nothing. Players who turned shares off, or lack {@code bluemapmini.share.receive}, are already gone. * *

When {@code share.candidates} is {@code all-online}, the recipients can include players in other - * worlds, and BlueMinimap only does that while at least one plugin listens to this event. + * worlds, and BlueMapMini only does that while at least one plugin listens to this event. */ public final class CoordinateShareEvent extends Event implements Cancellable { private static final HandlerList HANDLERS = new HandlerList(); diff --git a/src/main/java/com/extantape/blueminimap/command/HudCommands.java b/src/main/java/com/extantape/bluemapmini/command/HudCommands.java similarity index 90% rename from src/main/java/com/extantape/blueminimap/command/HudCommands.java rename to src/main/java/com/extantape/bluemapmini/command/HudCommands.java index dfbf05f..5df47e8 100644 --- a/src/main/java/com/extantape/blueminimap/command/HudCommands.java +++ b/src/main/java/com/extantape/bluemapmini/command/HudCommands.java @@ -1,13 +1,13 @@ -package com.extantape.blueminimap.command; +package com.extantape.bluemapmini.command; -import com.extantape.blueminimap.BlueMinimapPlugin; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.hud.HudManager; -import com.extantape.blueminimap.hud.HudSession; -import com.extantape.blueminimap.hud.PlayerSettings; -import com.extantape.blueminimap.share.ShareService; -import com.extantape.blueminimap.theme.Theme; -import com.extantape.blueminimap.theme.ThemeSet; +import com.extantape.bluemapmini.BlueMapMiniPlugin; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.hud.HudManager; +import com.extantape.bluemapmini.hud.HudSession; +import com.extantape.bluemapmini.hud.PlayerSettings; +import com.extantape.bluemapmini.share.ShareService; +import com.extantape.bluemapmini.theme.Theme; +import com.extantape.bluemapmini.theme.ThemeSet; import com.mojang.brigadier.Command; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; @@ -30,21 +30,19 @@ import java.util.Set; import java.util.function.BiConsumer; -/** Registers /map, /hud and /blueminimap, backing off to the next name when one is already taken. */ +/** Registers /map, /hud and /bluemapmini, backing off to the next name when one is already taken. */ public final class HudCommands { - private final BlueMinimapPlugin plugin; + private final BlueMapMiniPlugin plugin; /** Names chosen at startup. Data pack reloads rebuild the tree and must not back off from themselves. */ private String claimedMap; private String claimedHud; - public HudCommands(BlueMinimapPlugin plugin) { + public HudCommands(BlueMapMiniPlugin plugin) { this.plugin = plugin; } public void register(Commands commands, HudConfig config) { - commands.register(adminTree("blueminimap").build(), "BlueMinimap help and admin commands", List.of()); - // The old name, for one release (0.2.x) after the rename from BlueMapHUD. Logged at startup. - commands.register(adminTree("bmhud").build(), "Old name for /blueminimap. Goes in the next release.", List.of()); + commands.register(adminTree("bluemapmini").build(), "BlueMapMini help and admin commands", List.of()); registerShortNames(commands, config); } @@ -55,7 +53,7 @@ private LiteralArgumentBuilder adminTree(String label) { .then(hudTree(Commands.literal("hud"))) .then(Commands.literal("reload").requires(HudCommands::isAdmin).executes(ctx -> { plugin.reload(); - return reply(ctx.getSource().getSender(), "BlueMinimap reloaded. Command names change after a restart."); + return reply(ctx.getSource().getSender(), "BlueMapMini reloaded. Command names change after a restart."); })) .then(Commands.literal("debug").requires(HudCommands::isAdmin) .executes(ctx -> reply(ctx.getSource().getSender(), plugin.debugLine())) @@ -73,12 +71,9 @@ private void registerShortNames(Commands commands, HudConfig config) { claimedMap = claim(commands, claimedMap != null ? List.of(claimedMap) : config.commands().mapNames(), "Open the fullscreen map", true, firstTime); claimedHud = claim(commands, claimedHud != null ? List.of(claimedHud) : config.commands().hudNames(), "Control the minimap", false, firstTime); // Namespaced names always exist, so a taken short name never locks anyone out. - addNamespaced(commands, "map", claimedMap, mapTree(Commands.literal("blueminimap:map"))); - addNamespaced(commands, "hud", claimedHud, hudTree(Commands.literal("blueminimap:hud"))); - addNamespaced(commands, "map", claimedMap, mapTree(Commands.literal("bluemaphud:map"))); // old names, 0.2.x only - addNamespaced(commands, "hud", claimedHud, hudTree(Commands.literal("bluemaphud:hud"))); - plugin.getLogger().info("/bmhud, /bluemaphud:map and /bluemaphud:hud are the old names for /blueminimap, /blueminimap:map and /blueminimap:hud. They still work in 0.2.x but go in the next release."); - plugin.getLogger().info("Commands: fullscreen map is " + describe(claimedMap, "/blueminimap map") + ", minimap is " + describe(claimedHud, "/blueminimap hud") + "."); + addNamespaced(commands, "map", claimedMap, mapTree(Commands.literal("bluemapmini:map"))); + addNamespaced(commands, "hud", claimedHud, hudTree(Commands.literal("bluemapmini:hud"))); + plugin.getLogger().info("Commands: fullscreen map is " + describe(claimedMap, "/bluemapmini map") + ", minimap is " + describe(claimedHud, "/bluemapmini hud") + "."); } private String claim(Commands commands, List names, String description, boolean isMap, boolean checkLegacy) { @@ -107,11 +102,11 @@ private static String describe(String claimed, String fallback) { } private static boolean isAdmin(CommandSourceStack source) { - return com.extantape.blueminimap.Perms.has(source.getSender(), "blueminimap.admin"); + return com.extantape.bluemapmini.Perms.has(source.getSender(), "bluemapmini.admin"); } private LiteralArgumentBuilder mapTree(LiteralArgumentBuilder root) { - return root.requires(source -> com.extantape.blueminimap.Perms.has(source.getSender(), "blueminimap.fullscreen")) + return root.requires(source -> com.extantape.bluemapmini.Perms.has(source.getSender(), "bluemapmini.fullscreen")) .executes(player((p, s) -> plugin.toggleFullscreen(p))) .then(Commands.literal("zoom").then(Commands.argument("level", StringArgumentType.word()) .suggests((ctx, builder) -> suggestZoom(builder)) @@ -128,7 +123,7 @@ private LiteralArgumentBuilder mapTree(LiteralArgumentBuilde } private LiteralArgumentBuilder hudTree(LiteralArgumentBuilder root) { - return root.requires(source -> com.extantape.blueminimap.Perms.has(source.getSender(), "blueminimap.use")) + return root.requires(source -> com.extantape.bluemapmini.Perms.has(source.getSender(), "bluemapmini.use")) .executes(player((p, s) -> setEnabled(p, s, !s.settings().enabled))) .then(Commands.literal("on").executes(player((p, s) -> setEnabled(p, s, true)))) .then(Commands.literal("off").executes(player((p, s) -> setEnabled(p, s, false)))) @@ -265,7 +260,7 @@ private void listThemes(Player player, HudSession session) { boolean mine = i == current; Component name = Component.text(theme.name(), mine ? NamedTextColor.WHITE : NamedTextColor.AQUA) .decoration(TextDecoration.UNDERLINED, !mine) - .clickEvent(ClickEvent.runCommand("/blueminimap:hud theme " + theme.id())) + .clickEvent(ClickEvent.runCommand("/bluemapmini:hud theme " + theme.id())) .hoverEvent(HoverEvent.showText(Component.text(mine ? "Your theme" : "Switch to " + theme.name()))); line = line.append(name).append(Component.text(mine ? " (yours)" : "", NamedTextColor.GRAY)) .append(Component.text(i + 1 < themes.size() ? ", " : "", NamedTextColor.GRAY)); @@ -359,12 +354,12 @@ private int withPlayer(CommandContext ctx, BiConsumer. Sneak + F also opens it.")); sender.sendMessage(Component.text("Minimap: on, off, mode map or coords, zoom, size, offset, corner, theme, hide and show (coords, players, markers, clock, shares).")); sender.sendMessage(Component.text("Share your coordinates: /hud share, /hud share or /hud share everyone.")); - if (com.extantape.blueminimap.Perms.has(sender, "blueminimap.admin")) { - sender.sendMessage(Component.text("Admin: /blueminimap reload, debug, debug dump, debug pattern, pack export.")); + if (com.extantape.bluemapmini.Perms.has(sender, "bluemapmini.admin")) { + sender.sendMessage(Component.text("Admin: /bluemapmini reload, debug, debug dump, debug pattern, pack export.")); sender.sendMessage(Component.text(hud.debugLine())); } return Command.SINGLE_SUCCESS; diff --git a/src/main/java/com/extantape/blueminimap/config/HudConfig.java b/src/main/java/com/extantape/bluemapmini/config/HudConfig.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/config/HudConfig.java rename to src/main/java/com/extantape/bluemapmini/config/HudConfig.java index f58174a..3ada622 100644 --- a/src/main/java/com/extantape/blueminimap/config/HudConfig.java +++ b/src/main/java/com/extantape/bluemapmini/config/HudConfig.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.config; +package com.extantape.bluemapmini.config; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; @@ -27,7 +27,7 @@ public enum ShareScope { ALL_ONLINE } - public record Share(boolean enabled, ShareScope candidates, int cooldownSeconds, boolean log) {} + public record Share(boolean enabled, ShareScope candidates, int cooldownSeconds, boolean log, boolean requireMayor) {} public record Tiles(String source, String webRoot, String httpUrl, int refreshMinutes, int cacheChunks, Map mapOverrides) {} @@ -121,7 +121,7 @@ public static HudConfig from(FileConfiguration c) { Pack pack = new Pack( c.getBoolean("pack.send", true), c.getBoolean("pack.required", true), - c.getString("pack.kick-message", "This server needs the BlueMinimap resource pack."), + c.getString("pack.kick-message", "This server needs the BlueMapMini resource pack."), c.getString("pack.prompt", ""), c.getInt("pack.port", 8164), c.getString("pack.bind", "").trim(), @@ -137,7 +137,8 @@ public static HudConfig from(FileConfiguration c) { c.getBoolean("share.enabled", true), "all-online".equalsIgnoreCase(c.getString("share.candidates", "world-group")) ? ShareScope.ALL_ONLINE : ShareScope.WORLD_GROUP, clamp(c.getInt("share.cooldown-seconds", 30), 0, 3600), - c.getBoolean("share.log", true)); + c.getBoolean("share.log", true), + c.getBoolean("share.require-mayor", true)); return new HudConfig(tiles, hud, commands, fullscreen, players, markers, pack, share); } diff --git a/src/main/java/com/extantape/blueminimap/hud/FrameBuilder.java b/src/main/java/com/extantape/bluemapmini/hud/FrameBuilder.java similarity index 94% rename from src/main/java/com/extantape/blueminimap/hud/FrameBuilder.java rename to src/main/java/com/extantape/bluemapmini/hud/FrameBuilder.java index 419afd5..0916ae8 100644 --- a/src/main/java/com/extantape/blueminimap/hud/FrameBuilder.java +++ b/src/main/java/com/extantape/bluemapmini/hud/FrameBuilder.java @@ -1,16 +1,16 @@ -package com.extantape.blueminimap.hud; - -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.markers.MarkerService; -import com.extantape.blueminimap.render.FontLayout; -import com.extantape.blueminimap.render.HudFonts; -import com.extantape.blueminimap.render.HudIcon; -import com.extantape.blueminimap.render.MapComposer; -import com.extantape.blueminimap.render.MapFrame; -import com.extantape.blueminimap.render.ReadoutFont; -import com.extantape.blueminimap.render.TinyFont; -import com.extantape.blueminimap.theme.Theme; -import com.extantape.blueminimap.theme.ThemeSet; +package com.extantape.bluemapmini.hud; + +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.markers.MarkerService; +import com.extantape.bluemapmini.render.FontLayout; +import com.extantape.bluemapmini.render.HudFonts; +import com.extantape.bluemapmini.render.HudIcon; +import com.extantape.bluemapmini.render.MapComposer; +import com.extantape.bluemapmini.render.MapFrame; +import com.extantape.bluemapmini.render.ReadoutFont; +import com.extantape.bluemapmini.render.TinyFont; +import com.extantape.bluemapmini.theme.Theme; +import com.extantape.bluemapmini.theme.ThemeSet; import net.kyori.adventure.text.Component; import java.util.Arrays; diff --git a/src/main/java/com/extantape/blueminimap/hud/HudManager.java b/src/main/java/com/extantape/bluemapmini/hud/HudManager.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/hud/HudManager.java rename to src/main/java/com/extantape/bluemapmini/hud/HudManager.java index b58e209..6a1de07 100644 --- a/src/main/java/com/extantape/blueminimap/hud/HudManager.java +++ b/src/main/java/com/extantape/bluemapmini/hud/HudManager.java @@ -1,7 +1,7 @@ -package com.extantape.blueminimap.hud; +package com.extantape.bluemapmini.hud; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.pack.PackService; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.pack.PackService; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; import de.bluecolored.bluemap.api.BlueMapWorld; @@ -46,7 +46,7 @@ public final class HudManager { private final Map worldMaps = new HashMap<>(); private final Map bedrock = new ConcurrentHashMap<>(); private final ExecutorService builders = Executors.newFixedThreadPool(2, runnable -> { - Thread thread = new Thread(runnable, "BlueMinimap-build"); + Thread thread = new Thread(runnable, "BlueMapMini-build"); thread.setDaemon(true); thread.setPriority(Thread.NORM_PRIORITY - 1); return thread; @@ -183,7 +183,7 @@ private void tick() { String mapId = mapFor(player.getWorld()); boolean hasMap = !mapId.isEmpty() || session.pattern; - boolean canFull = hasMap && session.fullscreen && com.extantape.blueminimap.Perms.has(player, "blueminimap.fullscreen") && config.fullscreen().enabled(); + boolean canFull = hasMap && session.fullscreen && com.extantape.bluemapmini.Perms.has(player, "bluemapmini.fullscreen") && config.fullscreen().enabled(); if (!shouldShow(player, session, hasMap, canFull)) { hide(player, session); continue; @@ -200,7 +200,7 @@ private boolean shouldShow(Player player, HudSession session, boolean hasMap, bo boolean coordsOnly = session.settings.coordsOnly && !session.pattern; if (!hasMap && !coordsOnly) return false; // A dimension BlueMap doesn't map. Coordinates don't need one. if (isBedrock(player) || !packs.ready(player)) return false; - if (!com.extantape.blueminimap.Perms.has(player, "blueminimap.use")) return false; + if (!com.extantape.bluemapmini.Perms.has(player, "bluemapmini.use")) return false; if (canFull) return true; // Fullscreen is an explicit request, and it works while the minimap is off. if (!session.settings.enabled) return false; if (session.fullscreen && config.hud().hideWhileFullscreen() && !coordsOnly) return false; @@ -253,7 +253,7 @@ private int clockMinutes(World world, PlayerSettings settings) { } private int[] visiblePlayers(Player viewer, HudSession session, Location at) { - if (!session.settings.showPlayers || !com.extantape.blueminimap.Perms.has(viewer, "blueminimap.seeplayers")) return new int[0]; + if (!session.settings.showPlayers || !com.extantape.bluemapmini.Perms.has(viewer, "bluemapmini.seeplayers")) return new int[0]; HudConfig.Players rules = config.players(); BlueMapAPI api = rules.hideBlueMapHidden() ? BlueMapAPI.getInstance().orElse(null) : null; double radiusSquared = (double) rules.radius() * rules.radius(); diff --git a/src/main/java/com/extantape/blueminimap/hud/HudSession.java b/src/main/java/com/extantape/bluemapmini/hud/HudSession.java similarity index 96% rename from src/main/java/com/extantape/blueminimap/hud/HudSession.java rename to src/main/java/com/extantape/bluemapmini/hud/HudSession.java index 600e6fe..ca12d8a 100644 --- a/src/main/java/com/extantape/blueminimap/hud/HudSession.java +++ b/src/main/java/com/extantape/bluemapmini/hud/HudSession.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.hud; +package com.extantape.bluemapmini.hud; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; diff --git a/src/main/java/com/extantape/blueminimap/hud/PlayerSettings.java b/src/main/java/com/extantape/bluemapmini/hud/PlayerSettings.java similarity index 96% rename from src/main/java/com/extantape/blueminimap/hud/PlayerSettings.java rename to src/main/java/com/extantape/bluemapmini/hud/PlayerSettings.java index d44577d..1a39f85 100644 --- a/src/main/java/com/extantape/blueminimap/hud/PlayerSettings.java +++ b/src/main/java/com/extantape/bluemapmini/hud/PlayerSettings.java @@ -1,15 +1,15 @@ -package com.extantape.blueminimap.hud; +package com.extantape.bluemapmini.hud; -import com.extantape.blueminimap.config.HudConfig; +import com.extantape.bluemapmini.config.HudConfig; import org.bukkit.NamespacedKey; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; /** One player's HUD choices, saved in their PersistentDataContainer. */ public final class PlayerSettings { - private static final NamespacedKey KEY = new NamespacedKey("bluemaphud", "settings"); + private static final NamespacedKey KEY = new NamespacedKey("bluemapmini", "settings"); /** The theme is a name, so it survives themes being added or removed. */ - private static final NamespacedKey THEME_KEY = new NamespacedKey("bluemaphud", "theme"); + private static final NamespacedKey THEME_KEY = new NamespacedKey("bluemapmini", "theme"); private static final int FORMAT = 3; /** Saved before the clock and shares existed. */ private static final int FORMAT_WITHOUT_CLOCK = 2; diff --git a/src/main/java/com/extantape/blueminimap/hud/Snapshot.java b/src/main/java/com/extantape/bluemapmini/hud/Snapshot.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/hud/Snapshot.java rename to src/main/java/com/extantape/bluemapmini/hud/Snapshot.java index d293198..8e5eaa9 100644 --- a/src/main/java/com/extantape/blueminimap/hud/Snapshot.java +++ b/src/main/java/com/extantape/bluemapmini/hud/Snapshot.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.hud; +package com.extantape.bluemapmini.hud; /** * Everything a frame needs, copied on the main thread so that background threads never touch Bukkit. diff --git a/src/main/java/com/extantape/blueminimap/markers/MarkerService.java b/src/main/java/com/extantape/bluemapmini/markers/MarkerService.java similarity index 95% rename from src/main/java/com/extantape/blueminimap/markers/MarkerService.java rename to src/main/java/com/extantape/bluemapmini/markers/MarkerService.java index 57aee57..0bb4345 100644 --- a/src/main/java/com/extantape/blueminimap/markers/MarkerService.java +++ b/src/main/java/com/extantape/bluemapmini/markers/MarkerService.java @@ -1,6 +1,6 @@ -package com.extantape.blueminimap.markers; +package com.extantape.bluemapmini.markers; -import com.extantape.blueminimap.config.HudConfig; +import com.extantape.bluemapmini.config.HudConfig; import de.bluecolored.bluemap.api.BlueMapAPI; import de.bluecolored.bluemap.api.BlueMapMap; import de.bluecolored.bluemap.api.markers.Marker; diff --git a/src/main/java/com/extantape/blueminimap/pack/PackBuilder.java b/src/main/java/com/extantape/bluemapmini/pack/PackBuilder.java similarity index 92% rename from src/main/java/com/extantape/blueminimap/pack/PackBuilder.java rename to src/main/java/com/extantape/bluemapmini/pack/PackBuilder.java index e681c1a..d82fa5b 100644 --- a/src/main/java/com/extantape/blueminimap/pack/PackBuilder.java +++ b/src/main/java/com/extantape/bluemapmini/pack/PackBuilder.java @@ -1,14 +1,14 @@ -package com.extantape.blueminimap.pack; +package com.extantape.bluemapmini.pack; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.render.FontLayout; -import com.extantape.blueminimap.render.HudFonts; -import com.extantape.blueminimap.render.HudIcon; -import com.extantape.blueminimap.render.IconSet; -import com.extantape.blueminimap.render.ReadoutFont; -import com.extantape.blueminimap.render.TinyFont; -import com.extantape.blueminimap.theme.Theme; -import com.extantape.blueminimap.theme.ThemeSet; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.render.FontLayout; +import com.extantape.bluemapmini.render.HudFonts; +import com.extantape.bluemapmini.render.HudIcon; +import com.extantape.bluemapmini.render.IconSet; +import com.extantape.bluemapmini.render.ReadoutFont; +import com.extantape.bluemapmini.render.TinyFont; +import com.extantape.bluemapmini.theme.Theme; +import com.extantape.bluemapmini.theme.ThemeSet; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -28,7 +28,7 @@ import java.util.zip.ZipOutputStream; /** - * Generates the resource pack in memory. Everything lives under the blueminimap namespace, apart from + * Generates the resource pack in memory. Everything lives under the bluemapmini namespace, apart from * the optional transparent boss bar textures. No shaders are involved. */ public final class PackBuilder { @@ -67,7 +67,7 @@ public static Built build(HudConfig config, HudFonts fonts, IconSet icons) throw private static byte[] packMeta() { JsonObject pack = new JsonObject(); - pack.addProperty("description", "BlueMinimap minimap"); + pack.addProperty("description", "BlueMapMini minimap"); pack.addProperty("min_format", MIN_FORMAT); pack.addProperty("max_format", MAX_FORMAT); JsonObject root = new JsonObject(); @@ -81,18 +81,18 @@ private static void addLayout(Map files, FontLayout layout, Icon int iconCells = FontLayout.paddedCells(layout.maxIconAscent(), 1, HudIcon.SIZE); int textCells = FontLayout.paddedCells(layout.maxTextAscent(), 1, TinyFont.HEIGHT); - files.put("assets/blueminimap/textures/font/" + name + "_runs.png", png(runSheet(runCells))); - files.put("assets/blueminimap/textures/font/" + name + "_icons.png", png(iconSheet(icons, iconCells))); - files.put("assets/blueminimap/textures/font/" + name + "_text.png", png(textSheet(textCells))); + files.put("assets/bluemapmini/textures/font/" + name + "_runs.png", png(runSheet(runCells))); + files.put("assets/bluemapmini/textures/font/" + name + "_icons.png", png(iconSheet(icons, iconCells))); + files.put("assets/bluemapmini/textures/font/" + name + "_text.png", png(textSheet(textCells))); int readoutCells = FontLayout.paddedCells(layout.maxReadoutAscent(), 1, ReadoutFont.HEIGHT); int plateCells = FontLayout.paddedCells(layout.maxPlateAscent(), 1, FontLayout.PLATE_HEIGHT); - files.put("assets/blueminimap/textures/font/" + name + "_readout.png", png(readoutSheet(readoutCells))); + files.put("assets/bluemapmini/textures/font/" + name + "_readout.png", png(readoutSheet(readoutCells))); // One plate sheet for each opacity the themes use. The colour comes from the frame. for (int v = 0; v < themes.plateOpacities().size(); v++) { - files.put("assets/blueminimap/textures/font/" + name + "_plate" + v + ".png", png(plateSheet(plateCells, themes.plateOpacities().get(v)))); + files.put("assets/bluemapmini/textures/font/" + name + "_plate" + v + ".png", png(plateSheet(plateCells, themes.plateOpacities().get(v)))); } int clockCells = FontLayout.paddedCells(layout.maxClockAscent(), 1, Theme.CLOCK_SIZE); - files.put("assets/blueminimap/textures/font/" + name + "_clock.png", png(clockSheet(themes, clockCells))); + files.put("assets/bluemapmini/textures/font/" + name + "_clock.png", png(clockSheet(themes, clockCells))); JsonArray providers = new JsonArray(); providers.add(spaceProvider()); @@ -123,7 +123,7 @@ private static void addLayout(Map files, FontLayout layout, Icon } JsonObject font = new JsonObject(); font.add("providers", providers); - files.put("assets/blueminimap/font/" + name + ".json", GSON.toJson(font).getBytes(StandardCharsets.UTF_8)); + files.put("assets/bluemapmini/font/" + name + ".json", GSON.toJson(font).getBytes(StandardCharsets.UTF_8)); } private static JsonObject spaceProvider() { @@ -141,7 +141,7 @@ private static JsonObject spaceProvider() { private static JsonObject bitmap(String file, int height, int ascent, String[] chars) { JsonObject provider = new JsonObject(); provider.addProperty("type", "bitmap"); - provider.addProperty("file", "blueminimap:font/" + file + ".png"); + provider.addProperty("file", "bluemapmini:font/" + file + ".png"); provider.addProperty("height", height); provider.addProperty("ascent", ascent); JsonArray rows = new JsonArray(); diff --git a/src/main/java/com/extantape/blueminimap/pack/PackService.java b/src/main/java/com/extantape/bluemapmini/pack/PackService.java similarity index 94% rename from src/main/java/com/extantape/blueminimap/pack/PackService.java rename to src/main/java/com/extantape/bluemapmini/pack/PackService.java index e752f08..d73a334 100644 --- a/src/main/java/com/extantape/blueminimap/pack/PackService.java +++ b/src/main/java/com/extantape/bluemapmini/pack/PackService.java @@ -1,6 +1,6 @@ -package com.extantape.blueminimap.pack; +package com.extantape.bluemapmini.pack; -import com.extantape.blueminimap.config.HudConfig; +import com.extantape.bluemapmini.config.HudConfig; import com.sun.net.httpserver.HttpServer; import net.kyori.adventure.resource.ResourcePackInfo; import net.kyori.adventure.resource.ResourcePackRequest; @@ -34,7 +34,7 @@ /** Saves, hosts and sends the pack, and keeps track of which players have it loaded. */ public final class PackService { /** Fixed, so that re-sending replaces this pack and never touches anyone else's. */ - public static final UUID PACK_ID = UUID.nameUUIDFromBytes("bluemaphud:pack".getBytes(StandardCharsets.UTF_8)); + public static final UUID PACK_ID = UUID.nameUUIDFromBytes("bluemapmini:pack".getBytes(StandardCharsets.UTF_8)); private static final long RESEND_DELAY_TICKS = 40; private final Plugin plugin; @@ -67,7 +67,7 @@ public boolean install(HudConfig.Pack config, PackBuilder.Built built) throws IO this.pack = built; Files.createDirectories(packFolder); Files.write(exportPath(), built.zip()); - servedPath = "/blueminimap-" + built.sha1Hex() + ".zip"; + servedPath = "/bluemapmini-" + built.sha1Hex() + ".zip"; servedBytes = built.zip(); if (config.send() && config.publicUrl().isBlank()) startServer(config.port(), config.bind()); else stopServer(); @@ -83,13 +83,13 @@ public String publicUrl() { return PublicUrlCheck.fill(config.publicUrl(), pack.sha1Hex()); } - /** The last public-url check's result, for /blueminimap debug. */ + /** The last public-url check's result, for /bluemapmini debug. */ public String publicUrlStatus() { return publicUrlStatus; } public Path exportPath() { - return packFolder.resolve("blueminimap-pack.zip"); + return packFolder.resolve("bluemapmini-pack.zip"); } public String sha1() { @@ -118,15 +118,15 @@ private void reportFailure(Player player, PlayerResourcePackStatusEvent.Status s + "It'll try again when you change worlds or rejoin.", NamedTextColor.YELLOW)); String reason = status == PlayerResourcePackStatusEvent.Status.INVALID_URL ? "the address was invalid" : status == PlayerResourcePackStatusEvent.Status.FAILED_RELOAD ? "it didn't load" : "the download failed"; - plugin.getLogger().warning(player.getName() + " didn't get the BlueMinimap pack: " + reason + ". They're playing without the map." - + " Check the pack's hosting; /blueminimap pack export shows the address players are sent."); + plugin.getLogger().warning(player.getName() + " didn't get the BlueMapMini pack: " + reason + ". They're playing without the map." + + " Check the pack's hosting; /bluemapmini pack export shows the address players are sent."); long now = System.currentTimeMillis(); if (now - lastAdminWarning < ADMIN_WARNING_GAP_MILLIS) return; lastAdminWarning = now; - Component warning = Component.text("[BlueMinimap] " + player.getName() + " couldn't download the map's pack (" + reason - + "). Check the pack's hosting. /blueminimap pack export shows the address.", NamedTextColor.GOLD); + Component warning = Component.text("[BlueMapMini] " + player.getName() + " couldn't download the map's pack (" + reason + + "). Check the pack's hosting. /bluemapmini pack export shows the address.", NamedTextColor.GOLD); for (Player admin : Bukkit.getOnlinePlayers()) { - if (com.extantape.blueminimap.Perms.has(admin, "blueminimap.admin")) admin.sendMessage(warning); + if (com.extantape.bluemapmini.Perms.has(admin, "bluemapmini.admin")) admin.sendMessage(warning); } } @@ -218,7 +218,7 @@ private void startServer(int port, String bind) throws IOException { + " Players elsewhere need pack.public-url (or pack.send: false with the files merged into your own pack)."); } server.setExecutor(Executors.newFixedThreadPool(2, runnable -> { - Thread thread = new Thread(runnable, "BlueMinimap-pack"); + Thread thread = new Thread(runnable, "BlueMapMini-pack"); thread.setDaemon(true); return thread; })); @@ -295,14 +295,14 @@ private void checkMergedPackAsync() { boolean found = false; try (ZipInputStream zip = new ZipInputStream(response.body())) { for (ZipEntry entry; (entry = zip.getNextEntry()) != null; ) { - if (entry.getName().equals("assets/blueminimap/font/hud.json")) { + if (entry.getName().equals("assets/bluemapmini/font/hud.json")) { found = true; break; } } } if (!found) { - plugin.getLogger().warning("The server's resource pack doesn't contain BlueMinimap's files. Merge " + exportPath() + " into it."); + plugin.getLogger().warning("The server's resource pack doesn't contain BlueMapMini's files. Merge " + exportPath() + " into it."); } } catch (IOException | RuntimeException e) { plugin.getLogger().warning("Could not check the server's resource pack: " + e.getMessage()); diff --git a/src/main/java/com/extantape/blueminimap/pack/PublicUrlCheck.java b/src/main/java/com/extantape/bluemapmini/pack/PublicUrlCheck.java similarity index 96% rename from src/main/java/com/extantape/blueminimap/pack/PublicUrlCheck.java rename to src/main/java/com/extantape/bluemapmini/pack/PublicUrlCheck.java index f9e8839..9d074d1 100644 --- a/src/main/java/com/extantape/blueminimap/pack/PublicUrlCheck.java +++ b/src/main/java/com/extantape/bluemapmini/pack/PublicUrlCheck.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.pack; +package com.extantape.bluemapmini.pack; import java.io.IOException; import java.io.InputStream; @@ -48,7 +48,7 @@ public static Result check(String url, String expectedSha1, Duration timeout) { } return new Result(false, "The file at pack.public-url doesn't match the pack this plugin built. Hosted SHA-1 " + actual + ", built " + expectedSha1 + ". Players will fail the download" + kickNote() - + ". Upload plugins/BlueMinimap/pack/blueminimap-pack.zip unchanged to " + url + "."); + + ". Upload plugins/BlueMapMini/pack/bluemapmini-pack.zip unchanged to " + url + "."); } } catch (IllegalArgumentException e) { return new Result(false, "pack.public-url isn't a valid address: " + url); diff --git a/src/main/java/com/extantape/blueminimap/render/FontLayout.java b/src/main/java/com/extantape/bluemapmini/render/FontLayout.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/render/FontLayout.java rename to src/main/java/com/extantape/bluemapmini/render/FontLayout.java index a402ab3..042e8b5 100644 --- a/src/main/java/com/extantape/blueminimap/render/FontLayout.java +++ b/src/main/java/com/extantape/bluemapmini/render/FontLayout.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; import net.kyori.adventure.key.Key; @@ -61,7 +61,7 @@ public FontLayout(String name, int layoutIndex, int step, int rows, int reserved public FontLayout(String name, int layoutIndex, int step, int rows, int reservedRows, Direction direction, int plateVariants, int clockGlyphs, int onlyReadoutRow) { this.name = name; - this.font = Key.key("blueminimap", name); + this.font = Key.key("bluemapmini", name); this.layoutIndex = layoutIndex; this.step = step; this.rows = rows; diff --git a/src/main/java/com/extantape/blueminimap/render/HudFonts.java b/src/main/java/com/extantape/bluemapmini/render/HudFonts.java similarity index 95% rename from src/main/java/com/extantape/blueminimap/render/HudFonts.java rename to src/main/java/com/extantape/bluemapmini/render/HudFonts.java index cc5e09f..049ae25 100644 --- a/src/main/java/com/extantape/blueminimap/render/HudFonts.java +++ b/src/main/java/com/extantape/bluemapmini/render/HudFonts.java @@ -1,7 +1,7 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.theme.ThemeSet; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.theme.ThemeSet; /** The fonts a given config needs. The pack is generated from the same object that draws the map. */ public final class HudFonts { diff --git a/src/main/java/com/extantape/blueminimap/render/HudIcon.java b/src/main/java/com/extantape/bluemapmini/render/HudIcon.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/render/HudIcon.java rename to src/main/java/com/extantape/bluemapmini/render/HudIcon.java index becf3e6..0b109dd 100644 --- a/src/main/java/com/extantape/blueminimap/render/HudIcon.java +++ b/src/main/java/com/extantape/bluemapmini/render/HudIcon.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; import java.awt.image.BufferedImage; diff --git a/src/main/java/com/extantape/blueminimap/render/IconSet.java b/src/main/java/com/extantape/bluemapmini/render/IconSet.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/render/IconSet.java rename to src/main/java/com/extantape/bluemapmini/render/IconSet.java index d2a519d..a3aced6 100644 --- a/src/main/java/com/extantape/blueminimap/render/IconSet.java +++ b/src/main/java/com/extantape/bluemapmini/render/IconSet.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; diff --git a/src/main/java/com/extantape/blueminimap/render/MapComposer.java b/src/main/java/com/extantape/bluemapmini/render/MapComposer.java similarity index 96% rename from src/main/java/com/extantape/blueminimap/render/MapComposer.java rename to src/main/java/com/extantape/bluemapmini/render/MapComposer.java index 4c55fec..8e6383d 100644 --- a/src/main/java/com/extantape/blueminimap/render/MapComposer.java +++ b/src/main/java/com/extantape/bluemapmini/render/MapComposer.java @@ -1,6 +1,6 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; -import com.extantape.blueminimap.tiles.GridCache; +import com.extantape.bluemapmini.tiles.GridCache; /** Fills a colour grid from cached chunks, and fingerprints those chunks to detect tile changes. */ public final class MapComposer { diff --git a/src/main/java/com/extantape/blueminimap/render/MapFrame.java b/src/main/java/com/extantape/bluemapmini/render/MapFrame.java similarity index 99% rename from src/main/java/com/extantape/blueminimap/render/MapFrame.java rename to src/main/java/com/extantape/bluemapmini/render/MapFrame.java index e9b9ef7..25f944d 100644 --- a/src/main/java/com/extantape/blueminimap/render/MapFrame.java +++ b/src/main/java/com/extantape/bluemapmini/render/MapFrame.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; diff --git a/src/main/java/com/extantape/blueminimap/render/ReadoutFont.java b/src/main/java/com/extantape/bluemapmini/render/ReadoutFont.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/render/ReadoutFont.java rename to src/main/java/com/extantape/bluemapmini/render/ReadoutFont.java index d48ac23..45d80f3 100644 --- a/src/main/java/com/extantape/blueminimap/render/ReadoutFont.java +++ b/src/main/java/com/extantape/bluemapmini/render/ReadoutFont.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; /** * The 4x7 pixel font for the coordinate readout. It only has the characters coordinates need, and it is diff --git a/src/main/java/com/extantape/blueminimap/render/TinyFont.java b/src/main/java/com/extantape/bluemapmini/render/TinyFont.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/render/TinyFont.java rename to src/main/java/com/extantape/bluemapmini/render/TinyFont.java index 3b7918b..2639e92 100644 --- a/src/main/java/com/extantape/blueminimap/render/TinyFont.java +++ b/src/main/java/com/extantape/bluemapmini/render/TinyFont.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.render; +package com.extantape.bluemapmini.render; /** * A 3x5 pixel font drawn into the pack. The HUD must know every glyph's exact advance to keep the map diff --git a/src/main/java/com/extantape/blueminimap/share/ShareMenu.java b/src/main/java/com/extantape/bluemapmini/share/ShareMenu.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/share/ShareMenu.java rename to src/main/java/com/extantape/bluemapmini/share/ShareMenu.java index 67bdccb..2fb1c42 100644 --- a/src/main/java/com/extantape/blueminimap/share/ShareMenu.java +++ b/src/main/java/com/extantape/bluemapmini/share/ShareMenu.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.share; +package com.extantape.bluemapmini.share; import io.papermc.paper.dialog.Dialog; import io.papermc.paper.dialog.DialogResponseView; @@ -120,9 +120,9 @@ private void onMainThread(Runnable task) { /** One line per person to click, and one for everyone. */ private static void chatList(Player sender, List candidates) { sender.sendMessage(Component.text("Share your coordinates with:", NamedTextColor.GRAY)); - sender.sendMessage(link("Everyone here (" + candidates.size() + ")", "/blueminimap:hud share everyone")); + sender.sendMessage(link("Everyone here (" + candidates.size() + ")", "/bluemapmini:hud share everyone")); for (Player player : candidates.subList(0, Math.min(MAX_LISTED, candidates.size()))) { - sender.sendMessage(link(player.getName(), "/blueminimap:hud share " + player.getName())); + sender.sendMessage(link(player.getName(), "/bluemapmini:hud share " + player.getName())); } } diff --git a/src/main/java/com/extantape/blueminimap/share/ShareService.java b/src/main/java/com/extantape/bluemapmini/share/ShareService.java similarity index 82% rename from src/main/java/com/extantape/blueminimap/share/ShareService.java rename to src/main/java/com/extantape/bluemapmini/share/ShareService.java index 568ad23..12460d6 100644 --- a/src/main/java/com/extantape/blueminimap/share/ShareService.java +++ b/src/main/java/com/extantape/bluemapmini/share/ShareService.java @@ -1,8 +1,8 @@ -package com.extantape.blueminimap.share; +package com.extantape.bluemapmini.share; -import com.extantape.blueminimap.BlueMinimapPlugin; -import com.extantape.blueminimap.api.CoordinateShareEvent; -import com.extantape.blueminimap.config.HudConfig; +import com.extantape.bluemapmini.BlueMapMiniPlugin; +import com.extantape.bluemapmini.api.CoordinateShareEvent; +import com.extantape.bluemapmini.config.HudConfig; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -28,14 +28,14 @@ * players can turn receiving off. Other plugins can narrow or stop any share through {@link CoordinateShareEvent}. */ public final class ShareService { - public static final String SEND = "blueminimap.share.send"; - public static final String RECEIVE = "blueminimap.share.receive"; + public static final String SEND = "bluemapmini.share.send"; + public static final String RECEIVE = "bluemapmini.share.receive"; - private final BlueMinimapPlugin plugin; + private final BlueMapMiniPlugin plugin; /** When each player last shared. Kept across rejoins, so leaving can't skip the cooldown. */ private final Map lastShare = new HashMap<>(); - public ShareService(BlueMinimapPlugin plugin) { + public ShareService(BlueMapMiniPlugin plugin) { this.plugin = plugin; } @@ -67,7 +67,7 @@ public List candidates(Player sender) { List result = new ArrayList<>(); for (Player other : Bukkit.getOnlinePlayers()) { if (other.equals(sender) || !sender.canSee(other)) continue; - if (!com.extantape.blueminimap.Perms.has(other, RECEIVE) || !plugin.hud().session(other).settings().receiveShares) continue; + if (!com.extantape.bluemapmini.Perms.has(other, RECEIVE) || !plugin.hud().session(other).settings().receiveShares) continue; if (!anyWorld && !worldGroup(other.getWorld().getName()).equals(group)) continue; result.add(other); } @@ -86,8 +86,8 @@ public static Player findVisible(Player sender, String name) { /** Why the sender can't share right now, or null if they can. */ public String blocked(Player sender) { if (!config().enabled()) return "Sharing coordinates is turned off on this server."; - if (!com.extantape.blueminimap.Perms.has(sender, SEND)) return "You can't share your coordinates here."; - String guard = olderHouseRules(); + if (!com.extantape.bluemapmini.Perms.has(sender, SEND)) return "You can't share your coordinates here."; + String guard = olderMayor(); if (guard != null) { plugin.getLogger().warning(guard); return "Sharing coordinates is off on this server for now. An admin has been told why."; @@ -185,23 +185,27 @@ private static String place(World world) { } /** - * HouseRules 0.1.x listens for the share event under BlueMapHUD's old name, so it wouldn't see shares from - * BlueMinimap and they'd skip its chat circles. Fail closed: no shares until HouseRules is 0.2 or newer. + * Shares follow Mayor's chat rules, and Mayor before 0.5.0 listens for a share event BlueMapMini doesn't send. So + * sharing is off (fail closed) unless Mayor 0.5.0 or newer is installed, or the server turned require-mayor off. + * The version is null when Mayor isn't installed. */ - static String olderHouseRules(String version) { - if (version == null) return null; + static String olderMayor(String version, boolean requireMayor) { + if (version == null) return requireMayor + ? "Coordinate sharing is off because it follows Mayor's chat rules and Mayor isn't installed. Install Mayor 0.5.0 or newer, or set share.require-mayor: false on a server without chat rules." + : null; String[] p = version.split("[.-]"); try { int major = Integer.parseInt(p[0]), minor = p.length > 1 ? Integer.parseInt(p[1]) : 0; - if (major > 0 || minor >= 2) return null; + if (major > 0 || minor >= 5) return null; } catch (NumberFormatException e) { // Unreadable version: treat it as too old. } - return "Coordinate sharing is off because HouseRules " + version + " can't see BlueMinimap's shares, so they'd skip its chat circles. Update HouseRules to 0.2.0 or newer."; + return "Coordinate sharing is off because Mayor " + version + " can't see BlueMapMini's shares, so they'd skip its chat circles. Update Mayor to 0.5.0 or newer."; } - private String olderHouseRules() { - org.bukkit.plugin.Plugin houseRules = plugin.getServer().getPluginManager().getPlugin("HouseRules"); - return houseRules == null ? null : olderHouseRules(houseRules.getPluginMeta().getVersion()); + private String olderMayor() { + org.bukkit.plugin.Plugin mayor = plugin.getServer().getPluginManager().getPlugin("Mayor"); + boolean on = mayor != null && mayor.isEnabled(); + return olderMayor(on ? mayor.getPluginMeta().getVersion() : null, config().requireMayor()); } } diff --git a/src/main/java/com/extantape/blueminimap/theme/Theme.java b/src/main/java/com/extantape/bluemapmini/theme/Theme.java similarity index 99% rename from src/main/java/com/extantape/blueminimap/theme/Theme.java rename to src/main/java/com/extantape/bluemapmini/theme/Theme.java index 77372c6..3569cc8 100644 --- a/src/main/java/com/extantape/blueminimap/theme/Theme.java +++ b/src/main/java/com/extantape/bluemapmini/theme/Theme.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.theme; +package com.extantape.bluemapmini.theme; import com.google.gson.JsonArray; import com.google.gson.JsonElement; diff --git a/src/main/java/com/extantape/blueminimap/theme/ThemeContrast.java b/src/main/java/com/extantape/bluemapmini/theme/ThemeContrast.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/theme/ThemeContrast.java rename to src/main/java/com/extantape/bluemapmini/theme/ThemeContrast.java index 2dcaf1b..58e0b5e 100644 --- a/src/main/java/com/extantape/blueminimap/theme/ThemeContrast.java +++ b/src/main/java/com/extantape/bluemapmini/theme/ThemeContrast.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.theme; +package com.extantape.bluemapmini.theme; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/extantape/blueminimap/theme/ThemeSet.java b/src/main/java/com/extantape/bluemapmini/theme/ThemeSet.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/theme/ThemeSet.java rename to src/main/java/com/extantape/bluemapmini/theme/ThemeSet.java index 974da68..80e307b 100644 --- a/src/main/java/com/extantape/blueminimap/theme/ThemeSet.java +++ b/src/main/java/com/extantape/bluemapmini/theme/ThemeSet.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.theme; +package com.extantape.bluemapmini.theme; import java.io.IOException; import java.io.InputStream; @@ -21,7 +21,7 @@ /** * The themes the pack is built with: the built-in ones from the jar's {@code themes/} folder, plus or - * replaced by any in the server's {@code plugins/BlueMinimap/themes/}. The pack holds every theme, so a + * replaced by any in the server's {@code plugins/BlueMapMini/themes/}. The pack holds every theme, so a * player can switch with {@code /hud theme} without a new download. */ public final class ThemeSet { diff --git a/src/main/java/com/extantape/blueminimap/tiles/FileTileSource.java b/src/main/java/com/extantape/bluemapmini/tiles/FileTileSource.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/tiles/FileTileSource.java rename to src/main/java/com/extantape/bluemapmini/tiles/FileTileSource.java index c820551..888d0de 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/FileTileSource.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/FileTileSource.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/com/extantape/blueminimap/tiles/GridCache.java b/src/main/java/com/extantape/bluemapmini/tiles/GridCache.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/tiles/GridCache.java rename to src/main/java/com/extantape/bluemapmini/tiles/GridCache.java index 0816fa5..e433a6f 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/GridCache.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/GridCache.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import java.io.IOException; import java.util.Arrays; @@ -51,7 +51,7 @@ public int cell(int localX, int localZ) { private final Logger logger; private final Set loading = ConcurrentHashMap.newKeySet(); private final ExecutorService loaders = Executors.newFixedThreadPool(2, runnable -> { - Thread thread = new Thread(runnable, "BlueMinimap-tiles"); + Thread thread = new Thread(runnable, "BlueMapMini-tiles"); thread.setDaemon(true); thread.setPriority(Thread.NORM_PRIORITY - 1); return thread; diff --git a/src/main/java/com/extantape/blueminimap/tiles/HttpTileSource.java b/src/main/java/com/extantape/bluemapmini/tiles/HttpTileSource.java similarity index 98% rename from src/main/java/com/extantape/blueminimap/tiles/HttpTileSource.java rename to src/main/java/com/extantape/bluemapmini/tiles/HttpTileSource.java index 32c0325..72ee95d 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/HttpTileSource.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/HttpTileSource.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import java.io.IOException; import java.net.URI; diff --git a/src/main/java/com/extantape/blueminimap/tiles/LowresSettings.java b/src/main/java/com/extantape/bluemapmini/tiles/LowresSettings.java similarity index 97% rename from src/main/java/com/extantape/blueminimap/tiles/LowresSettings.java rename to src/main/java/com/extantape/bluemapmini/tiles/LowresSettings.java index 5f8c91b..6663030 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/LowresSettings.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/LowresSettings.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/src/main/java/com/extantape/blueminimap/tiles/TileSource.java b/src/main/java/com/extantape/bluemapmini/tiles/TileSource.java similarity index 96% rename from src/main/java/com/extantape/blueminimap/tiles/TileSource.java rename to src/main/java/com/extantape/bluemapmini/tiles/TileSource.java index aab0556..4c303b0 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/TileSource.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/TileSource.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import java.io.IOException; diff --git a/src/main/java/com/extantape/blueminimap/tiles/TileStore.java b/src/main/java/com/extantape/bluemapmini/tiles/TileStore.java similarity index 99% rename from src/main/java/com/extantape/blueminimap/tiles/TileStore.java rename to src/main/java/com/extantape/bluemapmini/tiles/TileStore.java index 3132d75..856ea4d 100644 --- a/src/main/java/com/extantape/blueminimap/tiles/TileStore.java +++ b/src/main/java/com/extantape/bluemapmini/tiles/TileStore.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.tiles; +package com.extantape.bluemapmini.tiles; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; diff --git a/src/main/java/com/extantape/blueminimap/Migration.java b/src/main/java/com/extantape/blueminimap/Migration.java deleted file mode 100644 index 4e5b6d4..0000000 --- a/src/main/java/com/extantape/blueminimap/Migration.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.extantape.blueminimap; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.stream.Stream; - -/** Carries a server's files over from the old plugin folder after the rename from BlueMapHUD (2026-11-09). */ -final class Migration { - private Migration() {} - - /** - * Copies {@code old} to {@code now} if {@code now} doesn't exist and {@code old} is a folder. Copies into a - * temporary sibling first and renames it into place, so a crash halfway leaves no half-filled folder. - * - * @return a line for the log saying what happened, or null if there was nothing to do - */ - static String copyIfMissing(Path old, Path now) { - if (Files.exists(now) || !Files.isDirectory(old)) return null; - Path tmp = now.resolveSibling(now.getFileName() + ".migrating"); - try { - if (Files.exists(tmp)) deleteTree(tmp); - try (Stream all = Files.walk(old)) { - all.forEach(p -> { - Path to = tmp.resolve(old.relativize(p).toString()); - try { - if (Files.isDirectory(p)) Files.createDirectories(to); - else Files.copy(p, to, StandardCopyOption.COPY_ATTRIBUTES); - } catch (IOException e) { throw new UncheckedIOException(e); } - }); - } - Files.move(tmp, now, StandardCopyOption.ATOMIC_MOVE); - return "Copied plugins/" + old.getFileName() + " to plugins/" + now.getFileName() - + " (BlueMapHUD is now called BlueMinimap). The old folder was left untouched; delete it once you're happy."; - } catch (IOException | UncheckedIOException e) { - return "Couldn't copy plugins/" + old.getFileName() + " to plugins/" + now.getFileName() + ": " + e.getMessage() - + ". Copy it by hand while the server is stopped, or BlueMinimap starts with a fresh config."; - } - } - - private static void deleteTree(Path root) throws IOException { - try (Stream all = Files.walk(root)) { - for (Path p : all.sorted(java.util.Comparator.reverseOrder()).toList()) Files.delete(p); - } - } -} diff --git a/src/main/java/com/extantape/blueminimap/Perms.java b/src/main/java/com/extantape/blueminimap/Perms.java deleted file mode 100644 index 1520c19..0000000 --- a/src/main/java/com/extantape/blueminimap/Perms.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.extantape.blueminimap; - -import org.bukkit.command.CommandSender; -import org.bukkit.permissions.Permissible; - -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - -/** - * Permission checks that still respect the names from before the rename to BlueMinimap (2026-11-09), for one - * release (0.2.x): {@code bluemaphud.use} alongside {@code blueminimap.use}, and so on. The old nodes are declared - * with their old defaults, so on a server that never touched them both names agree. - * - *

Most nodes are on by default, so the old names matter most where a server turned one off, for example - * {@code bluemaphud.share.send: false} for a children's group. That must stay off after the upgrade. So for nodes - * that are on by default, a "no" on either name wins. For {@code admin}, which is for operators only by default, a - * "yes" on either name wins, so admins keep their tools. Whenever the old name is what decided the answer, that's - * logged once per player and node, saying what to change. - */ -public final class Perms { - /** Nodes that are on by default, where a deny on either name wins. Everything else: a grant on either wins. */ - static final Set ON_BY_DEFAULT = Set.of("blueminimap.use", "blueminimap.fullscreen", "blueminimap.seeplayers", - "blueminimap.share.send", "blueminimap.share.receive"); - private static final Set warned = ConcurrentHashMap.newKeySet(); - private static volatile Consumer warn = line -> {}; - - private Perms() {} - - public static void logTo(Consumer sink) { warn = sink; } - - public static String oldName(String node) { - return "bluemaphud." + node.substring("blueminimap.".length()); - } - - public static boolean has(Permissible who, String node) { - boolean now = who.hasPermission(node); - if (!node.startsWith("blueminimap.")) return now; - String old = oldName(node); - boolean then = who.hasPermission(old); - if (now == then) return now; - boolean result = ON_BY_DEFAULT.contains(node) ? now && then : now || then; - if (result == now) return result; // the old name changed nothing, so there's nothing to tell anyone - String name = who instanceof CommandSender cs ? cs.getName() : String.valueOf(who); - if (warned.add(name + " " + node)) - warn.accept(name + " has " + node + " " + now + " but the old " + old + " " + then + ", so it's " + result - + ". The old name is still respected in 0.2.x but goes in the next release: set " + node + " instead."); - return result; - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index f912a25..736012f 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,4 +1,4 @@ -# BlueMinimap configuration. Apply changes with /blueminimap reload. +# BlueMapMini configuration. Apply changes with /bluemapmini reload. tiles: # file: read BlueMap's folder directly (fastest, file storage only). @@ -36,7 +36,7 @@ hud: # Players can switch with /hud mode, and their choice is saved. default-mode: map # Colours, plate and clock style for new players: classic, galaxy, desert or high-contrast, or a theme - # of your own in plugins/BlueMinimap/themes/. Players can choose their own with /hud theme. + # of your own in plugins/BlueMapMini/themes/. Players can choose their own with /hud theme. theme: classic clock: # A small clock and the in-game time after the coordinates, in 24-hour time. It's hidden where time @@ -57,8 +57,8 @@ hud: quick-hide-gesture: false commands: - # The first name no other plugin owns is used. /blueminimap map, /blueminimap hud, - # /blueminimap:map and /blueminimap:hud always work. + # The first name no other plugin owns is used. /bluemapmini map, /bluemapmini hud, + # /bluemapmini:map and /bluemapmini:hud always work. map-names: [map, worldmap] hud-names: [hud, minimap] @@ -96,13 +96,13 @@ markers: show-death: true pack: - # false means your own merged pack provides the files. See /blueminimap pack export. + # false means your own merged pack provides the files. See /bluemapmini pack export. send: true # true kicks players who decline the pack, with kick-message. A download that fails never kicks: # the player plays without the map, admins are warned, and it tries again on a world change or rejoin. required: true - kick-message: "This server needs the BlueMinimap resource pack." - prompt: "BlueMinimap draws the map with this small resource pack." + kick-message: "This server needs the BlueMapMini resource pack." + prompt: "BlueMapMini draws the map with this small resource pack." port: 8164 # Address the pack server listens on. Empty listens on every address, as before. 127.0.0.1 keeps it on # this machine only: then only players on this machine can download from it, so use pack.public-url (or @@ -113,9 +113,9 @@ pack: host: "" # Host the pack elsewhere, such as a CDN or GitHub release. Overrides the port. # {sha1} is replaced with the built pack's hash, so the address changes when the pack does. - # Upload plugins/BlueMinimap/pack/blueminimap-pack.zip unchanged; re-zipping it changes the hash. + # Upload plugins/BlueMapMini/pack/bluemapmini-pack.zip unchanged; re-zipping it changes the hash. public-url: "" - # On startup and /blueminimap reload, download public-url once and warn if it isn't the current pack. + # On startup and /bluemapmini reload, download public-url once and warn if it isn't the current pack. # Turn off if the server itself can't reach that address. verify-public-url: true # Make one boss bar colour transparent. Turn off only with the action bar. @@ -131,9 +131,13 @@ share: # Who can be offered a share: world-group is players in the sender's world, counting its _nether and # _the_end as the same world. all-online is everyone, for servers whose rules plugin narrows each share # through CoordinateShareEvent; with no such plugin listening it acts like world-group. Players who - # turned shares off (/hud hide shares) or lack blueminimap.share.receive are never offered. + # turned shares off (/hud hide shares) or lack bluemapmini.share.receive are never offered. candidates: world-group # Seconds a player waits between shares, so it can't be used to spam. cooldown-seconds: 30 # Log each share to the console: who sent it, where, and who received it. log: true + # Shares only while Mayor 0.5.0 or newer is installed, so every share follows the same rules as chat. With true + # and no Mayor, /hud share stays off and the console says why. Set false only on a server without chat rules, + # where sharing to anyone in the world group is fine. + require-mayor: true diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml index 717493e..fcd5406 100644 --- a/src/main/resources/paper-plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -1,9 +1,9 @@ -name: BlueMinimap +name: BlueMapMini version: '${version}' -main: com.extantape.blueminimap.BlueMinimapPlugin +main: com.extantape.bluemapmini.BlueMapMiniPlugin api-version: '26.1' description: A BlueMap minimap and coordinates HUD, with a fullscreen map, drawn with a resource pack font. -website: https://github.com/ExtantApe/BlueMinimap +website: https://github.com/ExtantApe/BlueMapMini # Commands are registered with Brigadier in code, so there is no commands section. dependencies: server: @@ -18,39 +18,21 @@ dependencies: required: false join-classpath: true permissions: - blueminimap.use: + bluemapmini.use: description: See and control the minimap. default: true - blueminimap.fullscreen: + bluemapmini.fullscreen: description: Open the fullscreen map. default: true - blueminimap.seeplayers: + bluemapmini.seeplayers: description: See other players on the map. default: true - blueminimap.share.send: + bluemapmini.share.send: description: Share your coordinates with /hud share. default: true - blueminimap.share.receive: + bluemapmini.share.receive: description: Receive coordinates other players share. default: true - blueminimap.admin: - description: Use /blueminimap reload, debug and pack commands. - default: op - bluemaphud.use: - description: The old name for blueminimap.use, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. - default: true - bluemaphud.fullscreen: - description: The old name for blueminimap.fullscreen, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. - default: true - bluemaphud.seeplayers: - description: The old name for blueminimap.seeplayers, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. - default: true - bluemaphud.share.send: - description: The old name for blueminimap.share.send, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. - default: true - bluemaphud.share.receive: - description: The old name for blueminimap.share.receive, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. - default: true - bluemaphud.admin: - description: The old name for blueminimap.admin, from before the rename. Still respected in 0.2.x (a "no" on either name wins for nodes that are on by default) and removed in the next release. + bluemapmini.admin: + description: Use /bluemapmini reload, debug and pack commands. default: op diff --git a/src/test/java/com/extantape/blueminimap/PlayerSettingsTest.java b/src/test/java/com/extantape/bluemapmini/PlayerSettingsTest.java similarity index 94% rename from src/test/java/com/extantape/blueminimap/PlayerSettingsTest.java rename to src/test/java/com/extantape/bluemapmini/PlayerSettingsTest.java index f23599b..176e8d8 100644 --- a/src/test/java/com/extantape/blueminimap/PlayerSettingsTest.java +++ b/src/test/java/com/extantape/bluemapmini/PlayerSettingsTest.java @@ -1,7 +1,7 @@ -package com.extantape.blueminimap; +package com.extantape.bluemapmini; -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.hud.PlayerSettings; +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.hud.PlayerSettings; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.persistence.PersistentDataContainer; import org.junit.jupiter.api.Test; @@ -66,7 +66,7 @@ void aSavedChoiceBeatsTheDefault() { void settingsSavedBeforeModesStillLoad() { PersistentDataContainer data = container(); // The first format: format, enabled, zoom, fullscreen zoom, size, offset x, offset y, coords, players, markers. - data.set(new org.bukkit.NamespacedKey("bluemaphud", "settings"), + data.set(new org.bukkit.NamespacedKey("bluemapmini", "settings"), org.bukkit.persistence.PersistentDataType.INTEGER_ARRAY, new int[] {1, 0, 16, 32, 24, 40, 8, 0, 1, 0}); PlayerSettings old = PlayerSettings.load(data, config("map")); assertFalse(old.enabled); @@ -103,7 +103,7 @@ void theClockAndThemeAreSaved() { void settingsSavedBeforeTheClockStillLoad() { PersistentDataContainer data = container(); // The second format added the mode at the end. - data.set(new org.bukkit.NamespacedKey("bluemaphud", "settings"), + data.set(new org.bukkit.NamespacedKey("bluemapmini", "settings"), org.bukkit.persistence.PersistentDataType.INTEGER_ARRAY, new int[] {2, 1, 4, 16, 40, 0, 0, 1, 1, 1, 1}); PlayerSettings old = PlayerSettings.load(data, config("map")); assertTrue(old.coordsOnly); diff --git a/src/test/java/com/extantape/blueminimap/RenderTest.java b/src/test/java/com/extantape/bluemapmini/RenderTest.java similarity index 96% rename from src/test/java/com/extantape/blueminimap/RenderTest.java rename to src/test/java/com/extantape/bluemapmini/RenderTest.java index 2eb8445..b40f384 100644 --- a/src/test/java/com/extantape/blueminimap/RenderTest.java +++ b/src/test/java/com/extantape/bluemapmini/RenderTest.java @@ -1,20 +1,20 @@ -package com.extantape.blueminimap; - -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.hud.FrameBuilder; -import com.extantape.blueminimap.hud.Snapshot; -import com.extantape.blueminimap.markers.MarkerService; -import com.extantape.blueminimap.pack.PackBuilder; -import com.extantape.blueminimap.render.FontLayout; -import com.extantape.blueminimap.render.HudFonts; -import com.extantape.blueminimap.render.HudIcon; -import com.extantape.blueminimap.render.IconSet; -import com.extantape.blueminimap.render.MapComposer; -import com.extantape.blueminimap.render.MapFrame; -import com.extantape.blueminimap.render.TinyFont; -import com.extantape.blueminimap.tiles.GridCache; -import com.extantape.blueminimap.tiles.TileSource; -import com.extantape.blueminimap.tiles.TileStore; +package com.extantape.bluemapmini; + +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.hud.FrameBuilder; +import com.extantape.bluemapmini.hud.Snapshot; +import com.extantape.bluemapmini.markers.MarkerService; +import com.extantape.bluemapmini.pack.PackBuilder; +import com.extantape.bluemapmini.render.FontLayout; +import com.extantape.bluemapmini.render.HudFonts; +import com.extantape.bluemapmini.render.HudIcon; +import com.extantape.bluemapmini.render.IconSet; +import com.extantape.bluemapmini.render.MapComposer; +import com.extantape.bluemapmini.render.MapFrame; +import com.extantape.bluemapmini.render.TinyFont; +import com.extantape.bluemapmini.tiles.GridCache; +import com.extantape.bluemapmini.tiles.TileSource; +import com.extantape.bluemapmini.tiles.TileStore; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.kyori.adventure.text.Component; @@ -94,7 +94,7 @@ void packUsesItsOwnNamespaceAndNoShaders() throws IOException { for (String path : client.files.keySet()) { assertFalse(path.contains("shaders"), path); assertTrue(path.equals("pack.mcmeta") - || path.startsWith("assets/blueminimap/") + || path.startsWith("assets/bluemapmini/") || path.startsWith("assets/minecraft/textures/gui/sprites/boss_bar/pink_"), path); } JsonObject pack = JsonParser.parseString(new String(client.files.get("pack.mcmeta"), StandardCharsets.UTF_8)) @@ -189,7 +189,7 @@ void framesUseOneFontAndNoShadow() { frame.drawGrid(new int[16]); Component component = frame.finish(); assertEquals("hud", component.style().font().value()); - assertEquals("blueminimap", component.style().font().namespace()); + assertEquals("bluemapmini", component.style().font().namespace()); assertEquals(ShadowColor.none(), component.style().shadowColor()); } @@ -295,8 +295,8 @@ void readoutFontAdvancesMatchTheClientFormula() throws IOException { HudConfig config = config(); HudFonts fonts = new HudFonts(config); SimulatedClient.Font font = client(config, fonts).fonts.get("hud"); - for (int glyph = 0; glyph < com.extantape.blueminimap.render.ReadoutFont.glyphCount(); glyph++) { - assertEquals(font.glyphs().get(fonts.minimap.readoutChar(0, glyph)).advance(), com.extantape.blueminimap.render.ReadoutFont.advance(glyph), "glyph " + glyph); + for (int glyph = 0; glyph < com.extantape.bluemapmini.render.ReadoutFont.glyphCount(); glyph++) { + assertEquals(font.glyphs().get(fonts.minimap.readoutChar(0, glyph)).advance(), com.extantape.bluemapmini.render.ReadoutFont.advance(glyph), "glyph " + glyph); } } @@ -384,7 +384,7 @@ void coordsOnlyDrawsJustTheReadoutAndNeedsNoMap() throws IOException { maxY = Math.max(maxY, y); } } - assertEquals(com.extantape.blueminimap.render.FontLayout.PLATE_HEIGHT, maxY - minY + 1, "Just one plate high"); + assertEquals(com.extantape.bluemapmini.render.FontLayout.PLATE_HEIGHT, maxY - minY + 1, "Just one plate high"); assertTrue(Math.abs((minX + maxX) / 2 - SCREEN_W / 2) <= 2, "Centred at the top: " + minX + " to " + maxX); assertTrue(maxX - minX < 100, "Only a short line: " + (maxX - minX)); ImageIO.write(image.getSubimage(SCREEN_W / 2 - 80, 0, 160, 40), "png", previewFile("coords-only.png")); diff --git a/src/test/java/com/extantape/blueminimap/ShareTest.java b/src/test/java/com/extantape/bluemapmini/ShareTest.java similarity index 89% rename from src/test/java/com/extantape/blueminimap/ShareTest.java rename to src/test/java/com/extantape/bluemapmini/ShareTest.java index 7069b39..5194e1e 100644 --- a/src/test/java/com/extantape/blueminimap/ShareTest.java +++ b/src/test/java/com/extantape/bluemapmini/ShareTest.java @@ -1,6 +1,6 @@ -package com.extantape.blueminimap; +package com.extantape.bluemapmini; -import com.extantape.blueminimap.share.ShareService; +import com.extantape.bluemapmini.share.ShareService; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/com/extantape/blueminimap/SimulatedClient.java b/src/test/java/com/extantape/bluemapmini/SimulatedClient.java similarity index 96% rename from src/test/java/com/extantape/blueminimap/SimulatedClient.java rename to src/test/java/com/extantape/bluemapmini/SimulatedClient.java index 4ab8cae..2dc8cea 100644 --- a/src/test/java/com/extantape/blueminimap/SimulatedClient.java +++ b/src/test/java/com/extantape/bluemapmini/SimulatedClient.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap; +package com.extantape.bluemapmini; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -35,8 +35,8 @@ record Font(Map glyphs, Map spaces) {} for (ZipEntry entry; (entry = in.getNextEntry()) != null; ) files.put(entry.getName(), in.readAllBytes()); } for (String path : files.keySet()) { - if (path.startsWith("assets/blueminimap/font/") && path.endsWith(".json")) { - String name = path.substring("assets/blueminimap/font/".length(), path.length() - 5); + if (path.startsWith("assets/bluemapmini/font/") && path.endsWith(".json")) { + String name = path.substring("assets/bluemapmini/font/".length(), path.length() - 5); fonts.put(name, loadFont(new String(files.get(path), StandardCharsets.UTF_8))); } } @@ -58,7 +58,7 @@ private Font loadFont(String json) throws IOException { int height = provider.get("height").getAsInt(); int ascent = provider.get("ascent").getAsInt(); if (ascent > height) throw new AssertionError("Client rejects ascent " + ascent + " > height " + height); - String file = "assets/blueminimap/textures/" + provider.get("file").getAsString().substring("blueminimap:".length()); + String file = "assets/bluemapmini/textures/" + provider.get("file").getAsString().substring("bluemapmini:".length()); byte[] png = files.get(file); if (png == null) throw new AssertionError("Missing texture " + file); BufferedImage sheet = sheets.computeIfAbsent(file, f -> { diff --git a/src/test/java/com/extantape/blueminimap/ThemeTest.java b/src/test/java/com/extantape/bluemapmini/ThemeTest.java similarity index 95% rename from src/test/java/com/extantape/blueminimap/ThemeTest.java rename to src/test/java/com/extantape/bluemapmini/ThemeTest.java index b00d488..2f9285e 100644 --- a/src/test/java/com/extantape/blueminimap/ThemeTest.java +++ b/src/test/java/com/extantape/bluemapmini/ThemeTest.java @@ -1,15 +1,15 @@ -package com.extantape.blueminimap; - -import com.extantape.blueminimap.config.HudConfig; -import com.extantape.blueminimap.hud.FrameBuilder; -import com.extantape.blueminimap.hud.Snapshot; -import com.extantape.blueminimap.markers.MarkerService; -import com.extantape.blueminimap.pack.PackBuilder; -import com.extantape.blueminimap.render.HudFonts; -import com.extantape.blueminimap.render.IconSet; -import com.extantape.blueminimap.theme.Theme; -import com.extantape.blueminimap.theme.ThemeContrast; -import com.extantape.blueminimap.theme.ThemeSet; +package com.extantape.bluemapmini; + +import com.extantape.bluemapmini.config.HudConfig; +import com.extantape.bluemapmini.hud.FrameBuilder; +import com.extantape.bluemapmini.hud.Snapshot; +import com.extantape.bluemapmini.markers.MarkerService; +import com.extantape.bluemapmini.pack.PackBuilder; +import com.extantape.bluemapmini.render.HudFonts; +import com.extantape.bluemapmini.render.IconSet; +import com.extantape.bluemapmini.theme.Theme; +import com.extantape.bluemapmini.theme.ThemeContrast; +import com.extantape.bluemapmini.theme.ThemeSet; import net.kyori.adventure.text.Component; import org.bukkit.configuration.file.YamlConfiguration; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/extantape/blueminimap/TilesTest.java b/src/test/java/com/extantape/bluemapmini/TilesTest.java similarity index 95% rename from src/test/java/com/extantape/blueminimap/TilesTest.java rename to src/test/java/com/extantape/bluemapmini/TilesTest.java index da319e8..50f9b9f 100644 --- a/src/test/java/com/extantape/blueminimap/TilesTest.java +++ b/src/test/java/com/extantape/bluemapmini/TilesTest.java @@ -1,9 +1,9 @@ -package com.extantape.blueminimap; +package com.extantape.bluemapmini; -import com.extantape.blueminimap.tiles.GridCache; -import com.extantape.blueminimap.tiles.LowresSettings; -import com.extantape.blueminimap.tiles.TileSource; -import com.extantape.blueminimap.tiles.TileStore; +import com.extantape.bluemapmini.tiles.GridCache; +import com.extantape.bluemapmini.tiles.LowresSettings; +import com.extantape.bluemapmini.tiles.TileSource; +import com.extantape.bluemapmini.tiles.TileStore; import org.junit.jupiter.api.Test; import javax.imageio.ImageIO; diff --git a/src/test/java/com/extantape/blueminimap/pack/ListenAddressTest.java b/src/test/java/com/extantape/bluemapmini/pack/ListenAddressTest.java similarity index 97% rename from src/test/java/com/extantape/blueminimap/pack/ListenAddressTest.java rename to src/test/java/com/extantape/bluemapmini/pack/ListenAddressTest.java index e5da435..05ce883 100644 --- a/src/test/java/com/extantape/blueminimap/pack/ListenAddressTest.java +++ b/src/test/java/com/extantape/bluemapmini/pack/ListenAddressTest.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.pack; +package com.extantape.bluemapmini.pack; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/extantape/blueminimap/pack/PublicUrlCheckTest.java b/src/test/java/com/extantape/bluemapmini/pack/PublicUrlCheckTest.java similarity index 99% rename from src/test/java/com/extantape/blueminimap/pack/PublicUrlCheckTest.java rename to src/test/java/com/extantape/bluemapmini/pack/PublicUrlCheckTest.java index f942070..b16bc80 100644 --- a/src/test/java/com/extantape/blueminimap/pack/PublicUrlCheckTest.java +++ b/src/test/java/com/extantape/bluemapmini/pack/PublicUrlCheckTest.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.pack; +package com.extantape.bluemapmini.pack; import com.sun.net.httpserver.HttpServer; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/com/extantape/bluemapmini/share/MayorGuardTest.java b/src/test/java/com/extantape/bluemapmini/share/MayorGuardTest.java new file mode 100644 index 0000000..d3c2f65 --- /dev/null +++ b/src/test/java/com/extantape/bluemapmini/share/MayorGuardTest.java @@ -0,0 +1,28 @@ +package com.extantape.bluemapmini.share; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** Shares must follow Mayor's chat rules, so sharing stays off unless a Mayor that can see them is installed. */ +class MayorGuardTest { + @Test + void sharingIsOffWithAMayorOlderThan05() { + assertNotNull(ShareService.olderMayor("0.4.0", true), "0.4.x hooks a share event BlueMapMini no longer sends"); + assertNotNull(ShareService.olderMayor("0.1.1", false), "an old Mayor stops shares even with require-mayor off"); + assertNotNull(ShareService.olderMayor("something odd", true), "an unreadable version fails closed"); + } + + @Test + void sharingIsOffWithoutMayorUnlessTheServerSaysOtherwise() { + assertNotNull(ShareService.olderMayor(null, true), "no Mayor, default settings: sharing stays off"); + assertNull(ShareService.olderMayor(null, false), "a server without chat rules can turn sharing on"); + } + + @Test + void sharingIsOnWithMayor05OrNewer() { + assertNull(ShareService.olderMayor("0.5.0", true)); + assertNull(ShareService.olderMayor("0.5.1-SNAPSHOT", true)); + assertNull(ShareService.olderMayor("1.0.0", true)); + } +} diff --git a/src/test/java/com/extantape/blueminimap/MigrationTest.java b/src/test/java/com/extantape/blueminimap/MigrationTest.java deleted file mode 100644 index 4d8c63e..0000000 --- a/src/test/java/com/extantape/blueminimap/MigrationTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.extantape.blueminimap; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.*; - -class MigrationTest { - - @Test - void copiesTheOldFolderWhenTheNewOneIsMissing(@TempDir Path plugins) throws Exception { - Path old = plugins.resolve("BlueMapHUD"); - Files.createDirectories(old.resolve("sub")); - Files.writeString(old.resolve("config.yml"), "profiles: {}\n"); - Files.writeString(old.resolve("changes.log"), "{\"a\":1}\n"); - Files.writeString(old.resolve("sub/x.json"), "[]"); - - String msg = Migration.copyIfMissing(old, plugins.resolve("BlueMinimap")); - - assertNotNull(msg); - assertEquals("profiles: {}\n", Files.readString(plugins.resolve("BlueMinimap/config.yml"))); - assertEquals("{\"a\":1}\n", Files.readString(plugins.resolve("BlueMinimap/changes.log"))); - assertEquals("[]", Files.readString(plugins.resolve("BlueMinimap/sub/x.json"))); - assertTrue(Files.exists(old.resolve("config.yml")), "the old folder is left as a backup"); - assertFalse(Files.exists(plugins.resolve("BlueMinimap.migrating"))); - } - - @Test - void neverOverwritesAnExistingNewFolder(@TempDir Path plugins) throws Exception { - Files.createDirectories(plugins.resolve("BlueMapHUD")); - Files.writeString(plugins.resolve("BlueMapHUD/config.yml"), "old"); - Files.createDirectories(plugins.resolve("BlueMinimap")); - Files.writeString(plugins.resolve("BlueMinimap/config.yml"), "new"); - - assertNull(Migration.copyIfMissing(plugins.resolve("BlueMapHUD"), plugins.resolve("BlueMinimap"))); - assertEquals("new", Files.readString(plugins.resolve("BlueMinimap/config.yml"))); - } - - @Test - void doesNothingOnAFreshServer(@TempDir Path plugins) { - assertNull(Migration.copyIfMissing(plugins.resolve("BlueMapHUD"), plugins.resolve("BlueMinimap"))); - assertFalse(Files.exists(plugins.resolve("BlueMinimap"))); - } - - @Test - void clearsAHalfFinishedCopyFromACrash(@TempDir Path plugins) throws Exception { - Files.createDirectories(plugins.resolve("BlueMapHUD")); - Files.writeString(plugins.resolve("BlueMapHUD/config.yml"), "real"); - Files.createDirectories(plugins.resolve("BlueMinimap.migrating")); - Files.writeString(plugins.resolve("BlueMinimap.migrating/junk"), "half"); - - assertNotNull(Migration.copyIfMissing(plugins.resolve("BlueMapHUD"), plugins.resolve("BlueMinimap"))); - assertEquals("real", Files.readString(plugins.resolve("BlueMinimap/config.yml"))); - assertFalse(Files.exists(plugins.resolve("BlueMinimap/junk"))); - } -} diff --git a/src/test/java/com/extantape/blueminimap/PermsTest.java b/src/test/java/com/extantape/blueminimap/PermsTest.java deleted file mode 100644 index 54fc513..0000000 --- a/src/test/java/com/extantape/blueminimap/PermsTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.extantape.blueminimap; - -import org.bukkit.permissions.Permissible; -import org.junit.jupiter.api.Test; - -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -class PermsTest { - - /** A Permissible whose answers come from the map; anything missing is false. */ - private static Permissible with(Map values) { - return (Permissible) Proxy.newProxyInstance(Permissible.class.getClassLoader(), new Class[]{Permissible.class}, - (proxy, method, args) -> switch (method.getName()) { - case "hasPermission" -> values.getOrDefault((String) args[0], false); - case "toString" -> "kid"; - case "hashCode" -> System.identityHashCode(proxy); - case "equals" -> proxy == args[0]; - default -> throw new UnsupportedOperationException(method.getName()); - }); - } - - @Test - void anOldDenyOnADefaultOnNodeStillDenies() { - List log = new ArrayList<>(); - Perms.logTo(log::add); - // A children's group had bluemaphud.share.send set to false; the new node is still at its default, true. - Permissible kid = with(Map.of("blueminimap.share.send", true, "bluemaphud.share.send", false)); - assertFalse(Perms.has(kid, "blueminimap.share.send")); - assertEquals(1, log.size()); - assertTrue(log.get(0).contains("set blueminimap.share.send"), log.get(0)); - } - - @Test - void aNewDenyOnADefaultOnNodeDenies() { - Permissible p = with(Map.of("blueminimap.share.receive", false, "bluemaphud.share.receive", true)); - assertFalse(Perms.has(p, "blueminimap.share.receive")); - } - - @Test - void untouchedDefaultsAgree() { - Permissible p = with(Map.of("blueminimap.use", true, "bluemaphud.use", true)); - assertTrue(Perms.has(p, "blueminimap.use")); - assertFalse(Perms.has(with(Map.of()), "blueminimap.admin")); - } - - @Test - void anOldAdminGrantStillGrants() { - Permissible mod = with(Map.of("bluemaphud.admin", true)); - assertTrue(Perms.has(mod, "blueminimap.admin")); - } - - @Test - void everyDeclaredNodeHasAnOldTwinWithTheSameDefault() throws Exception { - String yml = new String(PermsTest.class.getResourceAsStream("/paper-plugin.yml").readAllBytes()); - for (String node : List.of("use", "fullscreen", "seeplayers", "share.send", "share.receive", "admin")) { - int now = yml.indexOf(" blueminimap." + node + ":\n"), old = yml.indexOf(" bluemaphud." + node + ":\n"); - assertTrue(now >= 0 && old >= 0, node); - String d1 = yml.substring(yml.indexOf("default:", now)).split("\n")[0]; - String d2 = yml.substring(yml.indexOf("default:", old)).split("\n")[0]; - assertEquals(d1, d2, node); - } - } - - @Test - void aNewDenyWithTheOldNodeAtItsDefaultLogsNothing() { - List log = new ArrayList<>(); - Perms.logTo(log::add); - // The admin set the new name to false; the old one is still at its default, true. Nothing to tell them. - Permissible p = with(Map.of("blueminimap.seeplayers", false, "bluemaphud.seeplayers", true)); - assertFalse(Perms.has(p, "blueminimap.seeplayers")); - assertTrue(log.isEmpty(), String.valueOf(log)); - } - - @Test - void aNewAdminGrantWithTheOldNodeAtItsDefaultLogsNothing() { - List log = new ArrayList<>(); - Perms.logTo(log::add); - Permissible p = with(Map.of("blueminimap.admin", true, "bluemaphud.admin", false)); - assertTrue(Perms.has(p, "blueminimap.admin")); - assertTrue(log.isEmpty(), String.valueOf(log)); - } -} diff --git a/src/test/java/com/extantape/blueminimap/share/HouseRulesGuardTest.java b/src/test/java/com/extantape/blueminimap/share/HouseRulesGuardTest.java deleted file mode 100644 index a6a84bc..0000000 --- a/src/test/java/com/extantape/blueminimap/share/HouseRulesGuardTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.extantape.blueminimap.share; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class HouseRulesGuardTest { - @Test - void sharingIsOffWithHouseRulesOlderThan02() { - assertNotNull(ShareService.olderHouseRules("0.1.1")); - assertNotNull(ShareService.olderHouseRules("0.1.0")); - assertNotNull(ShareService.olderHouseRules("something odd"), "an unreadable version fails closed"); - } - - @Test - void sharingIsOnWithHouseRules02OrNewerOrWithout() { - assertNull(ShareService.olderHouseRules("0.2.0")); - assertNull(ShareService.olderHouseRules("0.2.1-SNAPSHOT")); - assertNull(ShareService.olderHouseRules("1.0.0")); - assertNull(ShareService.olderHouseRules(null)); - } -} diff --git a/test/live/README.md b/test/live/README.md index 9c6f4fa..74fbd46 100644 --- a/test/live/README.md +++ b/test/live/README.md @@ -1,6 +1,6 @@ # Live tests -These run BlueMinimap on a real Paper server with real BlueMap tiles, and drive it with a protocol bot. Every frame the bot receives is decoded and compared cell by cell with BlueMap's tile files on disk. The unit tests in `src/test` cover the rendering maths; these cover everything that needs a server. +These run BlueMapMini on a real Paper server with real BlueMap tiles, and drive it with a protocol bot. Every frame the bot receives is decoded and compared cell by cell with BlueMap's tile files on disk. The unit tests in `src/test` cover the rendering maths; these cover everything that needs a server. `run.sh` builds one throwaway server on 127.0.0.1, generates a small world with a fixed seed, has BlueMap render it, runs the tests you name, and deletes the server afterwards, including when a test fails. Only one server runs at a time. @@ -8,7 +8,7 @@ These run BlueMinimap on a real Paper server with real BlueMap tiles, and drive - **Real:** Paper, BlueMap, the plugin jar, the generated pack, BlueMap's tiles and SQL storage. - **A bot, not the game:** the client is [mineflayer](https://github.com/PrismarineJS/mineflayer), which speaks the 1.21.11 protocol, so it joins 26.x through ViaVersion and ViaBackwards. It doesn't draw anything. Frames are decoded with a model of the client's font rules. -- **Real HouseRules** in the `houserules` test only. +- **Real Mayor** in the `mayor` test only. - **Simulated:** the helper plugin acts like other plugins: vanish, boss bars, permissions, POI markers, a pack sent with the old one-pack method the way Magic does it, and a chat rules plugin that filters `CoordinateShareEvent`. The pack host for `public-url` is a local stand-in. - **Not covered:** pressing the buttons in the `/hud share` dialog. The bot checks the dialog it's sent, but its protocol library has no packet for clicking one. The buttons run Paper's own callbacks into the same code `/hud share ` and `/hud share everyone` test. - **Optional:** the font check runs the real Minecraft client's font code on the pack, if you give it a client classpath (see below). It's skipped otherwise, and the summary says so. @@ -33,14 +33,14 @@ You need Java 25, Node 22 or newer, and about 1 GB of disk per server while it r | `ViaVersion.jar`, `ViaBackwards.jar` | Builds that support your server version, from [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) and [ViaBackwards](https://hangar.papermc.io/ViaVersion/ViaBackwards). | | `Magic.jar` (optional) | Only for the real-Magic check in `storage.js`. Skipped without it. | -3. Running a server means accepting the [Minecraft EULA](https://aka.ms/MinecraftEULA), and BlueMap downloads the client's resources under the same terms. `run.sh` won't start until you set `BMH_ACCEPT_EULA=1`. +3. Running a server means accepting the [Minecraft EULA](https://aka.ms/MinecraftEULA), and BlueMap downloads the client's resources under the same terms. `run.sh` won't start until you set `BMM_ACCEPT_EULA=1`. ## Running ```bash -BMH_ACCEPT_EULA=1 test/live/run.sh 26.3 # the full suite -BMH_ACCEPT_EULA=1 test/live/run.sh 26.3 suite packurl storage load backoff -BMH_ACCEPT_EULA=1 test/live/run.sh 26.1.2 suite:coordsonly,onebar +BMM_ACCEPT_EULA=1 test/live/run.sh 26.3 # the full suite +BMM_ACCEPT_EULA=1 test/live/run.sh 26.3 suite packurl storage load backoff +BMM_ACCEPT_EULA=1 test/live/run.sh 26.1.2 suite:coordsonly,onebar ``` | Test | What it checks | Time | @@ -48,21 +48,21 @@ BMH_ACCEPT_EULA=1 test/live/run.sh 26.1.2 suite:coordsonly,onebar | `suite` | Everything players see: map accuracy, icons, the readout, the clock, themes, sharing, hiding rules, one boss bar, updates, pack handling, reloads, icons, action bar, HTTP source, bad data. Pick groups with `suite:`, such as `suite:clock,themes,share`. | about 20 min | | `suite:clockrate` | Not part of `suite`: what the clock costs a player standing still, at steps of 1, 5 and 10 in-game minutes. | 4 min | | `load` | 20 moving bots for a minute: update size, build time and tick. Results depend on how busy the machine is. | 2 min | -| `packurl` | `public-url` with `{sha1}`, the hosted-pack check, and `/blueminimap pack export`. | 3 min | +| `packurl` | `public-url` with `{sha1}`, the hosted-pack check, and `/bluemapmini pack export`. | 3 min | | `storage` | BlueMap starting 8 times next to the plugin, and BlueMap on SQLite read through the HTTP source. | 6 min | | `backoff` | Another plugin owning `/map` and `/hud`, and getting them back once it's removed. | 2 min | -| `houserules` | The real HouseRules with BlueMinimap: shares stay inside chat circles with HouseRules 0.2, sharing turns itself off with HouseRules 0.1.1, and works without HouseRules. Needs `BMH_HOUSERULES_JAR` and `BMH_HOUSERULES_OLD_JAR`; skipped otherwise. | 3 min | +| `mayor` | The real Mayor with BlueMapMini: shares stay inside chat circles with Mayor 0.5; without Mayor, sharing stays off by default and works with `share.require-mayor: false`. Needs `BMM_MAYOR_JAR`. | Logs go to `test/live/work/server--.log`. Each test prints a summary, with any failures and skipped checks. -Ports default to 25693 (game), 8193 (pack), 8123 (BlueMap) and 8293 (stand-in host). Change them with `BMH_PORT`, `BMH_PACK_PORT`, `BMH_WEB_PORT` and `BMH_HOST_PORT`. `BMH_LIVE_DIR` moves the work folder. +Ports default to 25693 (game), 8193 (pack), 8123 (BlueMap) and 8293 (stand-in host). Change them with `BMM_PORT`, `BMM_PACK_PORT`, `BMM_WEB_PORT` and `BMM_HOST_PORT`. `BMM_LIVE_DIR` moves the work folder. ## The font check `fontcheck/FontCheck.java` feeds the pack through the Minecraft client's own metadata and font loading code, without starting the game, and the suite compares the client's glyph advances with its own. To run it, download the client jar and its libraries for a version through the launcher's version manifest, then: ```bash -export BMH_CLIENT_CP="/path/to/client.jar:/path/to/libraries/*" +export BMM_CLIENT_CP="/path/to/client.jar:/path/to/libraries/*" ``` ## The test-only plugins diff --git a/test/live/backoff.js b/test/live/backoff.js index 79cb1c3..e1a8995 100644 --- a/test/live/backoff.js +++ b/test/live/backoff.js @@ -1,4 +1,4 @@ -// Command back-off: with an old-style plugin owning /map and /hud, BlueMinimap must take its next names, and +// Command back-off: with an old-style plugin owning /map and /hud, BlueMapMini must take its next names, and // get the short names back once that plugin is gone. // Usage: node backoff.js

, with and relative to the work folder. const { Server, Bot, check, section, summary, sleep, until } = require('./lib.js'); @@ -21,22 +21,22 @@ async function say(bot, command, pattern) { await s.start(); await sleep(4000); s.cmd('op Tester'); const names = s.log.match(/Commands: fullscreen map is (\S+), minimap is (\S+)\./); - check('BlueMinimap backs off to /worldmap and /minimap', names && names[1] === '/worldmap' && names[2] === '/minimap', names?.[0]); + check('BlueMapMini backs off to /worldmap and /minimap', names && names[1] === '/worldmap' && names[2] === '/minimap', names?.[0]); const bot = new Bot('Tester', port); await Promise.race([bot.spawned, sleep(20000)]); await until(() => bot.packBytes, 8000); await sleep(1000); check('/map still reaches the other plugin', await say(bot, '/map', /CONFLICT PLUGIN OWNS \/map/)); check('/hud still reaches the other plugin', await say(bot, '/hud', /CONFLICT PLUGIN OWNS \/hud/)); - check('/minimap reaches BlueMinimap', await say(bot, '/minimap off', /Minimap off/)); - check('/blueminimap hud always works', await say(bot, '/blueminimap hud on', /Minimap on/)); - check('/blueminimap:hud always works', await say(bot, '/blueminimap:hud off', /Minimap off/)); - await say(bot, '/blueminimap:hud on', /Minimap on/); + check('/minimap reaches BlueMapMini', await say(bot, '/minimap off', /Minimap off/)); + check('/bluemapmini hud always works', await say(bot, '/bluemapmini hud on', /Minimap on/)); + check('/bluemapmini:hud always works', await say(bot, '/bluemapmini:hud off', /Minimap off/)); + await say(bot, '/bluemapmini:hud on', /Minimap on/); await bot.cleanQuit(); await s.stop(); section('The other plugin is removed'); fs.rmSync(installed, { force: true }); await s.start(); await sleep(4000); const back = s.log.match(/Commands: fullscreen map is (\S+), minimap is (\S+)\./); - check('BlueMinimap takes /map and /hud again after a restart', back && back[1] === '/map' && back[2] === '/hud', back?.[0]); + check('BlueMapMini takes /map and /hud again after a restart', back && back[1] === '/map' && back[2] === '/hud', back?.[0]); await s.stop(); } catch (e) { check('Back-off test finished', false, e.stack?.slice(0, 300)); diff --git a/test/live/conflict/src/main/java/com/extantape/blueminimap/livetest/Conflict.java b/test/live/conflict/src/main/java/com/extantape/blueminimap/livetest/Conflict.java index 5b25cc4..cdd2f9e 100644 --- a/test/live/conflict/src/main/java/com/extantape/blueminimap/livetest/Conflict.java +++ b/test/live/conflict/src/main/java/com/extantape/blueminimap/livetest/Conflict.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.livetest; +package com.extantape.bluemapmini.livetest; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; diff --git a/test/live/conflict/src/main/resources/plugin.yml b/test/live/conflict/src/main/resources/plugin.yml index 90836ca..b27d45f 100644 --- a/test/live/conflict/src/main/resources/plugin.yml +++ b/test/live/conflict/src/main/resources/plugin.yml @@ -1,8 +1,8 @@ # Test only. Deliberately an old-style Bukkit plugin that owns /map and /hud in plugin.yml, so the live -# tests can check that BlueMinimap backs off to other names. Never install it on a real server. +# tests can check that BlueMapMini backs off to other names. Never install it on a real server. name: LiveTestConflict version: '1' -main: com.extantape.blueminimap.livetest.Conflict +main: com.extantape.bluemapmini.livetest.Conflict api-version: '26.1' commands: map: {} diff --git a/test/live/fontcheck/FontCheck.java b/test/live/fontcheck/FontCheck.java index 7e47282..bedb9ec 100644 --- a/test/live/fontcheck/FontCheck.java +++ b/test/live/fontcheck/FontCheck.java @@ -17,7 +17,7 @@ /** * Feeds a resource pack through the game's own metadata and font loading code, without starting the game, - * and writes each glyph's advance as JSON. Run by the live suite when BMH_CLIENT_CP is set: + * and writes each glyph's advance as JSON. Run by the live suite when BMM_CLIENT_CP is set: * {@code java -cp FontCheck.java } */ public class FontCheck { @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { StringBuilder out = new StringBuilder("{"); boolean firstFont = true; for (String path : new TreeSet<>(files.keySet())) { - if (!path.startsWith("assets/blueminimap/font/")) continue; + if (!path.startsWith("assets/bluemapmini/font/")) continue; String name = path.substring(path.lastIndexOf('/') + 1, path.length() - 5); JsonArray providers = JsonParser.parseString(new String(files.get(path), StandardCharsets.UTF_8)).getAsJsonObject().getAsJsonArray("providers"); int glyphs = 0; diff --git a/test/live/helper/src/main/java/com/extantape/blueminimap/livetest/Helper.java b/test/live/helper/src/main/java/com/extantape/bluemapmini/livetest/Helper.java similarity index 97% rename from test/live/helper/src/main/java/com/extantape/blueminimap/livetest/Helper.java rename to test/live/helper/src/main/java/com/extantape/bluemapmini/livetest/Helper.java index 8d6e2a3..c13eeb7 100644 --- a/test/live/helper/src/main/java/com/extantape/blueminimap/livetest/Helper.java +++ b/test/live/helper/src/main/java/com/extantape/bluemapmini/livetest/Helper.java @@ -1,4 +1,4 @@ -package com.extantape.blueminimap.livetest; +package com.extantape.bluemapmini.livetest; import com.flowpowered.math.vector.Vector3d; import de.bluecolored.bluemap.api.BlueMapAPI; @@ -51,7 +51,7 @@ public void execute(CommandSourceStack source, String[] args) { @Override public String permission() { - return "blueminimap.livetest"; + return "bluemapmini.livetest"; } })); } @@ -178,9 +178,9 @@ private void shareFilter(String[] a) { org.bukkit.event.HandlerList.unregisterAll(shareListener); shareMode = a.length > 2 ? a[1] + " " + a[2] : a[1]; if (!a[1].equals("off")) { - getServer().getPluginManager().registerEvent(com.extantape.blueminimap.api.CoordinateShareEvent.class, shareListener, + getServer().getPluginManager().registerEvent(com.extantape.bluemapmini.api.CoordinateShareEvent.class, shareListener, org.bukkit.event.EventPriority.NORMAL, (listener, event) -> { - var share = (com.extantape.blueminimap.api.CoordinateShareEvent) event; + var share = (com.extantape.bluemapmini.api.CoordinateShareEvent) event; say("share from " + share.getSender().getName() + " at " + share.getX() + " " + share.getY() + " " + share.getZ() + " to " + share.getRecipients().stream().map(Player::getName).sorted().toList()); if (shareMode.equals("cancel")) share.setCancelled(true); diff --git a/test/live/helper/src/main/resources/paper-plugin.yml b/test/live/helper/src/main/resources/paper-plugin.yml index 382c2f8..d50e6f3 100644 --- a/test/live/helper/src/main/resources/paper-plugin.yml +++ b/test/live/helper/src/main/resources/paper-plugin.yml @@ -1,6 +1,6 @@ name: LiveTestHelper version: '1' -main: com.extantape.blueminimap.livetest.Helper +main: com.extantape.bluemapmini.livetest.Helper api-version: '26.1' description: Test only. Lets the live tests act like other plugins. Never install it on a real server. dependencies: @@ -10,7 +10,7 @@ dependencies: required: true join-classpath: true # For the share tests: listens to CoordinateShareEvent the way a server's chat rules plugin would. - BlueMinimap: + BlueMapMini: load: BEFORE required: true join-classpath: true diff --git a/test/live/lib.js b/test/live/lib.js index 476d0fd..dc9e87b 100644 --- a/test/live/lib.js +++ b/test/live/lib.js @@ -1,8 +1,8 @@ -// Live test kit for BlueMinimap: server control, a protocol bot, a frame decoder, and an independent +// Live test kit for BlueMapMini: server control, a protocol bot, a frame decoder, and an independent // reading of BlueMap's tiles to compare frames against. See README.md in this folder. const path = require('path'), fs = require('fs'), zlib = require('zlib'), cp = require('child_process'), crypto = require('crypto'); /** Holds the server jars, plugins and throwaway servers. Never committed. */ -const ROOT = path.resolve(process.env.BMH_LIVE_DIR || path.join(__dirname, 'work')); +const ROOT = path.resolve(process.env.BMM_LIVE_DIR || path.join(__dirname, 'work')); /** The repository this kit lives in. */ const REPO = path.resolve(__dirname, '..', '..'); const mineflayer = require('mineflayer'); @@ -81,10 +81,10 @@ class Server { await sleep(500); } errors(from = 0) { - return this.log.slice(from).split('\n').filter((l) => /\bERROR\b|Exception|\bat com\.extantape|BlueMinimap.*WARN|WARN.*BlueMinimap/.test(l) && !/Advanced terminal/.test(l)); + return this.log.slice(from).split('\n').filter((l) => /\bERROR\b|Exception|\bat com\.extantape|BlueMapMini.*WARN|WARN.*BlueMapMini/.test(l) && !/Advanced terminal/.test(l)); } path(...p) { return path.join(this.dir, ...p); } - setConfig(edits) { editYaml(this.path('plugins/BlueMinimap/config.yml'), edits); } + setConfig(edits) { editYaml(this.path('plugins/BlueMapMini/config.yml'), edits); } } /** Sets scalar values by dotted path, keeping everything else in the file. */ @@ -146,7 +146,7 @@ class Pack { this.files = unzipAll(tmp); fs.unlinkSync(tmp); this.fonts = {}; for (const [name, data] of Object.entries(this.files)) { - const m = name.match(/^assets\/blueminimap\/font\/(\w+)\.json$/); + const m = name.match(/^assets\/bluemapmini\/font\/(\w+)\.json$/); if (m) this.fonts[m[1]] = this.loadFont(JSON.parse(data.toString('utf8'))); } } @@ -155,7 +155,7 @@ class Pack { for (const p of font.providers) { if (p.type === 'space') { for (const [k, v] of Object.entries(p.advances)) map.set(k.codePointAt(0), { kind: 'space', advance: v }); continue; } if (p.ascent > p.height) throw new Error(`ascent ${p.ascent} > height ${p.height}`); - const file = 'assets/blueminimap/textures/' + p.file.split(':')[1]; + const file = 'assets/bluemapmini/textures/' + p.file.split(':')[1]; const sheet = sheets[file] || (sheets[file] = readPng(this.files[file])); const rows = p.chars.map((s) => [...s]), cols = rows[0].length; const cw = sheet.w / cols, ch = sheet.h / rows.length, scale = p.height / ch; @@ -312,7 +312,7 @@ class Bot { if (this.downloadStatus === 200) { const res = await fetch(p.url), buf = Buffer.from(await res.arrayBuffer()); this.packSha = crypto.createHash('sha1').update(buf).digest('hex'); - if (p.url.includes('blueminimap')) { this.packUrl = p.url; this.packBytes = buf; } + if (p.url.includes('bluemapmini')) { this.packUrl = p.url; this.packBytes = buf; } } const send = (result) => this.bot._client.write('resource_pack_receive', { uuid: p.uuid, result }); if (this.mode === 'ignore') return; diff --git a/test/live/houserules.js b/test/live/mayor.js similarity index 61% rename from test/live/houserules.js rename to test/live/mayor.js index ef226a1..4a5f25a 100644 --- a/test/live/houserules.js +++ b/test/live/mayor.js @@ -1,12 +1,12 @@ -// BlueMinimap with the real HouseRules: shares follow chat circles, and with a HouseRules too old to see BlueMinimap's -// share event, sharing is off rather than unfiltered. -// Usage: node houserules.js , and relative to the work folder. +// BlueMapMini with the real Mayor: shares follow chat circles. Without Mayor, sharing is off by default rather than +// unfiltered, and a server without chat rules can turn it on with share.require-mayor: false. +// Usage: node mayor.js , and relative to the work folder. const { Server, Bot, check, section, summary, sleep, until } = require('./lib.js'); const fs = require('fs'); -const [dir, jar, portS, newJar, oldJar] = process.argv.slice(2); +const [dir, jar, portS, newJar] = process.argv.slice(2); const port = +portS; const s = new Server(dir, jar, port); -const installed = s.path('plugins', 'HouseRules.jar'); +const installed = s.path('plugins', 'Mayor.jar'); // Made-up circles. The overworld is circle-only, so only circles decide who hears whom there. const CONFIG = 'circles: [red, blue]\ncircle-only-worlds: [world]\n'; @@ -32,14 +32,14 @@ async function joinAll(names) { (async () => { let bots = {}; try { - section('BlueMinimap with HouseRules 0.2: shares follow the circles'); + section('BlueMapMini with Mayor 0.5: shares follow the circles'); fs.copyFileSync(newJar, installed); - fs.mkdirSync(s.path('plugins', 'HouseRules'), { recursive: true }); - fs.writeFileSync(s.path('plugins', 'HouseRules', 'config.yml'), CONFIG); + fs.mkdirSync(s.path('plugins', 'Mayor'), { recursive: true }); + fs.writeFileSync(s.path('plugins', 'Mayor', 'config.yml'), CONFIG); await s.start(); await sleep(4000); - check('HouseRules found BlueMinimap\'s share event', /BlueMinimap found: coordinate shares follow the same rules as chat/.test(s.log)); + check('Mayor found BlueMapMini\'s share event', /BlueMapMini found: coordinate shares follow the same rules as chat/.test(s.log)); bots = await joinAll(['Tester', 'Alex', 'Blair', 'Casey']); - for (const [who, circle] of [['Tester', 'red'], ['Alex', 'red'], ['Blair', 'blue']]) s.cmd(`bmt perm ${who} houserules.circle.${circle} true`); + for (const [who, circle] of [['Tester', 'red'], ['Alex', 'red'], ['Blair', 'blue']]) s.cmd(`bmt perm ${who} mayor.circle.${circle} true`); await sleep(800); let marks = Object.fromEntries(Object.entries(bots).map(([n, b]) => [n, b.chat.length])); const sent = await say(bots.Tester, '/hud share everyone', /Sent your coordinates|weren't sent|can receive/); @@ -53,33 +53,33 @@ async function joinAll(names) { for (const b of Object.values(bots)) await b.cleanQuit(); await s.stop(); - section('BlueMinimap with HouseRules 0.1.1: sharing is off, not unfiltered'); - fs.copyFileSync(oldJar, installed); + section('BlueMapMini without Mayor, default settings: sharing is off, not unfiltered'); + fs.rmSync(installed, { force: true }); await s.start(); await sleep(4000); - bots = await joinAll(['Tester', 'Alex', 'Blair']); - s.cmd('bmt perm Tester houserules.circle.red true'); s.cmd('bmt perm Alex houserules.circle.red true'); await sleep(800); - marks = Object.fromEntries(Object.entries(bots).map(([n, b]) => [n, b.chat.length])); - const mark = s.mark(); + bots = await joinAll(['Tester', 'Alex']); + let m = bots.Alex.chat.length; + let mark = s.mark(); const off = await say(bots.Tester, '/hud share everyone', /Sent your coordinates|off on this server|can receive/); await sleep(600); check('The sender is told sharing is off', /Sharing coordinates is off on this server for now/.test(off || ''), off); - check('and nobody receives anything', !heard(bots.Alex, marks.Alex) && !heard(bots.Blair, marks.Blair)); - check('The log tells the admin to update HouseRules', /HouseRules 0\.1\.1 can't see BlueMinimap's shares.*Update HouseRules to 0\.2\.0/.test(s.since(mark))); + check('and nobody receives anything', !heard(bots.Alex, m)); + check("The log says Mayor isn't installed", /follows Mayor's chat rules and Mayor isn't installed/.test(s.since(mark))); for (const b of Object.values(bots)) await b.cleanQuit(); await s.stop(); - section('BlueMinimap without HouseRules: sharing works'); - fs.rmSync(installed, { force: true }); + section('BlueMapMini without Mayor, require-mayor: false: sharing works'); + const cfg = s.path('plugins', 'BlueMapMini', 'config.yml'); + fs.writeFileSync(cfg, fs.readFileSync(cfg, 'utf8').replace('require-mayor: true', 'require-mayor: false')); await s.start(); await sleep(4000); bots = await joinAll(['Tester', 'Alex']); - const m = bots.Alex.chat.length; + m = bots.Alex.chat.length; const plain = await say(bots.Tester, '/hud share everyone', /Sent your coordinates|off on this server|can receive/); await sleep(600); - check('control: without HouseRules a share goes through', /Sent your coordinates/.test(plain || '') && heard(bots.Alex, m), plain); + check('A server without chat rules can share', /Sent your coordinates/.test(plain || '') && heard(bots.Alex, m), plain); for (const b of Object.values(bots)) await b.cleanQuit(); await s.stop(); } catch (e) { - check('houserules finished', false, e.stack?.slice(0, 400)); + check('mayor finished', false, e.stack?.slice(0, 400)); for (const b of Object.values(bots)) try { await b.cleanQuit(); } catch {} try { await s.stop(); } catch {} } diff --git a/test/live/package-lock.json b/test/live/package-lock.json index be99f60..7d6710d 100644 --- a/test/live/package-lock.json +++ b/test/live/package-lock.json @@ -1,10 +1,10 @@ { - "name": "blueminimap-live-tests", + "name": "bluemapmini-live-tests", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "blueminimap-live-tests", + "name": "bluemapmini-live-tests", "license": "MIT", "dependencies": { "mineflayer": "4.39.0" diff --git a/test/live/package.json b/test/live/package.json index 498204a..5645301 100644 --- a/test/live/package.json +++ b/test/live/package.json @@ -1,7 +1,7 @@ { - "name": "blueminimap-live-tests", + "name": "bluemapmini-live-tests", "private": true, - "description": "Live tests for BlueMinimap: throwaway Paper servers driven by a protocol bot.", + "description": "Live tests for BlueMapMini: throwaway Paper servers driven by a protocol bot.", "license": "MIT", "type": "commonjs", "engines": { diff --git a/test/live/packurl.js b/test/live/packurl.js index 38b8973..1887013 100644 --- a/test/live/packurl.js +++ b/test/live/packurl.js @@ -1,4 +1,4 @@ -// Live test for pack.public-url with {sha1}, the hosted-pack check, and /blueminimap pack export. +// Live test for pack.public-url with {sha1}, the hosted-pack check, and /bluemapmini pack export. // Usage: node packurl.js