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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ jobs:
- run: ./gradlew build
- uses: actions/upload-artifact@v4
with:
name: BlueMinimap
name: BlueMapMini
path: build/libs/*.jar
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" build/libs/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"
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
68 changes: 29 additions & 39 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
}

group = "com.extantape"
version = "0.2.1"
version = "0.3.0"

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

tasks.jar {
archiveBaseName.set("BlueMinimap")
archiveBaseName.set("BlueMapMini")
from("LICENSE")
}
10 changes: 5 additions & 5 deletions docs/26x-audit.md
Original file line number Diff line number Diff line change
@@ -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

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

Expand Down Expand Up @@ -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.
4 changes: 4 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
2 changes: 1 addition & 1 deletion docs/releases/v0.2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
15 changes: 15 additions & 0 deletions docs/releases/v0.3.0.md
Original file line number Diff line number Diff line change
@@ -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.
12 changes: 5 additions & 7 deletions docs/test-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <names>` and `/hud share everyone` test.
Expand Down
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
rootProject.name = "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")
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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"));
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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);
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/extantape/bluemapmini/Perms.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.extantape.blueminimap.api;
package com.extantape.bluemapmini.api;

import org.bukkit.World;
import org.bukkit.entity.Player;
Expand All @@ -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.
*
* <p>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();
Expand Down
Loading
Loading