ResourcePackManager 2.0.0:
- [New] Multi-module project layout — `resourcepackmanager-bukkit` (backend), `resourcepackmanager-bungee` and `resourcepackmanager-velocity` (proxy plugins for BungeeCord / Waterfall and Velocity), `resourcepackmanager-bedrock` (Geyser / Bedrock conversion), `resourcepackmanager-http-common` (shared HTTP + Magmaguy RSP client), `resourcepackmanager-mixer` (platform-neutral pack merge engine), `resourcepackmanager-proxy-common` (Geyser session binding + network sync). Single backend jar still drops into `plugins/`; proxy jars auto-extract into the proxy's `plugins/` on first boot.
- [New] Network mode — Velocity, BungeeCord, and Waterfall plugins detect every connected backend, fetch each backend's mixed Java and Bedrock packs over an embedded HTTP server, merge them per-network, push the merged Java pack to Java players, and serve the merged Bedrock pack to Geyser sessions. Backends running behind a proxy skip their own `setResourcePack` so the proxy is the sole pack source. Detected automatically via Floodgate-without-Geyser, `spigot.yml settings.bungeecord`, or `paper-global.yml proxies.velocity.enabled`.
- [New] Floodgate-key-derived network key — `NetworkKeyResolver` hashes `plugins/floodgate/key.pem` to a UUID-form key shared automatically across every proxy and backend on the same Floodgate network. No more pasting a key into the proxy config; separate Floodgate networks get separate keys for free. Setup collapses to "drop jars and restart."
- [New] Proxy ↔ backend Bedrock pack delivery — backends serve their per-backend Bedrock pack zip at `/bedrock.zip` (and mappings at `/mappings.json`) over an embedded `PackHttpServer`; the proxy polls each backend via `BackendMetadataPoller` (cheap 304 Not Modified after the first cycle) and ships URLs to Bedrock clients through `GeyserBinder`. Plugin-messaging fallback ships the URL if HTTP polling fails.
- [New] Three-surface warning system — when a Bedrock session loads before a pack is ready, the Bedrock player gets a Cumulus "OK — I'll Reconnect" modal, every online Java player gets a chat warning naming the affected player, and the proxy console gets a multi-line banner. Bookended by a fire-once green checkmark on first successful merge (with pack size + sha1 prefix). Backend-side, `AutoHost.sendResourcePack` fires console banner + per-player chat warning when a player joins before mix+upload finishes.
- [New] Self-host fallback — `AutoHost` now spins up `PackHttpServer` and serves the Java pack from this host if the magmaguy.com upload fails. New keys: `selfHostEnabled` (default true), `selfHostPort` (-1 = auto-derive MC port + `networkHttpOffset-v2`), `selfHostExternalHost` (auto-detected via ipify / checkip → `Bukkit.getIp` → `getLocalHost`), `selfHostForce` (bypass remote entirely), `preferSelfHost` (try self-host first, fall back to remote on reachability / HEAD-probe failure — default true).
- [New] `/rspm status` command — single-shot operator dump of version, deploy mode (standalone vs network-backend), resolved network key (masked last-4), Java pack path / size / sha1, Bedrock pack + Geyser mappings state, active hosting URL, all relevant config flags, and Floodgate / Geyser integration sanity. Mirrored on Velocity and Bungee proxies via `ProxyStatusRenderer` so both sides of the wire share output layout.
- [New] Compatible-plugin premades for `BetterStructures`, `CannonRTP`, `EternalTD`, `MegaBlockSurvivors`, and `ResurrectionChest`.
- [New] Bedrock identifier hashing via `BedrockShortName` — Bedrock pack file paths and Geyser mapping IDs collapse to 8-char SHA-256 hex prefixes, eliminating Bedrock's "80+ char path" warning flood and keeping identifiers opaque to pack inspection.
- [New] BungeeCord pack push uses native Bungee Protocol API via reflection — Protocolize is no longer required (was a hard soft-dep for `PostLoginEvent` injection). Supports 1.21.4+ packet IDs and emits one `ProtocolMapping` per protocol-range start.
- [Fix] `BackendMetadataPoller` deduplicates backends by `host

ort` and `NetworkSync` deduplicates by backend UUID — multi-host setups no longer double-poll or double-merge the same backend.
- [Fix] AutoHost player resource pack broadcasts wrapped in the sync scheduler — no more main-thread violations when the upload completes on the HTTP I/O thread.
- [Fix] `PackHttpServer` shuts down its executor on close — fixes the thread leak that accumulated one executor per `/rspm reload`.
- [Fix] `MagmaguyRspClient` (extracted from `AutoHost`) takes an injected `Logger` so log lines keep the plugin prefix, and surfaces SHA1-mismatch session errors instead of swallowing them.
- [Fix] `GeyserBinder` construction is now guarded on Geyser presence — proxy plugins boot cleanly on networks that haven't installed Geyser yet.
- [Fix] Mixer collision-log entries no longer dropped during the `MixEngine` / `MergeOperations` refactor; collision log routed through the engine wrapper; stale staging cleanup preserved; cluster ordering preserved.
- [Fix] Backend boot speed: initial pack-availability poll 5s → 2s, poll interval 30s → 5s, `STABLE_CYCLES_REQUIRED` 2 → 1 (BedrockZip writes via temp + atomic rename so torn reads can't occur). Cold-start time to first usable merged pack drops from ~65s to ~7s when backends are already up. Steady-state poll cost ~0 bytes per cycle via `If-Modified-Since`.
- [Fix] Maven `copy-proxy-jars` bound to `prepare-package` so `mvn compile` no longer fails looking for proxy artifacts.
- [Fix] Proxy build relocates `gson` to avoid classpath conflicts with Velocity / Bungee's bundled copies.
- [Tweak] Bedrock-conversion console output drastically less noisy when Geyser is installed — introduced `BedrockLog.debug(...)` gated on a new `bedrockConverterDebug` config flag (default `false`). High-volume informational sites are now debug-only: per-item "no Geyser equivalent" notices, per-bone unsupported-property warnings, "Detected Geyser at …" / "Geyser mappings deployed to …" status lines on every reload cycle, "Wrote merged Geyser mappings: N entries", per-texture "Texture not found", duplicate-mapping skip notices, face-rotation-not-multiple-of-90, equipment-texture-not-found, and the entire `ItemModelTreeWalker` per-node noise tree (~13 sites). Genuine errors (I/O failures, atlas-exceeds-max, AssetResolver cycle / depth violations, per-model conversion-step failures) and the per-cycle "Bedrock conversion complete: N mappings" summary stay at INFO / WARN.
- [Tweak] All modules and packages renamed from shortened `rpm-*` to unshortened `resourcepackmanager-*` for consistency with the plugin name.
- [Tweak] Module rename of `rpm-mixer` to `resourcepackmanager-mixer`; pure merge ops moved out of the Bukkit module into the platform-neutral mixer module so the proxy can mix without Bukkit on the classpath. `Mix.java` is now a thin Bukkit wrapper over `MixEngine`. Added `MergeOperationsTest` unit tests.
- [Tweak] `networkHttpOffset-v2` key with default `1` (was `networkHttpOffset` with default `100`). Default `+100` fell outside the per-container port range on shared / managed hosting (Pterodactyl tenants, alienhost.me, etc.); `+1` fits even the narrowest allocations. Old v1 key is intentionally not read — operators upgrading get the v2 default written on next boot.
- [Tweak] `network-key` is no longer a config option — derived from Floodgate's `key.pem` at every component, so the old "paste this key into the proxy config" misconfiguration vector is gone. Persisted proxy-side as a fallback for first-boot when Floodgate isn't installed yet.
- [Tweak] Plugin-messaging cache replaced with backend HTTP metadata endpoint — proxy no longer holds stale per-player state across reconnects.
- [Tweak] Network-mode documentation collapsed to "drop the jars in, restart" walkthroughs (server-side API contract documented separately for plugin devs integrating against RSPM).
- [Tweak] Various MagmaCore library improvements (Lua scripting engine + zones moved to MagmaCore, EasyMinecraftGoals absorbed, NMS v26 / Paper 26.1 support, type-based `EntityDimensions` reflection with cached lookup, `WorldFolderResolver` and Paper-migration debris quarantine, `TemporaryBlockManager`, `SetupMenuBuilder` + `InfoButtonFactory` + `NightbreakSetupIcons` shared UI, `ContainerAllowlist` / `WorldProtectionRules` instance protection, `MagmaCore.exportSharedAssets` / `enableWorldProtections` / `isShutdownRequested`, `AdvancedCommand` optional-argument support, `LocationAPI` with WorldGuard + GriefPrevention providers, Nightbreak token-change subscribers, `ClientboundEntityPositionSyncPacket` adoption on 1.21.2+ with Bedrock `ClientboundBundlePacket` skip, ArmorStand HeadPose force-send every tick for Bedrock attachable rebind, `DAMAGE_INDICATOR` outbound particle-count clamp, per-plugin Netty handler name in `PacketInteractionListener`, lazy Lua field support, `ZipFile` STORED-with-EXT-descriptor fix, dedup / rate-limited Nightbreak auth-failure logs, three-tier BedrockChecker detection — name pattern `^\..*\d{4}$` + UUID-MSB == 0 + case-insensitive plugin lookup — so Bedrock viewers are detected even when Floodgate hasn't registered them yet).