BlockProt ReloadedСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачатьСкачать
ВЕРСИИ (17)
release
BlockProt Reloaded 1.4.1-hotfix.2
1.4.1-hotfix.23 окт. 2026 г.235Minecraft: 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3folia, paper, purpur
Что нового
# BlockProt Reloaded 1.4.1-hotfix.2 Release Notes
> **Note:** As a targeted maintenance release, this hotfix does not include a release notes banner.
1.4.1-hotfix.2 fixes locked blocks losing their protection after a server restart. No configuration or data format changes.
## Fixed
- **Hoppers drained locked chests after a restart** ([#22](https://github.com/VictorGugug/BlockProt-Reloaded/issues/22)): the list of protected blocks was rebuilt at startup from a background thread and only from the statistics file, so locks that were not found stayed unprotected until they were locked again. A hopper under a locked chest could then pull its items. Protection is now verified against the block itself whenever a location is not yet known.
- **Same cause, other protections**: after a restart, locked blocks were also exposed to pistons, explosions, fire, redstone, and block breaking by other players. They all use the same check and are fixed together.
- **Double chests**: the second half of a locked double chest was never registered as protected. It is now verified like any other block.
## Verification
Before publication this build was tested in GitHub Actions ([run 37131912140](https://github.com/VictorGugug/BlockProt-Reloaded/actions/runs/37131912140)). Every supported Minecraft version (1.21.7 - 26.3) booted on real Paper, Folia and Purpur servers wherever that software publishes a build (a declared version without a build of its own runs on its newest hotfix), and passed the plugin console diagnostics. On every version the test client supports, a two-player protection test also passed: the owner protects and opens a chest, and a second player can neither open nor break it.
release
BlockProt Reloaded 1.4.0-hotfix
1.4.0-hotfix1 окт. 2026 г.32Minecraft: 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2, 26.3folia, paper, purpur
Что нового
# BlockProt Reloaded 1.4.0-hotfix Release Notes
> **Note:** As a targeted maintenance release, this hotfix does not include a release notes banner.
1.4.0-hotfix fixes the staff tier permissions of 1.4.0 and brings the documentation in line with what the plugin does. Servers that keep `admin_tiers.enabled: false`, the default, see no change in who can do what.
## Fixed
- **Admin hub checks each button**: with `admin_tiers.enabled: true`, any staff tier could open `/bp admin` and use every button in it, including the configuration editor, world protection deletion, reload, and staff role management. Each button of the hub now checks the tier of its action, in the chest menu, the Paper dialog, and the Bedrock form.
- **Lock menu on other players' blocks**: with admin tiers enabled, the Paper dialog and the Bedrock form gave every staff tier owner-level control over other players' blocks, while the chest menu did not. All three now require Tier 2, and Tier 2 can unlock those blocks as documented.
- **Tier 1 works as documented**: Tier 1 now opens `/bp info`, gets a read-only lock menu on other players' blocks with the block info and the audit log, and can teleport from admin block lists.
- **Startup warning**: the warning shown on Spigot and CraftBukkit no longer says support ends in 1.3.6. They are not supported.
## Documentation
- The [README](https://github.com/VictorGugug/BlockProt-Reloaded/blob/main/README.md), the [admin guide](https://github.com/VictorGugug/BlockProt-Reloaded/blob/main/docs/READ_MEs/ADMIN_GUIDE.md), the [player guide](https://github.com/VictorGugug/BlockProt-Reloaded/blob/main/docs/READ_MEs/PLAYER_GUIDE.md), and the download page descriptions now describe commands, permissions, friend levels, staff tiers, and the optional MySQL index as the plugin implements them.
- Timed access and the ImageFrame integration were listed as features but never existed. They are no longer mentioned.
## Testing
- Minecraft 26.1 is now tested on its newest server build, 26.1.2. Earlier test runs skipped it because no server software publishes a build named 26.1.
## Verification
Before publication this build was tested in GitHub Actions ([run 36803357003](https://github.com/VictorGugug/BlockProt-Reloaded/actions/runs/36803357003)). Every supported Minecraft version (1.21.7 - 26.3) booted on real Paper, Folia and Purpur servers wherever that software publishes a build (a declared version without a build of its own runs on its newest hotfix), and passed the plugin console diagnostics. On every version the test client supports, a two-player protection test also passed: the owner protects and opens a chest, and a second player can neither open nor break it.
release
BlockProt Reloaded 1.4.0
1.4.030 сент. 2026 г.12Minecraft: 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2, 26.3folia, paper, purpur
Что нового

# BlockProt Reloaded 1.4.0 Release Notes
Welcome to BlockProt Reloaded 1.4.0. This release launches the two legacy editions, so servers on Minecraft 1.18.2 through 1.21.6 have a supported BlockProt again, and it makes every console line and debug report name the edition that is running.
## Highlights
- **Legacy Editions Launch**: BlockProt Reloaded Legacy 1.4.0.1 covers Minecraft 1.20.5 to 1.21.6 on Java 21, and BlockProt Legacy 1.4.0.1 covers Minecraft 1.18.2 to 1.20.4 on Java 17. Both are published on Modrinth only: [BlockProt Reloaded Legacy](https://modrinth.com/plugin/blockprot-reloaded-legacy) and [BlockProt Legacy](https://modrinth.com/plugin/blockprot-legacy). The [version guide](../READ_MEs/VERSION_GUIDE.md) explains which one to download and how to move between them.
- **Tested On Real Servers**: every supported Minecraft version of the legacy editions is booted on a real Paper server in GitHub Actions, with Folia and Purpur on every version that has a build. Each server passes the plugin console diagnostics and a two-player protection test: the owner protects and opens a chest, and a second player can neither open nor break it. A legacy edition is only published when that run passes.
- **Edition In The Console**: the log prefix, the first start guide, `/bp debug` and the debug reports now show BlockProt Reloaded, BlockProt Reloaded Legacy or BlockProt Legacy instead of always saying BlockProt Reloaded.
- **Version Baseline Unchanged**: BlockProt Reloaded keeps supporting Minecraft 1.21.7 through 26.3. Nothing changes for servers already on 1.3.9.
## Changelog
### Changed
- The console prefix, the first start guide title, `/bp debug` and the debug report header use the name of the running edition.
## Status
- **BEDev**: pre-release builds of 1.4.0 are published on GitHub for testing before the stable release.
- **Maintenance**: the maintainer is taking a break to focus on other projects. Issues and pull requests are welcome for any change and are reviewed as time allows.
## Verification
Before publication this build was tested in GitHub Actions ([run 36665040826](https://github.com/VictorGugug/BlockProt-Reloaded/actions/runs/36665040826)). Every supported Minecraft version (1.21.7 - 26.3) booted on real Paper, Folia and Purpur servers wherever that software publishes a build, and passed the plugin console diagnostics. On every version the test client supports, a two-player protection test also passed: the owner protects and opens a chest, and a second player can neither open nor break it.
release
BlockProt Reloaded 1.3.9
1.3.929 сент. 2026 г.3Minecraft: 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2, 26.3folia, paper, purpur
Что нового

# BlockProt Reloaded 1.3.9 Release Notes
Welcome to BlockProt Reloaded 1.3.9. This release raises the minimum Minecraft version to 1.21.7, so native Paper dialogs are always available and are now built directly into the plugin, gives every paged chest menu the same button layout as the dialogs, and fixes statistics after ownership transfers.
## Highlights
- **Minecraft 1.21.7 Baseline**: 1.3.9 supports Minecraft 1.21.7 through 26.3. Servers on 1.21.1 to 1.21.6 keep using BlockProt Reloaded 1.3.8, and servers on 1.20.5 to 1.21 keep using 1.3.7; starting 1.3.9 on an older version shows which release to use and disables the plugin.
- **Dialogs Built In**: Paper dialogs are compiled directly into the plugin instead of being loaded through reflection from a separate build.
- **Consistent Chest Menus**: every paged chest menu now uses the same bottom row as the dialogs: previous page, the menu's main action, and next page in the center, with Back in the corner.
- **Correct Statistics After Transfers**: transferring a block now moves it from the old owner's statistics to the new owner's instead of counting it for both.
- **Editions**: BlockProt now ships as three editions, each with its own Minecraft range. The plugin knows which edition it is and points servers on another Minecraft version to the right download. See the [version guide](../READ_MEs/VERSION_GUIDE.md).
## Changelog
### Changed
- Raised the minimum supported Minecraft version to 1.21.7.
- Compiled the Paper dialog bridge into the main plugin and removed its separate source set and reflection loading.
- Moved Previous, Next, and the main action of every paged chest menu to slots 48, 50, and 49, with Back or Close in slot 53. List menus now show 45 entries per page.
- Updated Caffeine to 3.3.0, Apache Commons Lang to 3.20.0, and the Floodgate API to 2.2.5.
- Removed the typed inventory view fallback warning and the chest boat type fallback, which only applied to versions older than 1.21.7.
- The plugin JAR name now comes from the `jarBaseName` build property instead of the git branch name, and the Hangar platform versions are read from the `# Supported on` line of `gradle.properties`.
- Particle and enchantment constants that were renamed between Minecraft releases are resolved by name again, so the same code compiles against older Paper APIs.
- The unsupported Minecraft message now names the edition to download, its Minecraft range, and the download and guide links.
### Fixed
- Fixed transferred blocks staying in the previous owner's statistics and increasing the global protected block count on every transfer.
- Fixed transfers leaving the previous owner recorded in the database block index.
- Fixed the statistics list hiding the Previous button on its last page.
- Fixed the entity information menu drawing friends over its navigation row when an entity had more than 36 friends.
- Fixed clicks on empty bottom-row slots of list menus selecting an entry from the page.
- Fixed update checks offering the release of another edition: each edition now only sees its own tagged releases.
### Added
- Added a console diagnostics check that verifies statistics move correctly on ownership transfers.
- Added the edition model: `BlockProt Reloaded`, `BlockProt Reloaded Legacy` and `BlockProt Legacy`, shown in `/bp about`, the boot banner and `/bp debug`.
- Added the `.edition` marker in the plugin data folder. When the edition or the Minecraft version changes between starts, the plugin makes a backup named with both editions and logs it, and it warns when the change is a downgrade.
- Added a console diagnostics check that verifies the edition and its marker.
## Editions
BlockProt Reloaded covers Minecraft 1.21.7 and newer. BlockProt Reloaded Legacy (Minecraft 1.20.5 to 1.21.6) and BlockProt Legacy (Minecraft 1.18.2 to 1.20.4) are published separately and are announced with their first release. The [version guide](../READ_MEs/VERSION_GUIDE.md) explains which one to download and how to move between them.
## Status
- **BEDev**: pre-release builds of 1.3.9 are published on GitHub for testing before the stable release.
release
BlockProt Reloaded 1.3.8
1.3.829 сент. 2026 г.9Minecraft: 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2, 26.3folia, paper, purpur
Что нового

# BlockProt Reloaded 1.3.8 Release Notes
Welcome to BlockProt Reloaded 1.3.8. This release raises the minimum Minecraft version to 1.21.1, opens a public developer API, moves the bundled translations to MiniMessage, and automates testing and upkeep so every future build is checked on real Paper and Folia servers.
## Highlights
- **Minecraft 1.21.1 Baseline**: 1.3.8 supports Minecraft 1.21.1 through 26.3. Servers on Minecraft 1.20.5 to 1.21 keep using BlockProt Reloaded 1.3.7; starting 1.3.8 on those versions shows a clear message and disables the plugin instead of failing later.
- **Public Developer API**: other plugins can check whether a block is protected, who owns it, who can access it, its friends, and entity protection, and can react to lock, unlock, and access events. The API is available through JitPack.
- **MiniMessage Translations**: the English and Spanish translations now use MiniMessage formatting, including exact hex colors. Translation files with legacy `&` and `§` codes keep working.
- **Real Server Testing in CI**: every change is now tested by starting real Paper and Folia servers with the plugin and running the full console diagnostics.
- **Weekly Maintenance Check**: a weekly job detects new Paper, Folia, and Purpur versions, tests the plugin on them, audits dependencies, and keeps a single report issue up to date.
## Changelog
### Added
- Added `isProtected`, `getOwner`, `canAccess`, `getFriends`, `isPublic`, `isLockable`, `isEntityProtected`, and `getEntityOwner` to `BlockProtAPI`.
- Added JitPack publishing for `blockprot-spigot` and `common`, with a Developer API section in the README.
- Added a console diagnostics check for the public API.
- Added a startup guard that disables the plugin with a translated message on Minecraft versions older than 1.21.1.
- Added a CI job that boots the newest supported Paper and Folia servers and fails on any diagnostics error.
- Added a weekly maintenance workflow and Dependabot updates for GitHub Actions.
- Added a daily platform check that confirms the latest stable release is live on GitHub, Modrinth, CurseForge, and Hangar, and publishes it wherever it is missing (CurseForge only after 72 hours, since new files wait for manual review).
- Added a post-publication check that confirms every release is live on each platform.
### Changed
- Merged the CI, publish, release, and maintenance workflows into a single `blockprot.yml` workflow with an operation selector.
- Raised the minimum supported Minecraft version to 1.21.1 and `api-version` to `1.21`.
- Converted `translations_en.yml` and `translations_es.yml` to MiniMessage; hex colors now render exactly instead of being approximated.
- Removed the 1.20.x particle and enchantment fallbacks and version checks.
- Updated every GitHub Action used by the workflow to its current major version.
- Documentation now lists Paper, Purpur, and Folia as the supported server software; standalone Spigot is no longer listed.
### Fixed
- Fixed MiniMessage hex color tags not being recognized by the translation loader.
- Fixed the debug report headers showing outdated screen counts.
- Fixed the not-Paper startup warning still referring to the 1.3.6 end of Spigot support.
- Fixed the Hangar publish step skipping its JDK and Gradle setup.
- Fixed commit message validation failing on every pull request because of the merge commit GitHub creates for it.
## Status
- **Stable**: 1.3.8 was first published as the pre-release build `1.3.8-BEDev.1` for testing, and is now released as a stable version.
release
BlockProt Reloaded 1.3.7
1.3.729 сент. 2026 г.5Minecraft: 1.20.5, 1.20.6, 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2, 26.3folia, paper, purpur
Что нового

# BlockProt Reloaded 1.3.7 Release Notes
Welcome to BlockProt Reloaded 1.3.7. This release adds Minecraft 26.3 support, makes the admin toolset usable from the server console, and completes the move of every scheduled task onto FoliaLib so Folia servers run the plugin without falling back to the Bukkit scheduler (ALSO DONE IN RECORD TIME!!: 1.3.7 took less time to build than any previous version of the plugin, and from 1.3.8 onward the plugin is expected to keep getting optimized while the time between releases keeps shrinking).
## Highlights
- **Minecraft 26.3 Support**: The Poplar wood set (doors, trapdoors, fence gates, signs, hanging signs, shelf, and chest boat) and the new Straw bed are protected out of the box through the existing block families. Verified on Paper 26.3.
- **Console Administration**: `/bp debug`, `/bp protdel`, and `/bp unlock` now work from the server console. Diagnostics run their block and entity checks at the world spawn when no player is online, so the full NBT and gameplay simulation suite no longer needs someone in-game.
- **Complete FoliaLib Scheduling**: The remaining Bukkit scheduler calls were replaced with region-aware FoliaLib scheduling. Work that touches blocks now runs on the region that owns each block, and player-facing work runs on the player's own thread.
- **Unified World Protection Deletion**: The chest GUI, the Paper dialog, and the console now share one deletion and undo engine that processes a world chunk by chunk on its owning region, spreads the work across ticks, and keeps an undo history per administrator.
## Changelog
### Added
- Added Minecraft 26.3 to the supported version range, covering `POPLAR_DOOR`, `POPLAR_TRAPDOOR`, `POPLAR_FENCE_GATE`, `POPLAR_SIGN`, `POPLAR_WALL_SIGN`, `POPLAR_HANGING_SIGN`, `POPLAR_WALL_HANGING_SIGN`, `POPLAR_SHELF`, `POPLAR_CHEST_BOAT`, and `STRAW_BED`.
- Added console execution for `/bp debug` (plain `/bp debug` now runs the suite), running NBT, entity, sub-handler, and player simulation checks at the main world spawn when no player is online.
- Added `/bp protdel <world> confirm` and `/bp protdel undo` for console use.
- Added console output for `/bp unlock <player>`, listing every block the player has locked.
- Added translation keys for the new console messages and for previously hardcoded texts in English and Spanish.
### Changed
- `/bp info <player>` now checks block ownership on each block's owning region before listing it, and reports when the player owns no blocks in both chat and dialog mode.
- `/bp transferall` now transfers each block on its owning region and updates statistics once all transfers complete.
- World protection deletion from the GUI, dialog, and console shares a single undo history; the GUI undo button restores the most recent deletion.
- World protection deletion without the database index now scans loaded chunks using the configured block families instead of a fixed material list.
- Player-only commands (`/bp settings`, `/bp disablehints`, `/bp lockables`, `/bp stats`) now reply with a clear message when run from the console instead of printing the command usage.
- Updated the documented support range to Paper 1.20.5 through 26.3.
- Entity protection settings (tamed animals and villagers) now open as a Paper dialog when `use_dialogs` is enabled, with the same toggles as the chest menu.
- Reorganized dialog layouts: Block Settings shows the three protections on one row with Enable all and Disable all below, entity friend management uses the same `Prev | Search | Next` row as block friend management, and paged admin dialogs keep their navigation on its own row.
### Fixed
- Fixed entity protection settings showing No damage and No leash as enabled after Disable all, and toggling an individual option on an unprotected entity having no effect. Unprotected entities now show every option off, and enabling any option turns protection on with the default damage and leash protection.
- Fixed the block lock dialog offering Transfer on unprotected blocks, which have no owner to transfer from.
- Fixed the lock menu closing on Minecraft 26.3 when sneak-right-clicking a container with an empty main hand and a non-block item (such as a shield) in the off-hand. Since 26.3 the same click also fires an off-hand interaction, which opened the container on top of the menu; that interaction is now denied for the block only, so raising a shield still works and off-hand block placement is unaffected.
- Fixed revoked admin tiers returning to offline staff on their next join; `admins.yml` is now the only source used to resolve tiers and custom flags.
- Fixed world protection deletion and its undo using the Bukkit scheduler, which fails on Folia.
- Fixed the dialog-based world protection deletion querying the database on the main thread.
- Fixed friend search history heads being written to the inventory from an asynchronous thread.
- Fixed concurrent statistics updates from different Folia regions and the periodic save racing each other; all statistics access now shares one lock, and a failed save is retried on the next cycle.
- Fixed the global protected block counter drifting down on Folia when stale entries were checked from a region that does not own the block.
- Fixed the `SemanticVersion` diagnostic failing on BEDev and hotfix builds.
- Fixed console diagnostics reporting every inventory and dialog as uncovered.
- Fixed hardcoded English texts in `/bp tiers <player>`, the admin reload dialog, the custom flags menu, and the menu error message.
- Fixed the shadow JAR build warning about duplicate `kotlin_module` metadata.
### Repository and Governance
- The publish workflow has a version suffix selector: development builds are numbered automatically per release (`BEDev.1`, `BEDev.2`, ...), and choosing Stable clears `versionSuffix` in `gradle.properties` and commits it before tagging the release. The version input is now detected from `gradle.properties` when left blank.
- The publish workflow detects development builds (`BEDev`, `SNAPSHOT`, `exp`) and publishes them to GitHub Releases only, as pre-releases, skipping Modrinth, CurseForge, and Hangar.
- The publish workflow summary now includes a copy-ready Discord announcement (post title, tag, GitHub link, and platform links).
- The publish workflow now detects existing CurseForge uploads through the public CFWidget API, preventing duplicate CurseForge files when a publication is re-run.
## Credits
- **Eduardo Sanches ([@edusanches](https://github.com/edusanches))**: found and diagnosed the Minecraft 26.3 off-hand interaction bug that closed the lock menu, traced it to the duplicate off-hand `PlayerInteractEvent`, and proposed the fix in [Pull Request #9](https://github.com/VictorGugug/BlockProt-Reloaded/pull/9), together with the NBT-API 2.16.1 update required for 26.3.
## Status
- **Stable**: 1.3.7 was first published as the pre-release builds `1.3.7-BEDev.1` and `1.3.7-BEDev.2` for testing, and is now released as a stable version with no further changes.
release
BlockProt Reloaded 1.3.6
1.3.627 сент. 2026 г.7Minecraft: 1.20.5, 1.20.6, 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.2folia, paper, purpur
Что нового

# BlockProt Reloaded 1.3.6 Release Notes
Welcome to BlockProt Reloaded 1.3.6. This release focuses on comprehensive performance optimizations, memory bounding, FoliaLib scheduler unification across all asynchronous tasks and GUI updates, dialog navigation grid stabilization, dead code cleanup, and expanded language support.
## Highlights
- **Multi-Tier Admin Hierarchy and Granular Permissions**: Introduced a configurable 4-tier admin permission hierarchy (`t1`, `t2`, `t3`, `owner`) plus custom actions (`admin_tiers.enabled`), supporting standalone staff management via `/bp tiers [setrole] <player> <role>` and player NBT without LuckPerms, as well as in-game Owner execution of `/bp recommended`.
- **Comprehensive Player Simulation and Headless Server Diagnostics**: Expanded `/bp debug run` with Domain 10 (Player Simulation & Gameplay Verification) testing 10 realistic in-game player scenarios (block lock lifecycle, stranger access denial, friend management, redstone toggles, family expressions, hazard protection, entity protection, GUI state theft prevention, permission evaluation, and player settings persistence) with zero persistent side effects. Added console headless execution (`/bp debug run [player]`), allowing server operators to run diagnostics without an active player and automatically targeting online players when available.
- **Player Persistent NBT Reorganization**: Cleanly categorized player preferences, friend entries, search history, and admin data into nested PDC compounds (`BukkitValues/blockprot/...`), with automatic legacy flat tag migration and deletion for clean viewing in NBTExplorer.
- **Action Bar Notification Persistence and Raid Alert Debouncing**: Refined `TemporaryActionBar` for sustained client alerts with configurable duration (`action_bar.duration_seconds: 6`). Optimized `RaidDetectionListener` with `ProtectedBlockCache` early exit and 5-second owner debouncing to prevent alert spam during raids.
- **Expanded Entity Protection**: Added `protectable_entities` in `blocks.yml`, enabling protection for non-tameable entities with `VILLAGER` configured as the currently supported and compatible entity type.
- **Modernized GitHub Actions CI, Automated Governance, and Dependency Audit**: Replaced legacy, unmaintained workflows with modern GitHub Actions pipelines. Continuous Integration now resolves and displays the current plugin version and declared Minecraft version support range, executes comprehensive Gradle builds and unit test suites on pushes to `main` and Pull Requests with automated test report archiving, and uploads compiled shadow JAR artifacts. Introduced a dynamic release cycle commit aggregator generating categorized changelogs from Git history and `gradle.properties` directly into Job Summaries and release bodies. Introduced a chained automated dependency and plugin integration version audit comparing 24 core libraries and integrations against upstream releases in a comparative status table. Consolidated repository diagnostics and project integrity validation (`verify_project_integrity.py`) into the primary CI pipeline, auditing YAML syntax, translation parity (904 keys across English and Spanish), license headers, and pure Java architectural boundaries.
- **Multi-Platform Distribution and Release Pre-Flight Inspection**: Implemented automated distribution tooling (`publish.yml`) supporting Modrinth, CurseForge, and PaperMC Hangar via the official `io.papermc.hangar-publish-plugin:0.1.4`. Release and publication workflows feature a 3-mode execution selector (`Preview`, `Publish`, `Cancel`) providing complete pre-flight inspection of binary SHA-256 checksums, platform tokens, and release notes prior to upload.
- **Server Platform and Upstream Build Auditing**: Centralized supported, legacy, and unsupported platform declarations in `gradle.properties`, with automated real-time build queries against PaperMC Fill v3 API, PurpurMC API v2, and Folia builds to track stable and experimental upstream versions.
- **JUnit 6 Test Platform Alignment and Automated Test Suite**: Resolved transitive version incompatibilities between MockBukkit 4.110.0 and JUnit platform dependencies via `org.junit:junit-bom:6.0.3`, ensuring a fully green automated test suite.
- **Native Bedrock Forms Integration (Geyser and Floodgate)**: Added full native Bedrock Forms (Cumulus) GUI integration for Bedrock players connecting via Geyser and Floodgate. Bedrock players receive touch-optimized forms for menus, block locking, settings, friend management, and admin configuration, with seamless switching back to classic inventory GUIs via `/bp settings`.
- **Experimental Minecraft 1.20.5+ Compatibility**: Lowered descriptor `api-version` to `1.20`, allowing Minecraft 1.20.5 and 1.20.6 servers to load the plugin. While all core protection logic is theoretically compatible (~95-98%), this range is marked experimental; user feedback is appreciated to ensure full stability in subsequent releases.
- **Hot-Path Listener Optimizations**: Redstone, piston movements, block breaks, block burns, and explosion listeners now perform instant early exits via `ProtectedBlockCache`, avoiding expensive NBT deserialization and state snapshots for unaffected blocks.
- **Folia and Paper Scheduler Unification**: All background tasks, search routines, world expiry scanners, and async inventory skull loaders now run exclusively through FoliaLib with thread-safe entity region dispatching.
- **Bounded In-Memory Caching**: Bounded Caffeine caches have replaced unbounded memory structures for player skin profile lookups and offline player candidate queries, preventing memory growth on long-running servers.
- **Expanded Bundled Languages**: Added 5 new language translations (Romanian, Arabic, Ukrainian, Hebrew, and Swedish), bringing out-of-the-box support to 25 languages.
- **Standalone Spigot Deprecation**: Formalized the deprecation of standalone un-forked Spigot in favor of Paper, Purpur, and Folia.
- **Repository Governance and Standardized Commit Convention**: Added formal contribution guidelines (`CONTRIBUTING.md`), project scope definitions (`SCOPE.md`), and AI agent instructions (`AGENTS.md`), alongside a structured commit format (`BPR:<branch>(<type>): <description>`) to ensure consistent repository history and issue-first workflows.
## Changelog
### Added
- Added configurable multi-tier administrative permissions (`admin_tiers.enabled`) with 4 distinct tiers (`blockprot.user.admin.t1`, `blockprot.user.admin.t2`, `blockprot.user.admin.t3`, `blockprot.user.admin.owner`) and `blockprot.user.admin.custom`.
- Added standalone staff management via `/bp tiers [setrole] <player> <role>` and `admins.yml`, providing persistent role storage without requiring LuckPerms, decoupled from `/bp admin`.
- Added in-game `/bp recommended` command execution for players holding the `blockprot.user.admin.owner` permission.
- Added `action_bar.duration_seconds` configuration setting in `config.yml` (default 6 seconds).
- Added `protectable_entities` configuration list in `blocks.yml`, with `VILLAGER` configured as the currently supported non-tameable entity type.
- Added modern GitHub Actions Continuous Integration workflow (`.github/workflows/ci.yml`) executing full Gradle builds and automated test suites on pushes to `main` and Pull Requests.
- Added automated plugin version and Minecraft support target resolution step in `.github/workflows/ci.yml`, displaying declared support (`1.20.5 - 26.2`) and Java toolchain baseline in logs and Job Summaries.
- Added chained `dependency-audit` job in `.github/workflows/ci.yml` backed by `.github/scripts/audit_dependencies.py`, auditing 10 plugin integrations (Towny, PlaceholderAPI, WorldGuard, LandsAPI, ClaimChunk, Residence, GriefPrevention, Floodgate, Cumulus, ViaVersion), 10 core dependencies, and 4 build/test tools.
- Added dynamic release cycle commit aggregator (`.github/scripts/generate_version_commits.py`) automatically detecting release boundaries from `gradle.properties` and Git history without manual version input, outputting categorized commit summaries to GitHub Actions Step Summaries, build artifacts, and release bodies.
- Added comparative status table (`[v]` up to date / `[x]` update available) rendered directly into GitHub Actions Job Summary without failing CI runs on external upstream updates.
- Added weekly scheduled trigger (`cron: '0 3 * * 0'`) to CI workflow for proactive automated dependency monitoring.
- Added automated Governance and Standards validation integrated into `.github/workflows/ci.yml` validating commit conventions, version integrity in `gradle.properties`, GPL v3 license headers, and absence of placeholder markers.
- Added concurrency controls across all repository workflows (`ci.yml`, `publish.yml`, `release.yml`) to cancel redundant in-flight runs on active branches.
- Added structured GitHub Step Summaries across all workflows (`ci.yml`, `publish.yml`, `release.yml`).
- Added comprehensive automated unit test `EntityProtectionTest` covering stick locking, entity claiming, and third-party denial for villagers.
- Added safe accessors `BlockProt.getInstanceOrNull()` and `BlockProt.hasFoliaLib()` to facilitate headless testing environments.
- Declared explicit supported Minecraft version targets in `gradle.properties` for the 1.3.6 release cycle (`1.20.5` through `26.2`).
- Added structured player NBT organization under `BukkitValues/blockprot/...` with dedicated subcompounds for `preferences`, `friends`, `history`, and `admin`.
- Added native Bedrock Forms GUI integration using GeyserMC Floodgate and Cumulus APIs, including `BedrockUserMenuForm`, `BedrockUserSettingsForm`, `BedrockStatsForm`, `BedrockTransferForm`, `BedrockFriendManageForm`, `BedrockBlockLockForm`, `BedrockBlockSettingsForm`, `BedrockAdminMenuForm`, `BedrockAdminConfigForm`, `BedrockLockablesForm`, and `BedrockAutoDropForm`.
- Added player preference toggle (`blockprot_prefer_bedrock_forms`) to allow Bedrock players to switch between native Bedrock forms and Java inventory/dialog menus.
- Added discrete Brigadier command node registration for `/bp` and `/blockprot` on Paper servers, ensuring subcommand tab completions appear natively on Bedrock clients via Geyser.
- Added four friend permission levels (Basic, Operator, Full Manager, and Custom) with granular action flags, supported across dialogs, inventory menus, and Bedrock forms.
- Added centralized Geyser and Floodgate integrations in `integrations.yml` with automatic Floodgate username prefix detection.
- Added a block unlock action shortcut to the Admin Menu inventory.
- Added experimental support for Minecraft 1.20.5 and 1.20.6 by setting `api-version: '1.20'`.
- Added Romanian (`translations_ro.yml`), Arabic (`translations_ar.yml`), Ukrainian (`translations_uk.yml`), Hebrew (`translations_he.yml`), and Swedish (`translations_sv.yml`) language files to bundled resources.
- Added dynamic pagination and support for 25 languages in language selection interfaces.
- Added Bedrock player skin resolution in `SkinCache` via the official Geyser Global API (`/v2/skin/{xuid}`) with XUID extraction from Floodgate UUIDs and Xbox gamertags.
- Added language-agnostic block query aliases (`search_aliases:` in translation files) loaded dynamically via `Translator` and `BlockFamilyParser`.
- Added dual-interface Admin Tiers management supporting both chest inventory GUIs (`AdminTiersInventory`, `AdminTierSelectInventory`) and native Paper Dialogs (`AdminTiersDialog`, `AdminTierSelectDialog`), accessible via `/bp tiers`, `/bp tiers gui`, and slot 19 in `/bp admin`.
- Added support for configuring the Custom administrative tier directly in the role selection GUI (slot 22, styled as a blue dyed chestplate) and Paper Dialogs.
- Added automatic server operator (OP) detection across admin tier interfaces, displaying `[OP]` badges in player lists, player skulls, and dialog headers to clearly distinguish server operators from assigned tiers.
- Added direct single-player inspection via `/bp tiers <player>`, reporting both configured administrative tier and server operator status.
- Added automated unit tests (`BlockProtInventoryClickTest`) verifying click cancellation, state fallback generation, drag prevention, and exception logging in `BlockProtInventory` menus.
- Added official PaperMC Hangar publication plugin integration (`io.papermc.hangar-publish-plugin:0.1.4`) in `spigot/build.gradle.kts` targeting `BlockProt-Reloaded` for Paper `1.20.5 - 26.2`.
- Added multi-platform manual publication workflow (`.github/workflows/publish.yml`) uploading to Modrinth, CurseForge, and Hangar with credential verification.
- Added 3-mode execution selector (`Preview (Dry-Run Pre-Flight Inspection)`, `Publish / Release (Confirm & Upload)`, `Cancel (Abort without action)`) across release and publication workflows.
- Added single source of truth for platform and version compatibility boundaries in `gradle.properties` (`supportedPlatforms`, `legacyPlatforms`, `unsupportedPlatforms`, `unsupportedVersions`).
- Added real-time server software and upstream build queries to `.github/scripts/audit_dependencies.py` checking PaperMC Fill v3, PurpurMC API, and Folia builds, displaying stable, experimental, and unsupported platform statuses in Job Summaries.
- Added dynamic `run-name` headers across all GitHub Actions workflows (`CI: <commit>`, `Release [<mode>]: <version>`, `Publish [<mode>]: <tag>`) for clean, organized monitoring.
- Added Domain 10 ("Player Simulation & Gameplay Verification") to `/bp debug run` in `DebugCommand.java`, executing 10 in-game player simulation scenarios covering block lock/cache lifecycle, stranger access denial, friend lifecycle, redstone/hopper toggles, block family expressions, hazard protection, entity protection, GUI state integrity, permission node evaluation, and player settings persistence.
- Added console execution support for `/bp debug run [player]`, executing headless server diagnostics across non-player domains when no player is online, or running full 10-domain player simulation when an online player context is provided.
- Added automated `PlayerSimulationTest` utilizing MockBukkit to verify protected block caching, multi-block family resolution, and entity protection damage cancellation within the test suite.
- Added project file integrity audit step in `.github/workflows/ci.yml` powered by `verify_project_integrity.py`, testing YAML syntax, translation parity (904 keys across English and Spanish), GPL v3 headers, placeholder absence, and pure Java boundaries.
### Changed
- Consolidated standalone diagnostics and integrity auditing directly into `.github/workflows/ci.yml`, publishing the complete file integrity report to GitHub Job Summaries and archiving `integrity-report.md` alongside CI reports.
- Relocated developer compilation guide from consumer-facing documentation into internal developer tooling to preserve clean distribution boundaries.
- Updated all diagnostic check methods in `DebugCommand` to accept nullable player instances, enabling headless execution from console.
- Consolidated Governance and Standards validation directly into `.github/workflows/ci.yml` as Job 1 before build execution, eliminating redundant concurrent workflow runs and retiring standalone `governance.yml`.
- Renamed the unassigned role `none` to `User (Normal)` across language files, inventory lore, and dialog actions, allowing administrators to configure players back to standard user permissions directly from the interface.
- Expanded `AdminTier.fromString` with `user`, `normal`, and `0` aliases resolving to `AdminTier.NONE`.
- Expanded `/bp debug run` diagnostics with automatic structural class verification for all admin tier UI components and role storage roundtrip tests.
- Streamlined `/bp debug` environment diagnostic reporting into structured key-value entries, removing verbose logs and delimiter lines.
- Consolidated language label computation between `AdminConfigLanguageDialog` and `AdminConfigLanguageInventory`.
- Refactored `TemporaryActionBar` to eliminate resend flickering and abrupt empty packet clears, refreshing display packets every 40 ticks for sustained visibility throughout the configured window (`action_bar.duration_seconds: 6`).
- Decoupled tier role management from `/bp admin` to standalone `/bp tiers [setrole] <player> <role>`.
- Enforced strict command and tab-completion filtering to `/bp user` and `/bp admin` when `use_menus: true`, dispatching instant client command tree updates (`player.updateCommands()`) on join and dynamic config changes.
- Automated removal of obsolete `recommended_config_applied` and `recommended_blocks_applied` keys from disk on startup and patching.
- Updated `VillagerWorkstationProtectionListener` to enforce `AdminTierManager` permissions and dispatch alerts via `TemporaryActionBar`.
- Updated admin commands and listeners (`BlockEventListener`, `InteractEventListener`, `AdminMenuCommand`, `LockablesCommand`, `AdminUnlockCommand`, `WorldProtDeleteCommand`, `ReloadCommand`, `UpdateCommand`, `IntegrationsCommand`) to check granular `AdminAction` and `AdminTier` permissions.
- Converted `WorldExpiryTask` from legacy `BukkitRunnable` to `Runnable` dispatched through FoliaLib scheduler with chunk-level protected block pre-filtering.
- Modernized `VillagerLocateTask` to use FoliaLib scheduler with task cancellation hooks.
- Upgraded `FriendSearchResultInventory`, `EntityFriendSearchResultInventory`, and `TransferSearchInventory` to use asynchronous querying with `runAtEntity` UI callbacks, eliminating legacy 1-tick polling loops.
- Modernized `AuditInventory`, `BlockInfoInventory`, `EntityInfoInventory`, and `BlockProtInventory` async skull texture resolution to use entity-bound FoliaLib dispatchers.
- Modernized `FriendsAddAllCommand` background task execution with FoliaLib scheduler.
- Upgraded `commons-lang3` dependency to version `3.17.0`.
- Upgraded `item-nbt-api` to `2.16.1`, `Towny` integration to `0.103.2.7`, `GriefPrevention` integration to `16.18.7`, and `Residence` integration to `6.0.2.3`.
- Upgraded `mysql-connector-j` to Oracle CalVer `26.7.0`, `org.jetbrains:annotations` to `26.1.0`, and test platform `junit-bom` to `6.1.3` with `MockBukkit` `4.116.3`.
- Updated Gradle root project declaration in `settings.gradle.kts` to `BlockProt-Reloaded` and upgraded Shadow plugin to `9.6.1`.
- Bounded `SkinCache` with a Caffeine cache capped at 5,000 profiles and a 24-hour expiration window.
- Added candidate caching with a 30-second TTL to `PlayerLookup` to optimize repeated friend search queries on large offline player databases.
- Updated User Menu dialog (`UserMenuDialog`) block transfer button to prompt via chat input (`TextInput`), enabling native tab-completion for player names.
- Standardized multi-action dialog navigation rows across `AutoDropDialog`, `LockablesDialog`, `LockableCategoryDialog`, `AutoDropFamilyDialog`, `AutoDropSearchDialog`, and `WorldLockableDetailDialog` using grid padding (`BpDialogStyles.padToGrid`) to fix `Prev`, action, and `Next` buttons in stable 3-column bottom rows.
- Updated administrator and user guide documentation (`ADMIN_GUIDE.md` and `USER_GUIDE.md`) covering administrative permission tiers, standalone `/bp tiers` command usage, Bedrock forms preference toggling, and protectable entities.
- Modernized root `README.md` with complete documentation on UI parity (native Paper Dialogs, Bedrock Forms, Chest GUIs), 4-tier staff administration, and 13 external integrations, while removing obsolete roadmap and legacy documentation transition policies.
- Synchronized root `README.md` and documentation references with the complete 10-section configuration schema from `config.yml`, updating supported Minecraft versions to `1.20.5 - 26.2` across consumer guides.
### Deprecated
- Standalone un-forked Spigot is now formally deprecated and will reach end of support in this release cycle. Paper or modern Paper forks (Purpur, Folia) are strongly recommended.
### Removed
- Removed dead `filterFriends` and `filterFriendsInternal` methods from `PluginIntegration` and `TownyIntegration`, cleaning up orphaned javadoc references.
- Removed deprecated unused constructor in `BlockProtInventory`.
### Fixed
- Fixed action bar alerts fading out prematurely after 2 seconds regardless of configuration by refreshing packets every 40 ticks throughout the configured display window (default 6 seconds) and clearing cleanly at expiration.
- Fixed command tab completions remaining desynchronized on client join or runtime config modification when `use_menus` is enabled.
- Fixed `/bp tiers` reporting an unhelpful no-permission message when `admin_tiers` is disabled instead of displaying the informative disabled notice.
- Fixed performance lag during massive explosions on unprotected terrain in `RaidDetectionListener` by filtering blocks through `ProtectedBlockCache` before reading NBT.
- Fixed alert spam during raids by debouncing rapid explosion notifications within a 5-second cooldown per owner.
- Fixed legacy flat player tags cluttering the root player PersistentDataContainer in NBTExplorer by migrating and purging old keys upon login.
- Fixed un-cached NBT deserialization on high-frequency redstone current changes by checking `ProtectedBlockCache` prior to inspecting block state.
- Fixed piston extend and retract listeners reading NBT for blocks outside the protected block cache.
- Fixed block burn, block break, and explosion blast radius calculations reading persistent data for unprotected blocks.
- Fixed redundant `BlockState` allocation during block interaction checks in `InteractEventListener`.
- Fixed raw permission strings in `InactivityCleanupTask` and `EntityMenuOpenListener` to use centralized `Permissions` constants.
- Fixed navigation button misalignment in `AutoDropDialog` where 5-item family lists caused `Prev` and `Next` buttons to shift into content rows.
- Fixed player name resolution in block transfers and friend candidate lookups to reliably resolve both online and offline players.
- Fixed `EntityMenuOpenListener` and `EntitySettingsInventory` blocking non-tameable protectable entities by replacing restrictive `instanceof Tameable` checks with `EntityProtectionHandler.isSupportedEntity(...)` and enabling unowned entity claiming.
- Fixed `EntityProtectionHandler` throwing `AssertionError` during headless test execution by using safe `NamespacedKey` generation.
- Fixed test discovery failures (`NoSuchMethodError`) caused by version misalignment between MockBukkit 4.110.0 and JUnit 5 by aligning with `junit-bom:6.0.3`.
- Fixed `BlockFamilyParser` invoking mock-unimplemented legacy material checks by checking `m.isLegacy()` prior to `m.isAir()`.
- Fixed item theft vulnerability in `BlockProtInventory` menus (`AdminTiersInventory`, `AdminTierSelectInventory`) where clicks occurred without an active `InventoryState` or fell into unhandled container paths, ensuring top and bottom clicks are unconditionally cancelled and fallback state is automatically generated.
- Fixed silent error suppression on inventory and container click handlers by routing diagnostics through `BlockProtLogger.error` and informing players of internal failures.
- Fixed `InventoryDragEvent` on `BlockProtInventory` to unconditionally cancel item dragging into custom interfaces.
- Fixed premature menu close on "set by name" offline player action in `AdminTiersInventory`, ensuring `suppressCloseReopen` is set before triggering chat input.
- Fixed `/bp debug run` screen coverage failures (`[9g. Class coverage]`) by registering and exercising `AdminTiersInventory`, `AdminTierSelectInventory`, `AdminTiersDialog`, `AdminTierSelectDialog`, `FriendDetailDialog`, and `WorldExpiryDialog` in debug test suites.
- Fixed `BlockProtLogger` throwing `AssertionError` during headless test execution when calling `BlockProt.getInstance()` by utilizing safe accessor `getInstanceOrNull()` and falling back to standard logger.
- Fixed menu navigation origins and origin stack propagation when selecting players in `AdminTierSelectInventory` and `AdminTiersInventory`, ensuring back button clicks return to the correct originating parent menu.
- Fixed top-level command execution of `/bp tiers gui` displaying a back button by detecting `MenuOrigin.NONE` and rendering a barrier "Close" item that closes the inventory cleanly.
- Fixed `UpdateCommand`, `AboutCommand`, and `TiersCommand` opening dialogs with incorrect parent origins when executed from chat, passing explicit `DialogOrigin.NONE`.
- Fixed `AdminMenuDialog` opening `AboutDialog` with `DialogOrigin.NONE` instead of `DialogOrigin.ADMIN_MENU`, restoring proper return flow to the admin menu.
- Fixed dialog transition in `UserSettingsInventory` when toggling `preferDialogs`, correctly propagating parent origin.
- Fixed `/bp debug run` restricting diagnostics to in-game players only, now allowing server console execution in headless mode across all static and configuration domains while gracefully executing full player simulation when an online player context is provided.
- Fixed `InventoryState` test state retention by ensuring mock and test player states are cleanly removed in finally blocks.
### Repository and Governance
- Established formal repository governance documentation:
- `CONTRIBUTING.md`: Defines contribution guidelines, mandatory issue-first workflow, pull request lifecycle, live-server verification criteria, and AI-assisted contribution standards.
- `SCOPE.md`: Formalizes authoritative project boundaries, supported server platforms (Paper family and Folia), universal version separation (plugin semantic versioning versus upstream Minecraft game releases), and out-of-scope targets.
- `AGENTS.md`: Restates binding policies for AI assistants, enforcing the issue-first mandate, pure code without conversational narration comments, license header preservation, and prohibition of version bumping.
- Standardized commit message convention across the repository:
- Required format: `BPR:<branch>(<type>): <description>` (for example, `BPR:main(fix): Resolve duplicate interact event on off-hand click` or `BPR:main(add): Introduce protectable entities configuration in blocks.yml`).
- `BPR` identifies the BlockProt Reloaded project.
- `:<branch>` denotes the targeted repository branch (`:main` or future branches).
- `(<type>)` categorizes the modification (`fix`, `add`, `refactor`, `docs`, `chore`).
- Enforces linear history discipline, clarity, and verifiable compliance with repository standards.
- Added direct community Discord invitation (`https://discord.gg/RRcjuMr9Jd`) across governance documents for proactive issue coordination.
- Automated CI and Governance verification on all incoming pull requests and main pushes via GitHub Actions:
- CI pipeline executes full Gradle builds and test suites with automated test report archiving on failure and shadow JAR artifact publishing on success.
- Runtime environment step resolves and reports current plugin version, declared Minecraft support range (`1.20.5 - 26.2`), Java baseline, and platform targets in logs and job summaries.
- Chained dependency and integration audit job parses `gradle.properties` and Gradle build scripts, querying Maven Central, CodeMC, TCoded, ExtendedClip, EngineHub, OpenCollab, and GitHub APIs across 24 components to produce a comparative status table (`[v]` / `[x]`).
- Governance pipeline enforces commit formatting rules, version immutability in `gradle.properties`, GNU GPL v3 license headers across Java sources, and complete absence of placeholder markers (`TODO`, `FIXME`, `XXX`).
- Consolidated diagnostic and project file integrity audit (`verify_project_integrity.py`) directly into `.github/workflows/ci.yml`, validating 32 YAML files, 904 translation key parity between English and Spanish, and pure Java isolation in `:common`.
- Concurrency management across all workflows cancels obsolete in-flight executions on branches while allowing primary branch runs to conclude cleanly.
- Dynamic release cycle commit aggregator (`.github/scripts/generate_version_commits.py`) extracting version boundaries from `gradle.properties` and Git history, publishing categorized commit summaries directly to GitHub Step Summaries and release artifacts without manual version entry.
- Modernized Gradle wrapper validation in release and publish pipelines via `gradle/actions/wrapper-validation@v4`.
- Structured step summaries across all workflows providing immediate visibility into test outcomes, governance checks, artifact builds, and release metadata.
- Consolidated Governance and Standards validation directly into `ci.yml` as Job 1, preventing duplicate workflow runs and ensuring all quality gates pass before compilation.
- Multi-platform publication workflow (`publish.yml`) supporting Modrinth, CurseForge, and PaperMC Hangar with 3-mode execution (Preview, Publish, Cancel) and binary checksum validation.
- Upstream server platform build auditing for Paper, Folia, and Purpur tracking stable and experimental releases alongside compatibility boundaries.
release
BlockProt Reloaded 1.3.5
1.3.528 авг. 2026 г.109Minecraft: 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2bukkit, folia, paper, purpur, spigot
Что нового

## Summary
This release completes the admin config editor story started in 1.3.4. The dialog-based editor already mirrored `config.yml` section by section; 1.3.5 adds the matching **inventory-based editor** for servers running `use_dialogs: false`, so the Config entry in the Admin Menu now opens a real editor on every server software instead of the "not available" message dialog-mode servers never saw.
1.3.5 also closes the last remaining gap between the dialog and inventory UIs: **per-world lockables selection, previously an inventory-only feature, now has its dialog counterpart** (`/bp lockables > Configure per world`), so the lockables system is fully reachable from both interfaces.
On the dialog side, this release is mostly internal quality-of-life: `AdminConfigDialog` was split from one 826-line class into one class per category, the duplicated back-button switches in 16 dialog screens were replaced by a single unified helper, a per-player back stack makes BlockLock sub-screens return to the exact block lock screen they came from, and the category selector dialog gained a Reload button for parity with the inventory selector. The one remaining hardcoded English string in the reload flow (the failure message) was moved to a translation key. The six pastel dialog colors and the color-code stripping helper, duplicated verbatim in 18 dialog classes, were centralized into one shared `BpDialogStyles` class.
The dialog and inventory editors are interchangeable: same categories, same settings, same order, same labels, same config keys, same values, same click behavior. Both write through the same save path (`setAndSave`, the same suppress-then-reload invariant a manual YAML edit follows), and both validate numeric input with the same in-chat error message.
## Inventory Config Editor
`/bp admin > Config` now routes per player preference:
- On a Paper 1.21.7+ server with `use_dialogs: true`, the inventory closes and the native dialog editor opens (unchanged behavior).
- Everywhere else, the new `AdminConfigInventory` opens: a 54-slot inventory with the same 9 categories as the dialog, a Reload button, a Back button, and the same pastel color palette and stained-glass separators used across the config UIs.
### Category selector layout
The selector is a 9x6 grid with one category button per row (slots 9-17), the Reload button at slot 22, and the Back button at slot 49. Each category button shows its translated name with a click-to-edit tooltip.
| Slot | Category | Material |
|---|---|---|
| 9 | Language | Writable Book |
| 10 | Worlds | Grass Block |
| 11 | Players and friends | Player Head |
| 12 | Blocks and locking behavior | Anvil |
| 13 | Entity protection | Name Tag |
| 14 | Expiry | Clock |
| 15 | Raid detection | Crossbow |
| 16 | Notifications | Bell |
| 17 | Maintenance | Damaged Anvil |
| 22 | Reload | Comparator |
### Settings per category
Each category inventory lists every setting of its dialog counterpart, in the same order, with the same titles, descriptions, and config keys:
- **Language**: `replace_translations`, `fallback_string`, plus two sub-screens, "Enable or Disable Languages" (per-language toggles with a global Enable All/Disable All button) and "Select Active Language" (display name, completion percentage, active marker, click to set active).
- **Worlds**: `per_worlds_config`, `excluded_worlds` (comma-separated world list via chat input).
- **Players and friends**: `lock_on_place_by_default`, `public_is_friend_by_default`, `player_max_locked_block_count`, `lock_hint_cooldown_in_seconds`, `friend_search_similarity`, `disable_friend_functionality`.
- **Blocks and locking behavior**: `modern_family_blocks` (flips the blocks.yml storage format on toggle), `redstone_disallowed_by_default`, `simplified_hopper_logic`, `protect_locked_blocks_from_explosions`, `block_protected_block_piston_movement`, `clear_protection_on_shulker_break`, `allow_break_protected_blocks`, `respect_spawn_protection`, `block_lock_effects`, `block_lock_sounds`, `use_menus` (dialog-only, marked), `use_dialogs` (dialog-only, marked), `timed_access_max_duration_days`.
- **Entity protection**: `entity_protection.enabled`, `entity_protection.auto_protect_on_tame`, `villager_workstation_protection.enabled`, `villager_workstation_protection.radius`, `villager_workstation_protection.vertical_radius`, `entity_protection.villager_locate_seconds`, `entity_protection.menu_item` (validated against real material names).
- **Expiry**: `world_expiry.enabled`, `world_expiry.check_interval_minutes`.
- **Raid detection**: `raid_detection.enabled`.
- **Notifications**: `notify_op_of_updates`, `owner_notifications.enabled`.
- **Maintenance**: `auto_reload_configs`, `auto_reload_delay_seconds` (clamped 0-5), `inactivity_cleanup_days`, `enable_session_log`, `enable_backups`.
### How editing works
- Boolean settings are toggle items that apply immediately on click and re-render the screen; the current state is shown in the item name (the inventory equivalent of the dialog's on/off icon), and the item glows when active.
- Value settings (numbers and text) open the chat input prompt (`TextInput`) when clicked, the inventory-mode equivalent of the dialog's native text field. The same parse validation runs as in the dialog editor: invalid numbers show the `dialogs.admin_config.invalid_number` message and the value is not saved; the villager menu item is checked against actual material names before saving.
- Every change goes through `DefaultConfig.setAndSave()` or its dedicated setter, which saves to disk, suppresses file-watcher duplicate triggers, and schedules the programmatic reload after the configured `auto_reload_delay_seconds`.
- All titles, lore lines, tooltips, hints, and status messages come from `TranslationKey`; the editor reuses the dialog editor's key set, so both UIs stay in sync from a single translation file.
- All inventory category screens (`AdminConfig*Inventory`), `UserMenuInventory`, and `AdminMenuInventory` feature a unified, framed layout: dark gray stained-glass pane background borders, centered item slots across rows, and a standardized Back/Close button at slot 49 (bottom center).
## Per-World Lockables in the Dialog UI
The last inventory-only lockables screen now has its dialog equivalent. From `/bp lockables`, a new "Configure per world" button (only shown while `per_worlds_config: true`, matching the legacy inventory behavior) opens:
- **`WorldLockableSelectionDialog`**: lists every loaded world with its protection status (enabled/disabled), its protected-block count, and a hint when the world has its own config entry. Six worlds per page; clicking a world opens its detail screen.
- **`WorldLockableDetailDialog`**: the per-world material list for that world, sorted by name, nine materials per page. Each row toggles that material inside the world's list in `worlds.yml`, exactly like the inventory detail screen: worlds without a list of their own start from the global lockable/entity settings, and the first toggle for that world writes a compact family expression (never a flat wall of material names). The toggle runs through the same suppress-then-reload path, logs to the activity log, and confirms in the action bar with the world name in the feedback.
- Back navigation mirrors the inventory flow: detail goes back to the world selector, which goes back to the lockables dialog.
A note on scope: the dialog detail screen is the same full replication of the lockables list that the inventory detail screen already was; it is not a shortcut that reuses the global lists in place of the per-world ones.
## Reload Button in the Dialog Category Selector
The dialog category selector previously had no Reload button while its inventory counterpart did. The `AdminConfigDialog` categories screen now includes a Reload button at the end of the list, with the same behavior as the Admin Menu dialog's Reload: an immediate reload of `config.yml`, `blocks.yml`, and `lang/lang.yml` via the reload coordinator, reporting success or failure in chat with no review step.
## Reload Failure Message Is Now Translated
The reload flow no longer prints a hardcoded English string on failure. A new key, `messages.admin_reload_failed` ("Reload failed: {error}" / "La recarga falló: {error}"), replaces the literal in both the Admin Menu dialog and the config editor dialog, with the coordinator's error message inserted via the `{error}` placeholder. This was the last remaining hardcoded player-facing string in the reload path.
## Dialog Navigation Refactor
Two new classes replace the largest source of duplicated dialog code:
- **`DialogNavigation.backButton(...)`**: one helper builds the Back/Close button from the screen's origin (close label for standalone screens, back label and the correct "return to" tooltip for menu origins). The per-screen `originHint`/`originBack` switch blocks were removed from 16 dialog classes: About, AdminMenu, BlockLock, BlockSettings, Debug, EntityBlockSettings, FriendManage, Info, Integrations, Lockables, Protdel, Stats, Unlock, Update, UserMenu, and UserSettings. (`AdminConfigDialog` keeps its own inline back/close button because the config editor routes back to the Admin Menu dialog instead of using the shared origin helper.)
- **`DialogState`**: a per-player back stack (mirroring the inventory system's origin stack) for the child screens that previously hardcoded "back to BlockLockDialog". Block Settings, Friends, and Entity Settings screens reached from a block lock dialog now push the block lock screen onto the stack and pop it on Back, so returning works even when the same child screen is reachable from several parents. The stack is cleared when a block lock dialog is opened fresh.
## AdminConfigDialog Split per Category
`AdminConfigDialog` went from a single 826-line class holding the selector plus one `show` method per category to one class per category, each holding exactly its own screens: `AdminConfigLanguageDialog`, `AdminConfigWorldsDialog`, `AdminConfigPlayersDialog`, `AdminConfigBlocksDialog`, `AdminConfigEntityDialog`, `AdminConfigExpiryDialog`, `AdminConfigRaidDialog`, `AdminConfigNotificationsDialog`, and `AdminConfigMaintenanceDialog`. `AdminConfigDialog` keeps the top-level category selector and the shared button builders. No player-visible behavior changed; the split is purely organizational.
## Config Entry Always Opens an Editor
With `use_dialogs: false`, the Config button in the Admin Menu inventory previously replied with a "config GUI not available" action-bar message. It now opens the inventory editor described above. The `messages.admin_config_no_gui` translation key and its `TranslationKey` constant, no longer referenced by any code, were removed in this release.
## Menu Order and Dialog Parity
The two top-level menus now show their entries in the same order in both UI modes, and the dialog UIs close the last remaining feature gaps with their inventory counterparts:
- **User menu order**: Friends, Settings, Stats, Transfer, About. `UserMenuInventory` slots were reordered (Friends at 11, Settings at 12, Stats at 13, Transfer at 14, About at 15) to match the order the dialog already displayed.
- **Admin menu order**: Lockables, Config, Auto Drop, Remove All Protections, Stats, Integrations, Check for Updates, Reload, Debug, Info, About. `AdminMenuInventory` slots were reordered (Stats at 19, Integrations at 20, Check for Updates at 21, Reload at 22, Debug at 23, Info at 24, About at 25) to match the dialog order.
- **Transfer in the User Menu dialog**: the inventory-only "Transfer all blocks" button now also exists in the dialog version. It opens a native value-input dialog asking for the target player name, then runs the same `TransferCommand.transferAll` path the inventory button uses.
- **Auto Drop and About in the Admin Menu dialog**: both were inventory-only and now appear in the dialog version, Auto Drop after Remove All Protections and About last, mirroring the inventory placement. Auto Drop opens the auto-drop dialog; About opens the About dialog.
All new buttons reuse existing translation keys and dialog components, so no new keys were added to either language file.
## Dead Code Cleanup
Verified dead code (each item confirmed to have zero call sites before removal) was removed in this release:
- `BlockInfoInventory.getOnlineProfileOrCreate` (zero call sites; the shipped skin path uses `SkinCache` instead).
- `BlockProtInventory.modifyFriendsForAction(Player, OfflinePlayer, ...)`: all call sites pass a `UUID`, so the deprecated `OfflinePlayer` overload was removed.
- `BlockProtInventory.setPlayerSkull(int, OfflinePlayer)` (zero call sites; the `PlayerProfile` overload and `setPlayerSkullAsync` cover all screens).
- `BlockProtInventory.toggleEnchants(ItemStack)` single-argument overload (zero call sites; the two-argument overload is used internally).
- The `MESSAGES__ADMIN_CONFIG_NO_GUI` constant and its `messages.admin_config_no_gui` key (see above).
- 67 unused translation keys removed from `translations_en.yml` and `translations_es.yml`: the lock-groups feature leftovers (`inventories.groups.*`, `messages.groups.*`), legacy flat `dialogs.admin_config.*` keys superseded by the per-category nested keys, the nested `console.boot.*` duplicates of the flat boot keys, `console.claims_system_enabled/disabled`, `messages.user_transfer_hint`, `messages.user_timed_hint`, `inventories.integrations.none/separator`, and `worlds.scan_world_added`. Both files stay in sync; the completeness check confirms every remaining key maps to a live `TranslationKey` constant.
- `DefaultConfig.migrateLegacyBlocksIfNeeded()` (deprecated empty stub, zero callers).
- `TransferSearchInventory.openSearch(Player)` single-argument overload (both call sites use the `(Player, Block)` overload).
- The `FriendHandler` access-flag leftovers `getAccessFlagsBitset()`, `setAccessFlagsBitset(int)`, `getAccessFlags()`, and `setAccessFlags(EnumSet<BlockAccessFlag>)`. `isManager()` keeps its signature but always returns `false`, which is exactly what the removed feature's empty stubs already produced.
- The `NBTHandler.PERMISSION_LOCK`, `PERMISSION_INFO`, `PERMISSION_ADMIN`, and `PERMISSION_BYPASS` constants (zero references; `Permissions` is the single source of permission nodes).
- `PlayerSettingsHandler.addPlayerToSearchHistory(OfflinePlayer)` and `addPlayerToSearchHistory(String)` overloads (the only call site passes a `UUID`).
- `UpdateChecker(PluginDescriptionFile)` and `UpdateChecker(PluginDescriptionFile, List<Player>)` constructors (all call sites use the `String`-based constructors).
- `SemanticVersion.equals(Object)` and `hashCode()` (version objects are never used as map keys or set members; the Object defaults now apply).
- The spigot module no longer disables `-Xlint:deprecation` and `-Xlint:removal`; the module compiles clean with both enabled.
## Lockable Blocks Catalog by Family
A new reference file, `LOCKABLE_BLOCKS_BY_FAMILY.md`, lists the lockable block catalog grouped by family (`TILE_ENTITIES`, `SHULKER_BOXES`, `BLOCKS`, `DOORS`, `ENTITIES`) instead of by sub-family. Every material under a family header was verified against the `BlockFamilyParser` registry that defines family membership; it is an additional view on top of the existing `LOCKABLE_BLOCKS_REFERENCE.md`, which stays unchanged. Both files carry a cross-reference at the top so a reader lands on whichever ordering they need. No code, config, or translation changes.
## Blocks Category Split into Sub-Screens
`AdminConfigBlocksDialog` was the largest config category (13 settings). It now opens a three-way chooser matching the dialog editor's split:
- **Locking**: lock-on-place by default, public-is-friend default, max locked blocks, hint cooldown, friend search similarity, disable friends.
- **Behavior**: modern family blocks, redstone disallowed, hopper logic, piston movement, explosion protection, shulker break, allow break protected blocks, spawn protection.
- **Effects**: lock effects, lock sounds, use menus, use dialogs, timed access max duration.
`AdminConfigBlocksInventory` mirrors the same three sub-screens for the inventory editor (its MAIN screen now hosts the three sub-category buttons), keeping the dialog/inventory parity rule intact. Three new `TranslationKey` entries (`DIALOGS__ADMIN_CONFIG__BLOCKS__LOCKING_TITLE`, `...__BEHAVIOR_TITLE`, `...__EFFECTS_TITLE`, "Locking"/"Bloqueo", "Behavior"/"Comportamiento", "Effects"/"Efectos") were added to both language files; the settings themselves reused their existing keys.
## Multi-Candidate Player Search
When an add-friend search falls below the configured `friend_search_similarity` threshold, the plugin no longer returns a dead-end "player not found" if any candidate is close enough:
- `PlayerLookup.findCandidates(query, minSimilarity, limit, exclude)` returns up to `limit` candidates from the same merged online/offline set `findBestMatch` already scans, paired with their similarity scores (`ScoredMatch` record), sorted by descending score.
- The call sites in `FriendManageDialog` (blocks) and `EntityFriendManageDialog` (entities) now fall through to the candidate list instead of the error message; the "player not found" message only appears when the candidate list is empty.
- `FriendCandidateSelectionInventory` shows up to 26 candidates as player heads (name plus match percentage), back to the friend manage screen on selection or cancel.
- `FriendCandidateSelectionDialog` is the dialog equivalent with six candidates per page and prev/next paging, gated by `shouldUseDialogs(player)` the same way every other dialog screen is.
- New keys: title `inventories.friends.select_candidate` ("Select a candidate" / "Selecciona un candidato"), hint `dialogs.friends.select_candidate_hint` ("Who did you mean? Select a candidate:" / "¿A quién querías decir? Selecciona un candidato:"), and score tooltip `dialogs.friends.select_candidate_score` ("Similarity: {score}%" / "Similitud: {score}%") in both language files.
## Built-in Skin Resolution & Player Head Rendering
`SkinCache` and player head item rendering received a major overhaul to guarantee player skins render reliably across all inventory screens, including on offline-mode and local development servers:
1. **Instant online player profile resolution**: `SkinCache` checks whether a player is currently online on the server before making any external network requests. If online, `player.getPlayerProfile()` (which already carries skin textures from Bukkit or SkinsRestorer) is returned instantly in 0 ms without HTTP calls.
2. **Name-only resolution fallback for offline UUIDs**: On offline-mode servers (`online-mode: false`), Bukkit generates version-3 offline UUIDs that Mojang's session servers reject. `SkinCache` now falls back to name-only resolution (`Bukkit.createProfile(name).update()`) which queries Mojang's name-to-UUID endpoint first to retrieve the real Mojang UUID before fetching textures.
3. **PlayerDB third tier**: When both Bukkit update and SkinsRestorer fail, `SkinCache` resolves the Mojang UUID via `https://playerdb.co/api/player/minecraft/{username}` and fetches the signed texture from `https://sessionserver.mojang.com/session/minecraft/profile/{uuid}`.
4. **Cache failure protection**: `SkinCache` no longer permanently caches textureless profiles, allowing future attempts (when a player logs in or network recovers) to successfully resolve skins.
5. **Universal inventory head support**: All 13 inventory GUIs that display player heads (`UserMenuInventory`, `AdminMenuInventory`, `AdminConfigInventory`, `UserSettingsInventory`, `BlockLockInventory`, `BlockInfoInventory`, `EntityInfoInventory`, `FriendManageInventory`, `EntityFriendManageInventory`, `FriendSearchResultInventory`, `FriendDetailInventory`, `PlayerListInventory`, `AuditInventory`) now use `setPlayerSkullAsync`. Buttons and heads render with the player's skull and skin while preserving legacy color code formatting on titles and lores and retaining PersistentDataContainer metadata (such as `audit_player_uuid` in AuditInventory).
## Async-Safety Guard
A new `AsyncGuard` utility fails fast when NBT/tile-entity code runs off the primary thread. On Paper/Spigot, `AsyncGuard.assertSync(operation)` throws `IllegalStateException` carrying the operation name when `Bukkit.isPrimaryThread()` is false; on Folia the check no-ops, since Folia enforces region ownership itself and throws on an actual violation. The guard now protects `FriendSupportingHandler.addFriend`, its `compound()` accessor, and every `BlockNBTHandler` constructor.
As part of wiring the guard in, the only async NBT caller found in the cross-check, `InactivityCleanupTask`, was reworked: the task now collects candidates on the worker thread (reading only async-safe statistics data) and processes each candidate's NBT on the primary thread via one scheduler tick per batch, so the new guard never trips on a legitimate path. `DebugCommand`'s diagnostics were audited and already schedule their NBT checks on the primary thread, so they needed no changes. Pure internal diagnostics: no new translation keys, no new config keys.
## Translation Changes
Eight new keys were added in this release, each in both `translations_en.yml` and `translations_es.yml`:
- `messages.admin_reload_failed`: reload failure message, used by both dialog reload buttons.
- `dialogs.admin_config.blocks.locking_title`, `...behavior_title`, `...effects_title` ("Locking"/"Bloqueo", "Behavior"/"Comportamiento", "Effects"/"Efectos"): the three sub-screen titles of the split Blocks category.
- `inventories.friends.select_candidate` ("Select a candidate" / "Selecciona un candidato"), `dialogs.friends.select_candidate_hint`, and `dialogs.friends.select_candidate_score` ("Similarity: {score}%" / "Similitud: {score}%"): the multi-candidate selection screen, in both the inventory and dialog UI.
- `console.update.available_dev` ("A new experimental development build (BEDev) of BlockProt Reloaded is available: {version}. It is NOT a stable version and is only published on GitHub." / "Hay una nueva build de desarrollo experimental (BEDev) ..."): the console counterpart of the in-game dev-build message, so a pre-release server is no longer told a dev candidate is a "stable" version (see "Console Update Notification for Dev Builds").
All other screens reuse the existing key set, so the English and Spanish files stay the single source of truth for both interfaces.
## Shared Dialog Palette
The six pastel colors used across the dialog system (`SOFT_GRAY` 0xAAAAAA, `PASTEL_MINT` 0x8FE3B0, `PASTEL_CORAL` 0xF0A0A0, `PASTEL_GOLD` 0xD2B48C, `SOFT_BLUE` 0xA0C4E8, `PASTEL_PURPLE` 0xC8A0E0) and the `stripColor` helper that removes Minecraft color codes from translated strings were duplicated verbatim in 18 dialog classes. They now live in one static-only class, `BpDialogStyles`, and the 18 classes (About, AdminMenu, Audit, BlockInfo, BlockSettings, Debug, EntityBlockSettings, EntityFriendManage, EntityInfo, FriendManage, Info, Integrations, LockableCategory, Stats, Unlock, Update, UserMenu, UserSettings) import them statically. Dialogs that intentionally use a different accent color (`AutoDrop*`, `BlockLock`, `Lockables`, `WorldLockable*`, `FriendCandidateSelection`, `Protdel`) and the `AdminConfig*` family, which already centralized its own palette, keep their local definitions. Pure internal change; no player-visible behavior or colors changed.
## Console Update Notification for Dev Builds
The in-game update notification already distinguished a BEDev candidate from a stable or hotfix release. The console notification did not: a server running an experimental build that ran `/bp update` from console, or read the mirrored record in `logs/blockprot-*.log`, would see "A newer STABLE version ... is available" even when the detected release was a BEDev build. A new `console.update.available_dev` key ("A new experimental development build (BEDev) of BlockProt Reloaded is available: {version}. It is NOT a stable version and is only published on GitHub." / "Hay una nueva build de desarrollo experimental (BEDev) ...") was added to both language files, and the console path now picks the message by the same release-channel split as the in-game path (stable, hotfix, or dev). The boot checklist line is unaffected; it already used its own channel-agnostic wording.
## Debug Coverage of the Version-Suffix Table
`/blockprot debug` group 25 (Utility helpers) now exercises `SemanticVersion` against the suffix-ranking table documented in `gradle.properties`: it confirms blank is a stable release, `BEDev`/`bdev`/`SNAPSHOT-3` are pre-releases, `hotfix` and `fix.1` are hotfixes ranked above the clean release, legacy `-RELEASE` is normalized to a clean release, and `exp` is experimental. It also verifies compare order between ranks, the numeric counter tiebreak (`1.3.4-BEDev.2 > 1.3.4-BEDev.1`), numeric-segment comparison, and `baseVersion()` stripping. This closes the one remaining untested utility the version-detection system relied on. No new translation keys were needed (debug output goes through `BlockProtLogger`).
## Admin Menu Update Button Notifies Operators Only
The "Check for updates" button in the Admin Menu inventory previously sent the update notification to every online player, not only operators. As of this release it filters its recipients to ops, matching the join notification which is already op- and config-gated (`notify_op_of_updates`). Players keep only the user-facing BPR options; admins configure and receive everything. No new translation keys; the button, its translated label, and its tooltip are unchanged.
## Debug Diagnostics Coverage
`/blockprot debug` no longer leaves whole subsystems untested. The diagnostics suite grew from 20 to 28 groups:
- **Group 21, All dialogs**: builds every dialog screen through a no-op bridge (`DialogBridgeFactory.setTestBridge`) so the full dialog UI is smoke-tested without opening real dialogs on the player. 39 of 40 screen classes are exercised with the same debug-chest and temporary-ArmorStand fixtures the inventory group uses; only `AdminConfigValueDialog` (a field-input helper without a `show` entry point) is skipped. The real bridge is restored afterwards.
- **Group 17, All inventories**: grew from 18 to 40 inventory classes. All 10 `AdminConfig*Inventory` editors, the auto-drop, lockables, per-world, unlock, candidate-selection, entity, transfer-search, and world-delete screens were added. `PlayerListInventory` is skipped with a logged reason: its only entry point opens a live GUI, unlike every other screen's `fill()`.
- **Group 22, Commands registered**: confirms the `blockprot` command resolves with an executor, and that every `Permissions` enum constant is declared in the `plugin.yml` permissions section (read from the jar resource). It also verifies all 18 `*Command` classes load and that all 8 integration classes are actually constructed in `onLoad()` by comparing against the live integration list, so a class that exists on disk but was never wired up now shows up as a failed check.
- **Group 23, Listeners registered**: compares the listeners actually registered through `HandlerList` against the 17 active listener classes, so a listener that exists on disk but was never wired up in `onEnable()` now shows up as a failed check.
- **Group 24, SkinCache tiers**: exercises the online/cached profile path for the debug player and confirms the SkinsRestorer tier no-ops cleanly when SkinsRestorer is not installed.
- **Group 25, Utility helpers**: exercises the pure static logic: `DurationParser` parse/format, `DurationLimits` validation, `StringUtil` distance/similarity, `BlockUtil` block names, `AsyncGuard` main-thread assertion, `PlayerNameResolver`, `TemporaryActionBar`, `BpDialogStyles` palette and `stripColor`, `DialogNavigation` back buttons, `DialogState` push/pop, `ReloadReport` snapshot diffing, `IntegrationConfig`, and `AdminConfigValueDialog` through the no-op bridge.
- **Group 26, NBT sub-handlers**: exercises `FriendSupportingHandler`/`FriendHandler` friend add/remove/query on a chest fixture, `RedstoneSettingsHandler` protection toggles, `BlockCountStatistic`, `EffectGeometry` bounding boxes, `ProtectedBlockCache` mark/unmark, `EntityProtectionHandler` on a temporary ArmorStand (structural-only when the entity type is unsupported), `LocationListEntry`, and `PlayerInventoryClipboard` set/contains/remove.
- **Group 27, Structural classes**: load-checks the classes that cannot be instantiated from a diagnostics run (event classes, chat-input gateways, tasks, console, metrics formatter, config base, storage, abstract statistic bases) so their presence in the jar is proven instead of silently skipped.
- **Group 28, Class coverage**: enumerates every screen class actually present in the plugin jar under the four screen packages (inventories, dialogs, commands, listeners) and reports a failure for any concrete class the run did not touch, so a screen added in a future version shows up as a red line instead of silently shipping untested. Classes are matched by the screen naming convention (`*Inventory`, `*Dialog`, `*Command`, `*Listener`); abstract classes, interfaces, enums, inner classes, and non-screen helpers are skipped. In a dev workspace (not running from a jar) the group logs that it is skipped instead of failing. Current tree: 45 inventories, 41 dialogs, 18 commands, 19 listeners.
Together with the earlier groups, every one of the 214 classes under `de/sean/blockprot/bukkit` is now either exercised directly or load-checked. All new checks report through the existing debug logger and translation keys; no new keys were needed.
## Build and Compatibility
- `gradle.properties` set to `1.3.5` with a blank `versionSuffix`, shipping as a clean stable release.
- No dependency or toolchain changes; the plugin still targets Java 21 bytecode with `api-version 1.21.1`, keeping the dialog system gated behind the Paper 1.21.7 runtime check.
- The dialog and inventory editors behave identically regardless of `use_menus`; `use_dialogs` only decides which of the two opens.
- The per-world lockables dialog entry appears only while `per_worlds_config: true`, matching the legacy inventory button.
## Additional Fixes and Polish
Additional fixes and polish included in this release:
- **ESC returns to the parent menu in inventories**: pressing ESC (or E, or closing a submenu window) on an inventory that was opened from another BlockProt menu now reopens the parent menu one tick later, using the same origin stack the back button uses. Programmatic navigation (a menu that opens another menu in code) is unaffected because the new window is already open when the check runs. Top-level menus still close normally on ESC.
- **Auto Drop is now reachable only from Lockables**: the Auto Drop entry was removed from the Admin Menu (both the inventory and the dialog version). The screen is still available under `/bp lockables > Auto Drop`, matching the intended flow, and its back button returns to Lockables from every level of the auto-drop screen (family list and per-family page).
- **Auto Drop now applies to operators and admins**: regular auto-drop blocks previously skipped the breaker when they held operator or admin privileges, while shulker boxes always used the inventory path; now every block listed in `auto_drop_to_inventory.blocks` delivers its drops to the breaking player's inventory for all players alike (still excluding creative mode). The admin guide was updated to match.
- **Blocked breaks no longer leak auto-drop items**: when a player without access broke a protected block that was listed in `auto_drop_to_inventory.blocks`, the block's item was placed in their inventory one priority step before the protection handler cancelled the break, duplicating the item while the block remained intact. The auto-drop handler now mirrors the protection decision and skips breaks that are about to be blocked, so nothing is delivered. The check covers every lockable block: the original fix only guarded tile-entity holders, so doors, trapdoors, fence gates, beds, anvils and cauldrons still leaked their item until the guard was moved above the tile-entity branch.
- **Auto drop now covers entities**: the same auto-drop-on-break behaviour applies to the lockable entity families (item frames, glow item frames, storage minecarts, hopper minecarts, chest boats). Their contents drop straight into the breaking player's inventory, the same protection mirror applies (a protected vehicle breaks only for its owner or an admin; a linked frame follows its block's protection), and creative mode is still excluded. Nothing is delivered when the break is about to be blocked, so no duplication. The admin guide now documents this.
- **Auto-drop block search**: the Auto-Drop screen (inventory and dialog) gained a creative-style block search: a compass entry in the inventory and a search button in the dialog open a chat prompt, and matching materials are listed in relevance order (exact match, starts-with, word prefix, contains, Levenshtein within 2 edits) with the same one-click toggles as the family pages. A query with no matches shows a notice.
- **Debug check counters updated**: the diagnostics suite now exercises `AutoDropSearchInventory` (group 17), `AutoDropSearchDialog` (group 21), and `AutoDropEntityListener` (group 23); group 28's tree count is now 45 inventories, 41 dialogs, 18 commands and 19 listeners.
- **Back buttons return to the menu they came from**: About opened from the Admin Menu dialog returns to the Admin Menu dialog (it previously closed), BlockLock opened from the User Menu returns to the User Menu dialog, and the auto-drop back chain follows the actual entry point instead of hardcoding Lockables.
- **Lockables categories match the inventory**: the dialog category list now uses the exact same classification as `LockablesInventory`: a Beds category was added between Trapdoors and Gates (beds were previously lumped into Interactive), Storage gained the missing tile entities (shelves, crafter, brewing stand, hopper, dispenser, dropper, beehive, bee nest, jukebox, lectern), workstations match the seven tables plus anvil, hanging wall signs are recognized, Entities lists the whole entity family, and remaining block-family members fall back to Interactive. Category order is identical to the inventory enum.
- **Access Log hides the owner**: the block and entity access log (both the inventory and the dialog view) filters out the owner's own entries, showing only accesses by non-owner players. Actions logged by the owner's own container interactions no longer clutter the history.
- **Pale oak signs are lockable**: PALE_OAK_SIGN and its wall, hanging, and wall-hanging variants were rejected by the tile-entity validator in `DefaultConfig` because signs were missing from the tile whitelist; the validator now accepts every `_SIGN` variant, so entries in `blocks.yml` resolve to a lockable material. The blocks.yml integrity check no longer reports them as mismatched.
- **Separate debug report file**: `/blockprot debug` now writes to `logs/debug-report-<timestamp>.log` next to the session log, and while a run is active the session log receives nothing (no more diagnostic noise mixed into the activity log). The report opens with a header that includes the plugin version, the player, server, API and Java versions, and compatibility strings; it ends with an explicit end marker. Both file paths are announced in chat when the run finishes.
- **Debug checks closed**: group 17 skips `EntityInspectContentsInventory` with a logged reason (it requires a live container entity, not reproducible with an ArmorStand), group 19 accepts the pale oak sign family, and group 28 now covers `BlockProtCommand`, which group 22 touches when it verifies the registered executor. The diagnostics run reports 0 failures on a stock server.
- **Auto-drop now delivers the real drops for every listed block**: the non-shulker path used `setDropItems(false)`, which the server ignores for tile-entity contents, so chests, trapped chests, furnaces, blast furnaces, smokers, dispensers, droppers, hoppers, barrels, brewing stands, chiseled bookshelves, decorated pots, and crafters delivered only the empty block item to the inventory while their actual contents spilled on the ground; doors and beds (double blocks) were equally fragile because the cancel path did not remove the partner half. The handler now mirrors the shulker path: it cancels the break, captures both `getDrops(tool)` and the tile-entity snapshot inventory via `Container.getSnapshotInventory()`, sets the clicked block (and the verified complementary half for doors and beds) to AIR, and delivers the block item plus the contents to the breaker's inventory in one step. Only the clicked half of a double chest is delivered (its single 27-slot snapshot, not the combined 54-slot view), so no items are duplicated or lost; doors and beds still drop exactly one item, matching vanilla, while both halves are removed. The stat/hopper cleanup the protection handler normally runs on a successful break is now replicated on the cancelled path, so owner counters and hopper caches stay consistent. The item-frame auto-drop now resolves projectile breakers too, so a frame or glow frame knocked off by an arrow or trident routes its contents and itself to the shooter the same way a direct punch already did.
- **Vehicle destruction exception fix**: `AutoDropEntityListener.onVehicleDestroy` now filters out `null` items (empty slots) when collecting the contents of destroyed chest boats and storage minecarts, preventing an `IllegalArgumentException` from Bukkit's `addItem()`.
- **Bed bottom auto-drop fix**: `BlockEventListener.onAutoDropBlockBreak` now retrieves drops from the opposite half of double blocks (such as beds) when the clicked half returns empty drops, ensuring the item is always delivered regardless of which part is broken.
- **Auto-drop configuration debug check**: `/blockprot debug` group 4b (AutoDrop) was added to verify the auto-drop setting and the configured auto-drop materials list, ensuring the configuration matches expectations in diagnostic reports.
- **AuditDialog crash on entities fix**: Trying to open the Audit Log from a block lock dialog applied to an entity (like a Boat or Minecart) will no longer crash the server with a "not a lockable block" `RuntimeException` if the entity is standing on a non-lockable block like snow.
- **Dialog toggle visual glitch fix**: Added a 1-tick delay when reopening Paper/Floodgate native dialogs after a button click (such as toggling boolean config values), preventing race conditions where the Bedrock or Java client would occasionally ignore the new dialog state. (Reported by TankObliterator)
- **Block name input menu flow**: Fixed a timing issue where clicking "Set block name" in block lock menus immediately reopened the menu on inventory close, allowing players to type their desired name in chat uninterrupted.
- **Author and maintainer credits separation**: Updated the about command output and dialog labels so author and maintainer credits are rendered on distinct lines with dedicated translation keys.
- **Statistics phantom block and air filtering**: Statistics and block listings now filter out coordinates where the block in the world has been destroyed or turned into non-lockable materials like air or snow, preventing phantom block entries or incorrect chest icons.
- **First start guide pastel styling**: updated the in-game first start guide broadcast on operator join (`first_run`) from legacy harsh gold and yellow to the plugin's standard pastel hex color scheme (`#D2B48C` pastel gold, `#8FE3B0` pastel mint, and soft gray) in both English and Spanish translations.
- **Context-aware Back vs Close in menus**: inventories opened directly via commands (such as `/bp protdel`, `/bp lockables`, `/bp unlock`, `/bp stats`, `/bp expiry`, and auto-drop screens) now detect when they have no parent menu origin and correctly display the Barrier "Close" button instead of "Back", cleanly closing the inventory on click.
- **Expanded bundled language templates (25 languages total)**: added translation templates for Arabic (`translations_ar.yml`), Hebrew (`translations_he.yml`), Romanian (`translations_ro.yml`), Swedish (`translations_sv.yml`), and Ukrainian (`translations_uk.yml`) in `spigot/src/main/resources/lang/` and registered them in `Translator.DEFAULT_TRANSLATION_FILES`. `AdminConfigLanguageInventory` and `AdminConfigLanguageDialog` were expanded to display and paginate all 25 languages. Full key parity (774 keys) is maintained across English and Spanish reference files.
- **BlockUtil regex caching**: cached the underscore pattern in `BlockUtil` as a pre-compiled `Pattern` instead of recompiling per call, reducing allocation overhead during block and item name formatting.
## Future Changelog Format (1.3.6+)
Starting with release 1.3.6, BlockProt Reloaded release notes and changelogs will adopt the [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) format (with standard Added, Changed, Deprecated, Removed, Fixed, and Security sections) to ensure structured, consistent, and easily diffable change records across releases.
## Commits
- [`5cce389`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/5cce3895fc43ff15671004cb679acbb51f22a3cb): Update 1.3.5.RELEASE_NOTES.md.
- [`0ea5599`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/0ea55998b6572a47d1fec747683cc131af485b8d): Add missing commits to 1.3.5 commits section.
- [`a3280f5`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/a3280f5cbc3ebf8564c19c2cf42d807caff134d9): Add title image to LOCKABLE_BLOCKS_BY_FAMILY.md.
- [`dfccd89`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/dfccd89f6ea12ed38c265f2f9ab919ba992c7717): Create LOCKABLE BLOCKS BY FAMILY.png.
- [`c000402`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/c00040266bd1bb161ec98785325bec43d5ef2155): Cache underscore regex in BlockUtil; add 1.3.5 commits section.
- [`7ac7ebe`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/7ac7ebe75795ab80a7f1079dc309b950653c8571): Improve menu origin awareness, add first-run pastel styling, and expand language templates.
- [`de48b19`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/de48b1965f74a3d914c91c9ba32f34ba622ce44d): Use updated isLockable API.
- [`9272fe6`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/9272fe6d093b22b3c0ad6bbc79e27b4bd7f91005): Fix release notes image paths.
- [`8457784`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/84577841b3d4cea5478614e21149c6059a33a76e): Fix auto-drop: block contents, door/bed halves, and frame projectile breaks.
- [`4ed0c1a`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/4ed0c1aa0ca6b7edd12a3ea3525e80156fdfd169): Renamed release images folder.
- [`cf95251`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/cf95251f43d8d338d4a3a13599e6ca2b3fabcad9): Update MODR_HANG_README.md.
release
BlockProt Reloaded 1.3.4-hotfix
1.3.4-hotfix8 авг. 2026 г.97Minecraft: 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2bukkit, folia, paper, purpur, spigot
Что нового

## Summary
1.3.4-hotfix.1 is a hotfix on top of the 1.3.4 release. It fixes the critical startup crash on Spigot 26.2 (`NoClassDefFoundError: net/kyori/adventure/text/Component`) that prevented the plugin from enabling, the second wave of Paper-only runtime crashes that appeared once the plugin could enable, two `NoSuchMethodError` crashes when opening the block info panel and the sign prompt, menu buttons that printed `usage: /bp <user/admin>` instead of doing anything, and back buttons that closed the whole menu instead of returning to the previous window.
The hotfix also improves friend search across blocks, pets, and dialogs, and removes the anvil GUI in favor of chat input everywhere.
> **Note:** This hotfix does not claim to make every feature work correctly on Spigot or any other non-Paper software. It fixes what was detected during a test run on the software this server environment targets (Paper), plus the Spigot failures that same test surfaced. That test was a one-time, spontaneous check; I normally only test on Paper, the main target. Spigot 26.2 was the only software that errored, and lower versions (26.2 down to 1.21.1) were not tested, so errors there are possible. I always recommend the latest, most up-to-date version. If you run into an error, please open a GitHub issue so I can resolve it.
## Spigot Startup Crash
On Spigot 26.2 the plugin could not enable: it threw `NoClassDefFoundError: net/kyori/adventure/text/Component` with a `ClassNotFoundException` for the same class, because Spigot and vanilla CraftBukkit do not ship Kyori Adventure and do not expose Adventure-based `sendMessage`, `sendActionBar`, or `ItemMeta#displayName` methods.
Fixed with a `ComponentMessages` runtime wrapper that checks via reflection whether the server exposes the Adventure methods. On Paper, Folia, and Purpur it calls the native APIs; on Spigot and CraftBukkit it serializes to legacy colour-coded strings and calls the plain-string equivalents. The build also shades the required Kyori Adventure transitive dependencies so those environments can resolve the classes at runtime.
## Runtime Crashes Found After the Startup Fix
With the startup crash fixed, a second wave of Paper-only API calls crashed on Spigot as they were used. All of the following are now guarded with a Spigot-compatible fallback:
- **Block events** (place, break, burn, redstone) broke because a Paper-only `NamespacedKey` accessor was unguarded.
- **Player join** broke because a Paper-only profile-creation overload was unguarded.
- **Every inventory GUI** broke because a Paper-only inventory-creation overload was unguarded.
- **Block locking, friend management, and renaming** (chests, doors, beds, other tile-entity blocks) broke because Paper-only block-state accessors were unguarded.
- **Skull rendering** in friends lists, block/entity info, and the audit log used a Paper-only profile type; these now use the standard Bukkit profile API.
- **Direct action-bar calls** across dialogs, inventories, listeners, and commands crashed on Spigot; they now all go through `ComponentMessages`.
## Inventory Menus & Navigation
- **Menu buttons now run their actions.** Buttons that previously executed `/blockprot` subcommands through `performCommand` (which prints `usage: /bp <user/admin>` and does nothing in menu mode) now execute their action directly: transfer (`/bp transferall`), About, Config, Auto Drop, and Debug.
- **Back buttons restore the exact window you came from.** The menu system now keeps an origin stack instead of a single overwritten origin: every menu pushes its own origin before opening a child menu, and `goBack` pops it, so the admin menu -> lockables -> auto drop/worlds chain, the stats/info lists, settings -> friends, and the block lock submenus all walk back level by level.
## Update Notifications & Version Channels
- **Version ranking now distinguishes three tiers:** experimental pre-releases (BEDev/snapshot), clean releases, and post-release corrections (hotfix/patch/fix). The old alpha/beta/rc/dev special-casing is gone.
- **Channel-aware update messages.** Stable servers only see stable updates; hotfix messages name the release they fix; BEDev messages state that the build is experimental and not a stable version.
- **Boot banner** announces which channel the server runs, and experimental builds create a safety backup on startup when backups are enabled.
## Server Software Detection
- On startup the plugin detects the real server software and warns when it is not Paper or a Paper fork (Spigot, CraftBukkit, hybrids, unknown). The warning is non-fatal; the plugin still loads with its fallbacks. Pure CraftBukkit remains hard-blocked.
- Support for Spigot and Bukkit is planned to end with 1.3.6, when a separate BlockProt Reloaded Legacy project begins.
## Friend Search, Chat Input and the Discord Case
- **Case-insensitive search.** The fuzzy name comparison lowercases both strings, so a correctly-typed but differently-cased name is found.
- **Shared player pool (`PlayerLookup`).** Merges every online player with the offline cache, so an online player is always found and a known offline player still is. All friend-add entry points (block search, pet/entity search, both dialog equivalents) and the transfer-target search use this same pool.
- **Pets/entities now get search results.** They open the same search-results screen as block friends instead of silently auto-adding the best match, and search failures report a real error message instead of a misleading "player not found".
- **Chat input everywhere, no more anvil GUI.** Every free-text prompt (friend search, transfer search, block/entity naming, admin config values, world-expiry duration) now uses chat input on Paper and Spigot alike. Block/entity renaming uses its own label (e.g. "Set block name") instead of the generic player-search wording, and the prompt no longer tells players to press Tab.
- **The Discord case.** A case about friend search not finding anyone was reported via Discord; the issue was that user's other plugins, not this one. Improvements were applied anyway.
## Raid Detection Off by Default
`raid_detection.enabled` now defaults to `false`, matching `entity_protection.enabled`. Both features remain fully working; administrators opt in explicitly in `config.yml`.
## Visible Download Link in Update Notifications
The update notification shown to operators now also prints the download link as visible text in chat, not only as a clickable component: the message ends with a `| Download:` prefix and the release URL itself, underlined in white and still clickable (hover tooltip: "Click to visit the GitHub Releases page"). This guarantees the notification always satisfies the standing requirement: it states that a new version is available, names which version, and gives the download link, no matter where the player clicks.
## Boot Banner Update Status
The startup checklist now ends with an `Update Check` line that shows the real check result instead of a separate console warning: green (`● Up to date (1.3.4)`) when the installed version is the latest release, red/coral (`● New version available: 1.3.5`) with the download URL indented below when a newer version exists, and gold when the installed version is ahead of the latest public release. The line waits up to 3 seconds for the asynchronous check and, if it is still in flight, falls back to a synchronous request (with its own timeouts) so a slow GitHub API still yields a real result; `Not checked` only appears when the API is genuinely unreachable. The in-game update dialog now shows the release URL as visible text next to the underlined version (`Download: v1.3.5 | https://github.com/...`), still clickable. All new strings are translatable (EN/ES).
### Hotfix-ahead update message
- **Running a hotfix ahead of the latest published release now shows a dedicated message.** Previously, when `UpdateChecker` found the running version ranked above the latest GitHub release (`latestVersion.compareTo(currentVersion) < 0`), it always reported the *latest published* version with the generic `messages.update.ahead` key, which read "BlockProt version is ahead of release (X)" and named the older public tag instead of the hotfix the server is actually running. When the running version is a hotfix (`SemanticVersion.isHotfix()`), the in-game chat, the console log, and the boot banner now use the new `messages.update.ahead_hotfix` translation key, which prints the running hotfix version (`{version}` = `currentVersion`) and the release it corrects (`{base_version}` = `currentVersion.baseVersion()`), instead of the older public tag. Non-hotfix ahead builds keep the existing `messages.update.ahead` key with `{version}` from `latestVersion`. Both the in-game `UpdateChecker` path and the console/logger path use the same two-branch selection.
- **The `ahead` translation was reworded** to name "BlockProt Reloaded" and say "ahead of the published release" (EN: `BlockProt Reloaded is ahead of the published release ({version})`, ES: `BlockProt Reloaded está por delante del lanzamiento publicado ({version})`). The new `ahead_hotfix` key reads `BlockProt Reloaded is running hotfix {version}, ahead of the published release ({base_version})` (ES: `BlockProt Reloaded está ejecutando el hotfix {version}, por delante del lanzamiento publicado ({base_version})`). A new `MESSAGES__UPDATE__AHEAD_HOTFIX` entry was added to `TranslationKey.java`; EN and ES were updated together.
## Commits
- [`65fa6e3`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/65fa6e39fe64ffa230b7abb3eae22c082cb5c307): Update UpdateChecker.java (visible download link in update notifications).
- [`2dc438f`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/2dc438f88f79d47c5c29de69281914427bd83bae): Update build.gradle.kts.
- [`d09e08e`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/d09e08eb34bb1ee8cdbf61268ee7041cfb4dfb4d): Update BlockProtConsole.java.
- [`087b4b0`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/087b4b0fc0747ffdd218c15971bc7d59395eb5b0): Add ComponentMessages utility for cross-platform compatibility.
- [`85c584d`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/85c584d74b47ba05940f05cb213eb7cfab750f89): Fix Spigot startup & menu/navigation issues.
- [`f7e16cb`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/f7e16cbd76d0caade74efcb137278be2fd934d92): Improve update notifications for hotfixes and dev builds.
- [`975a722`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/975a7222c47ee8d860704a55e316a352707bf84f): Add BEDev/hotfix channels & Spigot fixes.
- [`0822163`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/0822163f1d46ab3526904381541dc6d1a8307a86): Create 1.3.4 HOTFIX.png.
- [`defbda5`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/defbda558eba399cf036a94f38352dbdb5f823fc): Hotfix: friend search, chat input, raid toggle & more.
- [`59af0a0`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/59af0a05727f007e363652b2ed4ec0963eaa9135): Remove unnecessary text (#_<-).
- [`2e346e2`](https://github.com/VictorGugug/BlockProt-Reloaded/commit/2e346e2754ab946295d97988326d4976d1931d90): Handle hotfix-ahead updates and refresh translations (new `ahead_hotfix` key rewords the ahead-of-release message to name the running hotfix and its base, and rewords the existing `ahead` key).
release
BlockProt Reloaded 1.3.4
1.3.43 авг. 2026 г.38Minecraft: 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2bukkit, folia, paper, purpur, spigot
Что нового

## Summary
This release adds a Paper dialog-based menu system as an alternative to the legacy inventory GUIs. **The recommended peak experience** is `use_menus: true` combined with `use_dialogs: true` on Paper 1.21.7+: consolidated `/bp user` and `/bp admin` menus rendered as native Minecraft dialog windows, with an in-game `AdminConfigDialog` to edit `config.yml` without touching files.
When `use_dialogs: false` (default), behavior is unchanged from previous versions: legacy inventories work on any server software.
An in-game admin config editor (`AdminConfigDialog`) mirrors `config.yml` section by section, letting admins modify settings directly. The lockables menu was reworked with a sub-dialog for individual material toggling.
A new language management system adds language enable/disable via `lang/lang.yml`, an in-game language selector cycling through the 15 registered languages with completion percentages, and automatic translation completion tracking.
Config.yml had minor cleanup (removed a deprecated leftover config block, added the `use_dialogs` key), and the plugin log file now recovers automatically if it's deleted or truncated while the server is running.
> **Note:** The Residence/GriefPrevention/ClaimChunk integrations, the centralized `integrations.yml`, the Paper `PlayerProfile` skin-resolution migration, and the per-block protection expiry removal were **not** part of the 1.3.4 commit range: they were already present as of 1.3.3 and are documented in the 1.3.3 release notes. They have been removed from this document to avoid re-claiming pre-existing work as new.
## Community Feedback Fixes
A tester gave feedback on the dialog system shortly after it landed. Three items came out of that:
- **`/bp user` now takes priority over `/bp admin`** when `/blockprot` is run with no arguments, matching the convention used by other plugins. Admins still reach the admin menu explicitly via `/bp admin`.
- **The Statistics tab in `/bp user` is now Placements.** It shows your locked block count against the server limit (`Your Protected Blocks: 12/24`, or just the count if the server has no limit set), lists your blocks grouped by material with world and coordinates, and dropped the global server-statistics toggle entirely, since that never belonged on a personal stats screen. Clicking a block opens it directly for editing instead of only offering a teleport. The admin-side Statistics screen (Admin Menu > Stats) is unchanged and still has both the player and global-server pages.
- **Admin config editor buttons now show a short, readable name** instead of the raw `config.yml` key (for example `lock_hint_cooldown_in_seconds` now reads "Lock Hint Cooldown"). The longer description and the raw key are still shown in the tooltip for anyone who wants the technical detail.
The sign-closing-instantly bug reported in the same feedback was already fixed earlier in this cycle by the native dialog text input described below.
### Follow-up bug found during that same testing pass
- **(bug) Opening any container could throw `RuntimeException: Given block X is not a lockable block/tile entity` and spam the console**, most visible with `per_worlds_config: true` on a world whose per-world lists are still empty (the default right after `/bp lockables` auto-scans a new world). Several listeners (`InventoryEventListener`, `BlockEventListener`, `PistonEventListener`, `RedstoneEventListener`) checked whether a block was lockable using the config-wide check, which ignores `per_worlds_config`, while `BlockNBTHandler` always validates per-world. When the two disagreed, the handler threw. All of those checks now use the per-world-aware check so they agree with `BlockNBTHandler`.
- **The Placements block list showed a "click to teleport" hint even though clicking actually opened the block's edit dialog** whenever the block was still lockable (teleport only happens as a fallback once a block drops out of the lockable list). The hint now matches whichever action a click will actually perform.
### Lockables toggle and auto-reload timing fixes
- **(bug) Disabling specific materials inside a mostly-active lockable category could silently re-enable them.** `BlockFamilyParser.toFamilyExpression()` could write a malformed expression like `[* CHEST COPPER_CHEST ...]`: a global `*` (meaning "everything") followed by plain material names that do nothing to exclude anything from that `*`. The next time that expression was parsed, every material in the family came back active. Fixed so the compact writer never mixes a global `*` with bare inclusion names; it always falls back to the explicit exclusion form (`*-TAG -missing...`) in that case.
- **(bug) Auto-reload after a lockables change sometimes fired much later than `auto_reload_delay_seconds`, or an extra reload showed up out of nowhere.** The file watcher ignored its own writes for a fixed 3-second window regardless of the configured delay. With a higher delay, several rapid toggles, or slow OS-level file-watch delivery, that window could expire before the write's own change event arrived, so the watcher mistook its own write for an external one and queued a second reload on top of the first. The self-write suppression window is now `max(3s, auto_reload_delay_seconds + 2s)` instead of a fixed 3s.
- **(bug) The hover tooltip on an individual material button in the lockables dialog read "Click to enable all." / "Click to disable all."**, even though the button only toggled that one material. Individual material buttons now use new `dialogs.click_enable_single` / `dialogs.click_disable_single` translation keys ("Click to enable." / "Click to disable."); the existing `dialogs.click_enable` / `dialogs.click_disable` ("...all.") keys are unchanged and still used by the category-level and enable-all/disable-all buttons, where "all" is accurate.
- **The lockables category indicator (dialog) and the "select all" indicator (inventory) now share a third, orange state for a partially-active category**, instead of only showing green/red (dialog) or green/red/gold (inventory). Gold was replaced by the same orange used in the dialog for consistency. Orange is now reserved for counts sitting near the midpoint (a 40-60% band, widened to 30-70% for categories of 5 or fewer materials); other partial states show the normal mint/green color instead of orange for every partial count.
- **`/bp recommended` is split into two independent console subcommands.** `/bp recommended blocks` writes only `blocks.yml` (lockable lists, auto-drop), while `/bp recommended config` writes only `config.yml` (enables `modern_family_blocks`, `use_menus`, and `use_dialogs`, the recommended settings that are not on by default). `/bp recommended all` applies both halves in sequence. Each half applies only once: a `recommended_blocks_applied` flag is stored inside `blocks.yml` and a `recommended_config_applied` flag in `config.yml`; re-running an already-applied half is a no-op that logs `recommended_already_applied` instead of silently overwriting the file again (which previously discarded any manual edits made since). Passing `force` as the third argument (`/bp recommended blocks force` / `/bp recommended config force` / `/bp recommended all force`) bypasses the guard and re-applies that half.
- **Auto Drop to Inventory is now reachable from the Dialog UI**, not just the legacy inventory. `LockablesDialog` gained an Auto Drop button leading to `AutoDropDialog` (per-family status list) and `AutoDropFamilyDialog` (per-material toggles within a family, 9 per page), mirroring `AutoDropInventory`/`AutoDropFamilyInventory`. Per-world lockables selection in the Dialog UI was intentionally left out of this pass (see `docs/ZYZ/FOR_LATER.md`, planned for 1.3.5) since it requires porting a full per-world config screen, not a simple list.
## Paper Dialog System (`use_dialogs: true`)
The dialog system is the suggested interface for Paper 1.21.7+ servers. It uses Minecraft's native dialog API for cleaner, more intuitive menus. The old inventory system continues to work for servers running Spigot, older Paper versions, or anyone who prefers the original layout.
When `use_dialogs: true` is set, the plugin checks for the Paper dialog API at runtime. If unavailable, it falls back to normal inventories and logs a warning.
All dialogs use a pastel color palette, support pagination where needed, track navigation history via `DialogOrigin`, and read translations from `translations_en.yml` and `translations_es.yml`.
The `DialogOrigin` enum tracks which menu opened each dialog. Back buttons return to the correct origin: `NONE` (individual command mode, back closes the dialog), `USER_MENU` (returns to `UserMenuDialog`), `ADMIN_MENU` (returns to `AdminMenuDialog`), and `INFO` (read-only block info mode).
> Corrected during development: the standalone commands `/bp lockables`, `/bp stats`, `/bp info`, and `/bp protdel` were passing `ADMIN_MENU` or `USER_MENU` as their dialog origin even when invoked directly, not from within the admin or user menu. This made their Back button navigate into a menu the player never opened. They now pass `NONE` when invoked as standalone commands, so Back correctly closes the dialog instead of jumping into an unrelated menu. Origin is still passed correctly as `ADMIN_MENU` when the same dialogs are opened from within `AdminMenuDialog`.
### Interaction with `use_menus`
`use_menus` controls consolidated (`/bp user`, `/bp admin`) vs individual subcommand routing when `use_dialogs: false`. When `use_dialogs: true`, all interfaces use dialogs regardless of `use_menus`. When `use_dialogs: false`, behavior is unchanged from previous versions.
### New Dialog Screens
| Dialog | Access | Purpose |
|---|---|---|
| `UserMenuDialog` | `/bp user` | Consolidated user menu (settings, friends, stats, about) |
| `AdminMenuDialog` | `/bp admin` | Consolidated admin menu (lockables, config, reload, update, integrations, stats, debug, info, expiry) |
| `UserSettingsDialog` | `/bp settings` | Toggle auto-lock, hints, notifications |
| `FriendManageDialog` | `/bp friends` | Add/remove friends, public/private toggle. Toggling public/private updates all existing owned blocks. |
| `StatsDialog` | `/bp stats` | Player and server-wide block statistics (2 pages) |
| `InfoDialog` | `/bp info` | Paginated player block list (7 per page), click a player to view their block info |
| `LockablesDialog` | `/bp lockables` | 11 material categories (6 per page), click to open sub-dialog |
| `LockableCategoryDialog` | (sub-dialog) | Individual material toggles within a category (9 per page) |
| `AutoDropDialog` | Lockables Dialog > Auto Drop | Per-family auto-drop-to-inventory status list |
| `AutoDropFamilyDialog` | (sub-dialog) | Individual material auto-drop toggles within a family (9 per page) |
| `UnlockDialog` | `/bp unlock <player>` | Paginated block list for admin unlock (6 per page), includes cache invalidation after unlock. No-argument opens player list. |
| `ProtdelDialog` | `/bp protdel` | World selector, batched deletion (20 blocks/tick), undo with timestamps and per-player history |
| `AboutDialog` | `/bp about` | Plugin version, maintainer, issue tracker |
| `UpdateDialog` | `/bp update` | Cached version check with Check Now button. Results refresh the dialog instead of sending to chat. |
| `IntegrationsDialog` | `/bp integrations` | List of plugin integrations with enabled status |
| `AdminConfigDialog` | Admin Menu > Config | In-game config.yml editor (see below) |
## Recommended Configuration: The 1.3.4 Peak Experience
For the best user experience, enable **both** `use_menus` and `use_dialogs` in `config.yml`:
```yaml
# config.yml
use_menus: true
use_dialogs: true
```
This unlocks the full 1.3.4 experience:
- **`/bp user`** opens the consolidated `UserMenuDialog`: settings, friends, stats, and about all in one place.
- **`/bp admin`** opens the consolidated `AdminMenuDialog`: lockables, config editor, reload, update checker, integrations, stats, debug, info, and world protection management.
- Individual subcommands (`/bp settings`, `/bp friends`, `/bp lockables`, etc.) are hidden from tab-complete but still accessible if typed directly.
- The `AdminConfigDialog` mirrors every section of `config.yml` for in-game editing: no more file edits on the server.
- Everything uses Minecraft's native dialog windows: cleaner menus, no chest inventories, no anvil prompts, no chat-based input.
When `use_dialogs: true`, the plugin checks for Paper's dialog API at runtime. If unavailable (Spigot or Paper < 1.21.7):
- A warning is logged with the translation key `CONSOLE__DIALOGS_UNAVAILABLE`
- `use_dialogs` is **automatically set to `false`** in `config.yml` and saved to disk
- The plugin falls back to legacy inventories: no crash, no data loss
- On the next reload or restart, the check runs again (so if the server is later upgraded to Paper 1.21.7+, the admin can re-enable dialogs manually)
> If your server runs **Paper 1.21.7+**, this configuration is strongly recommended. Servers on Spigot or older Paper versions should leave `use_dialogs: false` (the auto-disable handles it) and may optionally use `use_menus: true` for the consolidated inventory GUI.
## AdminConfigDialog
A master config editor accessible from Admin Menu > Config. It mirrors `config.yml` section by section in the same order.
Categories and settings:
- **Language**: `replace_translations`, `fallback_string`, plus two sub-menus: "Enable or Disable Languages" (toggle individual languages in `lang.yml`) and "Select Active Language" (choose the active `language_file`)
- **Worlds**: `per_worlds_config`
- **Players and friends**: `lock_on_place_by_default`, `public_is_friend_by_default`, `player_max_locked_block_count`, `lock_hint_cooldown_in_seconds`, `friend_search_similarity`, `disable_friend_functionality`
- **Blocks and locking behavior**: `modern_family_blocks`, `redstone_disallowed_by_default`, `simplified_hopper_logic`, `protect_locked_blocks_from_explosions`, `block_protected_block_piston_movement`, `clear_protection_on_shulker_break`, `allow_break_protected_blocks`, `respect_spawn_protection`, `block_lock_effects`, `block_lock_sounds`, `use_menus [Dialog]`, `use_dialogs [Dialog]`, `timed_access_max_duration_days`
- **Entity protection**: `entity_protection.enabled`, `entity_protection.auto_protect_on_tame`, `villager_workstation_protection.enabled`
- **Expiry**: `world_expiry.enabled`, `world_expiry.check_interval_minutes`
- **Raid detection**: `raid_detection.enabled`
- **Notifications**: `notify_op_of_updates`, `owner_notifications.enabled`
- **Maintenance**: `auto_reload_configs`, `auto_reload_delay_seconds` (0-5 s, 0 = next tick), `enable_session_log`, `enable_backups`
Boolean settings toggle on click. Settings that only apply in dialog mode (`use_menus`, `use_dialogs`) are tagged `[Dialog]` with a tooltip marker and use `_de` suffix in translation keys (e.g., `BLOCKS__USE_DIALOGS_DE`).
### AdminConfigValueDialog - Native Text Input
Five numeric settings (`player_max_locked_block_count`, `lock_hint_cooldown_in_seconds`, `friend_search_similarity`, `timed_access_max_duration_days`, `world_expiry.check_interval_minutes`) no longer close the dialog and open a SignInput or AnvilInput inventory. They use Paper's native `TextDialogInput` field inside the dialog itself. The value is submitted with the same click that confirms it - no dialog close or reopen. Parse errors show an in-dialog error message instead of closing the screen.
When the dialog API is unavailable (Spigot or Paper < 1.21.7), the editor falls back to SignInput or AnvilInput automatically.
#### Set Block Name Uses Dialog Text Input
Block name editing (`INVENTORIES__SET_BLOCK_NAME`) from the block lock dialog now also uses the native dialog text input via `AdminConfigValueDialog.openText()`, instead of closing the dialog and opening an AnvilInput inventory. The block name is entered in-place inside the same dialog, with a "Confirm" button to save it.
#### Dialog Text Input Save Button
Every `DialogTextField` now has a separate confirm button label (`confirmLabel`), decoupled from the input field label. The `AdminConfigValueDialog` passes "Confirm" (`DIALOGS__ADMIN_CONFIG__CONFIRM_VALUE`) as the button text, so the save action is clearly labeled instead of reusing the config key name as the button text.
## LockableCategoryDialog
The `LockablesDialog` previously toggled every material in a category at once, causing inconsistent results (some activating while others deactivated). Now each category opens `LockableCategoryDialog`, a sub-dialog showing individual materials (9 per page). Each material has its own on/off toggle. No more bulk toggling. Each material row now also shows its real item icon next to the toggle.
The "Enable All" button at the top of each category uses compact family-expression notation (e.g. `[*-SIGN]`) to activate every member of that sub-family in a single line. Individual toggles write specific material names within the same expression format. Both forms are valid family expressions and compress automatically when the full sub-family is active.
## Bed Lockability
Beds can now be added to `lockable_blocks` (including via the `[*-BED]` family expression used elsewhere in this document). A bed occupies two blocks (head and foot); locking, unlocking, or breaking either half now applies to both halves as a single unit, the same way double chests are already handled. Breaking one half while the other is in an unloaded chunk is safely skipped rather than throwing.
## Dialog Cursor Behavior Fix
Every dialog now sets `afterAction: none`, so clicking a button no longer forces Minecraft to close and regenerate the dialog screen behind the scenes. Buttons that navigate to another dialog, or that only need to close the current one, now close the dialog explicitly instead of relying on the client's default post-click behavior. This avoids the client recentering the mouse cursor on every click, which previously happened because each click was treated as a brand new screen being opened.
On a Paper 1.21.8+ server, closing a dialog uses the dedicated dialog-close API. On a server running exactly Paper 1.21.7, that API method is not yet present, so the plugin falls back to closing the player's open screen through the older, general-purpose method instead. Both paths produce the same result for the player; the fallback only matters on that one specific Paper version.
## Commands Updated for Dialog Mode
| Command | Behavior with dialogs enabled |
|---|---|
| `/bp stats` | Opens `StatsDialog` |
| `/bp info` | Opens `InfoDialog` (player list). Click a player to view block info in read-only mode. |
| `/bp lockables` | Opens `LockablesDialog` |
| `/bp unlock` | Opens `UnlockDialog` with player list when no argument given |
| `/bp unlock <player>` | Opens `UnlockDialog` for the specified player |
| `/bp about` | Opens `AboutDialog` |
| `/bp update` | Opens `UpdateDialog`. Check Now refreshes the dialog with results. |
| `/bp integrations` | Opens `IntegrationsDialog` |
| `/bp settings` | Opens `UserSettingsDialog` |
| `/bp friends` | Opens `FriendManageDialog` |
| `/bp user` | Opens `UserMenuDialog` |
| `/bp admin` | Opens `AdminMenuDialog` |
## DefaultConfig API Additions
20+ public setter methods for runtime config modification, added to `DefaultConfig`:
- `getBukkitConfig()`: direct access to the underlying `FileConfiguration`
- `setAndSave(key, value)`: set any config value and save to disk
- Individual setters: `setLockOnPlaceByDefault`, `setPublicIsFriendByDefault`, `setSimplifiedHopperLogic`, `setProtectFromExplosions`, `setBlockPistonMovement`, `setClearProtectionOnShulkerBreak`, `setAllowBreakProtectedBlocks`, `setRespectSpawnProtection`, `setLockEffects`, `setLockSounds`, `setWorldExpiryEnabled`, `setEntityProtectionEnabled`, `setNotifyOpOfUpdates`, `setSessionLogEnabled`, `setBackupsEnabled`, `setAutoReloadConfigs`, `setAutoReloadDelaySeconds` (clamped 0-5), `setRedstoneDisallowedByDefault`, `setLanguageFile`, `setPlayerMaxLockedBlockCount`, `setLockHintCooldown`, `setFriendSearchSimilarity`
## Configuration Reload Transactions (`auto_reload_delay_seconds`)
Previously, the plugin reloaded configuration files as soon as the file-watcher detected any write. This caused double-reloads when external editors wrote files in multiple chunks and made it impossible to coordinate multiple related changes into a single reload.
Starting in 1.3.4, a **quiet-period transaction** system wraps every reload trigger:
- `auto_reload_delay_seconds` (default `2`, range `0-5`) sets the quiet period. `0` means reload on the **next server tick** (effectively immediate but never mid-write); `2` batches an editor's double-write or several files edited back to back into a single reload without feeling laggy.
- On each file-change event a generation counter is incremented and a scheduled task is posted. When the task fires it compares the current generation to its own; if another write happened in between, the old task self-cancels and only the latest fires.
- Writes **from the plugin itself** (config saves from the dialog editor) inject a write token keyed by the exact file path. The watcher consumes and discards any event whose path matches a held token, preventing self-triggered reloads.
- In **manual mode** (`auto_reload_configs: false`), external YAML edits and dialog changes are still written to disk immediately, but the automatic reload does not fire. The change takes effect on the next `/bp reload`, the next click of the Reload button in the Admin Menu, or the next server restart.
> Corrected during development: the language-file completion-percentage writer (`updateLangCompletionPercentages()`) rewrote `lang/lang.yml` on every reload without checking whether anything had actually changed, and without registering a write token first. Combined with a path-matching bug in the file watcher for files under `lang/`, this created a self-sustaining reload loop: each automatic reload rewrote `lang.yml`, which the watcher saw as an external change, which triggered another reload. The writer now skips the write entirely when content is unchanged, and registers its write token before saving when it does write. The watcher's path matching for the `lang/` subdirectory was also fixed to consistently include the `lang/` prefix. Config toggles made through `AdminConfigDialog` (`DefaultConfig.setAndSave()`) now also register a write token before saving, so an in-game toggle no longer triggers a redundant automatic-reload cycle for a change the plugin itself already applied.
The new key is editable from the Maintenance section of `AdminConfigDialog` using the native text-input field (accepts 0-5).
## Configuration Reload Behavior
Clicking **Reload** in the Admin Menu (gold/`PASTEL_GOLD` colored) runs an immediate reload of `config.yml`, `blocks.yml`, and `lang/lang.yml` and reports success or failure directly in chat. The reload runs as soon as the button is clicked, with no separate review or confirmation step.
`ReloadReport` compares individual leaf config values, not whole config sections, when building a diff for the session log. `YamlConfiguration.getValues(true)` returns both a config section as a whole object and its individual child keys in the same map, and the whole-section object has no value-based equality, so comparing only leaf values keeps `logs/blockprot-*.log` reporting only keys that actually changed on a given reload.
## Activity Logging (`BlockProtLogger` - Mandatory)
`BlockProtLogger` previously logged only when `enable_session_log: true`. As of 1.3.4 the logger is always active. `enable_session_log` now controls only whether the session header is written at startup; the file is always opened and written.
New in this release:
- **Java Logger mirror**: a `java.util.logging.Handler` is attached to the `BlockProt` logger on `onEnable`. Every `Logger.info/warning/severe` call is automatically echoed into the log file with its level prefix. No manual `BlockProtLogger.log()` calls are needed for console output.
- **Reload reports**: `ReloadCoordinator` snapshots all config values before and after every reload and appends a structured diff:
```
[RELOAD] Triggered by: DIALOG_CONFIRM | Player: Steve
[RELOAD] auto_reload_delay_seconds: 3 -> 0
[RELOAD] block_lock_effects: true -> false
[RELOAD] 2 key(s) changed.
```
- **Re-entrancy guard**: the mirror handler sets a boolean flag before logging to prevent infinite loops if the logger itself emits a warning.
## Adaptive Particle Geometry (`EffectGeometry`)
Previous versions placed `block_lock_effects` particles at four fixed corners of a 1x1x1 cube regardless of the actual block shape.
`EffectGeometry` (new in 1.3.4) computes the real bounding box for any block and samples particle positions uniformly around its perimeter:
| Block type | Geometry used |
|---|---|
| Single block | `Block.getBoundingBox()`: exact block-model bounds |
| Bed | Union of head + foot block bounding boxes: one continuous rectangle |
| Double chest | Union of left + right chest bounding boxes: one wide rectangle |
Particles are placed at evenly-spaced points along the perimeter edges of the union bounding box, so beds and double chests show a proportionally wider ring. The sound effect plays once at the geometric center of the union.
`LockEffectListener` was updated to call `EffectGeometry.perimeterPoints()` and `EffectGeometry.center()`.
## Language Config (`lang/lang.yml`)
New config file `lang/lang.yml` under the `lang/` directory controls:
- **Fallback language**: when a translation key is missing from the active language file, the plugin looks for it in the configured fallback before falling back to the raw key name. Default: `translations_en.yml`.
- **Language enable/disable**: each of the 15 registered languages has a true/false flag. Disabled languages are not parsed at startup, reducing YAML warnings. The active language from `config.yml`'s `language_file` is always loaded regardless of its enabled flag.
- **Completion percentages**: on every reload, the plugin computes each language file's translation completion percentage and writes it as an inline comment in `lang/lang.yml`.
## GitLocalize Integration
Translations are now managed through [GitLocalize](https://gitlocalize.com/repo/10833). The project page tracks completion percentages per language and accepts community contributions through a split-view editor. The `.gitlocalize.yml` config points at `translations_en.yml` as source and all 20 translation files (19 targets plus the en source, including the staged hu/nl/th/fi/id templates) as synchronize sources.
The badge showing overall translation progress is displayed in the README:
[](https://gitlocalize.com/repo/10833)
## In-Game Language Selector
The admin config dialog's Language section (`/bp admin > Config > Language`) is now split into two sub-menus:
- **Enable or Disable Languages**: Toggle which languages are loaded on startup via `lang/lang.yml`. Each language has its own enable/disable toggle, plus a global "Enable All" / "Disable All" button. To prevent accidental breakage, clicking a disabled language only enables it without setting it as the active language.
- **Select Active Language**: Choose which language file to use as the active server language. Each language shows its display name, completion percentage (e.g. `English (100%)`, `Español (96%)`, `Čeština (42%)`), and whether it is currently the active language. Click any enabled language to set it as active.
Settings that remain in the main Language category: `replace_translations` (auto-fill missing keys) and `fallback_string` (text shown for missing keys).
## Translation Completion Tracking
`Translator.computeCompletionPercentage()` calculates each file's completion against the full 738-key `TranslationKey` enum. Values are recalculated on server startup, `/bp reload`, admin menu reload, and automatic config file watcher reload.
## Translation Changes
### TranslationKey.java
- 110+ new keys for dialog UI strings, organized by section
- Dialog-only settings use `_de` suffix
- New section keys follow config.yml structure: `LANGUAGE__LANGUAGE_FILE`, `PLAYERS__LOCK_ON_PLACE`, `BLOCKS__USE_DIALOGS_DE`, etc.
- `INVENTORIES__ENTITY__INSPECT_CONTENTS` renamed to `INVENTORIES__ENTITY__INSPECT_ENTITY` to fix duplicate key YAML warning.
- 25 new `ICON__*` keys for dialog icons (emoji/indicators), replacing hardcoded characters. All dialog icons now read from translation files.
### translations_en.yml and translations_es.yml
- New `icon:` section with all dialog icon/emoji keys
- New `dialogs:` section with all dialog UI strings
- New `admin_config:` subsection mirroring config.yml categories
- Both files updated together. Spanish translations are natural, not literal.
- YAML indentation fixed for empty `entity:` key and misindented `transfer_not_available`.
### Other language files
- 13 non-EN/ES language files are now skipped at startup by default (configurable via `lang/lang.yml`), eliminating all YAML parse warnings from them.
## BlockProtLogger: Automatic Log File Recovery
The plugin log file (`logs/blockprot-<timestamp>.log`) now detects if the file is deleted or its content is cleared while the server is running. If either happens, `BlockProtLogger` closes the current file and creates a new one with an incrementing suffix (e.g. `blockprot-2026-07-15_15-39-00_2.log`), then continues writing. This prevents log data loss when cleaning or rotating logs on a live server.
All color codes (`§7`, `§x§D§2§B§4§8§C`, etc.) are stripped from the log file output, leaving clean plain text.
The startup ASCII banner now prints in a pastel coffee tone instead of pastel cyan, with a blank line before the banner and after the boot checklist to separate it from surrounding console output.
## Admin Command Visibility Fix
When `use_menus: true`, the `/bp lockables` and `/bp recommended` commands are no longer directly executable or visible in tab-complete for players. They are only accessible through the `/bp admin` GUI. Tab-complete now only shows `user` and `admin` in menu mode. (`/bp recommended` remains console-only regardless of `use_menus`, since `canUseCommand` only permits the console sender.)
When `use_menus: false` (CLI mode), admin commands remain fully accessible.
> Corrected during development: `about`, `help`, `info`, `reload`, `debug`, and `update` were still directly executable and visible in tab-complete even with `use_menus: true`, bypassing the menu-only restriction described above. They now follow the same rule as every other individual subcommand: blocked with a usage hint and hidden from tab-complete, only reachable through `/bp admin` or `/bp user` while menus are enabled.
## Language File Cleanup
Disabled language files (set to `false` in `lang/lang.yml`) are now deleted from the `lang/` folder on reload. The completion percentage computation (`updateLangCompletionPercentages()`) only processes enabled languages plus the active language, instead of all registered files.
## Dialog Diagnostic Logging and Auto-Disable
The plugin now detects incompatible servers and reacts automatically:
- **On config reload** (`reloadConfigAndTranslations`): if `use_dialogs: true` but `VersionCompat.hasDialogApi()` returns false (Paper < 1.21.7 or Spigot), the plugin logs the `CONSOLE__DIALOGS_UNAVAILABLE` warning to both console and the log file, then calls `defaultConfig.setAndSave("use_dialogs", false)` to persist the auto-disable.
- **On first dialog attempt** (`DialogBridgeFactory.getBridge`): if the bridge is still null because the API check failed, the factory logs a one-time warning suggesting the admin set `use_dialogs: false` manually.
- **On reflection failure**: if the `PaperDialogBridge` class exists but fails to instantiate, the error message is logged at `SEVERE` level.
## Completion Percentage Format
Translation completion percentages in `lang/lang.yml` are now stored as YAML comments (`# K: 0%` instead of `K: 0%`), eliminating `duplicate keys found: K` warnings from the YAML parser.
## Config.yml Cleanup
`config.yml` had a small cleanup pass rather than a full reorganization: the deprecated `worldedit_paste_autolock` block (already superseded by `integrations.yml` in an earlier release) was removed along with its `DefaultConfig` getters, the unused `localized_command_aliases` key was removed, and the new `use_dialogs` key was added next to `use_menus` with inline documentation. Net effect is a slightly shorter file, not a longer one.
## Build & Compatibility
- `spigot/build.gradle.kts` updated for the Paper dialog API dependency (root `build.gradle.kts` was not changed in this release).
- Gradle wrapper updated from 9.6.0 to 9.6.1 (build tooling only, no runtime impact).
- `gradle.properties` version set to `1.3.4` with a blank `versionSuffix`, shipping as a normal (non-beta) release on distribution platforms like Modrinth and CurseForge.
- `.github/workflows/publish.yml`: artifact upload and publishing jobs removed from CI.
- `.github/ISSUE_TEMPLATE/feature_suggestion.yml` and `question.yml` updated with an optional Discord-username field, an additional-context field, and the assignee changed from `spnda` to `VictorGugug`.
- README.md updated.
## Bug Fixes
- `EntityFriendManageInventory` no longer shows "Friend cannot be removed" when the typed player name was not found. It now correctly shows "Player not found."
- `EntityFriendManageDialog` and `FriendManageDialog` now use the same corrected "Player not found" translation key instead of the wrong "Friend cannot be removed" message.
- `stripColor()` regex fixed to match uppercase hex color codes (`[§&][0-9a-fk-orxA-F]`), fixing color stripping in dialog formatting.
- Hardcoded English strings in `DebugDialog`, `AdminConfigDialog`, and `UpdateDialog` replaced with translation keys.
- `RedstoneSettingsInventory` updated to fix interaction behavior.
- `EntityInspectContentsInventory` and `WorldLockableSelectionInventory` localized string fixes.
- `BlockLockInventory`: `INVENTORIES__ENTITY__INSPECT_CONTENTS` translation key renamed to `INVENTORIES__ENTITY__INSPECT_ENTITY` to fix a duplicate-key YAML warning; back button now returns to the correct menu origin instead of always closing, and the close button reads "Close" instead of "Back" when there's no origin to return to.
- Lockables no longer bulk-toggle on category click: each material has its own toggle in `LockableCategoryDialog`.
- `DefaultConfig.isKeyInExpressionFormat()` reversed from prior behavior: it no longer short-circuits to flat format when `modern_family_blocks: false`. It now checks each key's actual on-disk format per-key, preserving expression format when the key already uses one. This fixes individual material toggles in `LockableCategoryDialog` writing verbose flat material names when the same category already uses compact family expressions like `[*-SIGN]`. A new `convertBlocksFileFormat()` sweep re-writes every key to match `modern_family_blocks` right after the flag is flipped.
- `HybridDatabase`: log message for `getBlockIndexByWorld` failures no longer double-prefixes `[BlockProt]` (Bukkit's logger already adds it).
- `UpdateChecker`: new constructor overload accepts an `onComplete` callback, used by `UpdateDialog`'s Check Now button to refresh the dialog in place instead of sending results to chat.
- `BlockLockDialog`: "Set Block Name" no longer closes the dialog and opens an anvil inventory. It now uses the native dialog text input with a "Confirm" save button, matching the pattern used by `AdminConfigValueDialog`.
- `AdminConfigDialog`: Language section split into two sub-menus (language toggle and language selector), separating enable/disable from active-language selection to make the interface clearer.
- `DialogTextField`: new `confirmLabel` field separates the text input label from the confirm button text, so the save button reads "Confirm" instead of the config key name.
- `PaperDialogBridge.showValueInput`: confirm button now uses `field.confirmLabel()` instead of `field.label()`.
- `AboutDialog`: hardcoded English labels for database engine, cache, and integrations replaced with translation keys (`DIALOGS__ABOUT__DB_ENGINE_LABEL`, `DIALOGS__ABOUT__DB_MYSQL`, `DIALOGS__ABOUT__DB_SQLITE`, `DIALOGS__ABOUT__CACHE_LABEL`, `DIALOGS__ABOUT__CACHE_SUFFIX`, `DIALOGS__ABOUT__INTEGRATIONS_LABEL`, `DIALOGS__ABOUT__INTEGRATIONS_DISABLED`, `DIALOGS__ABOUT__INTEGRATIONS_ACTIVE`).
- `EntityEventListener`, `BlockEventListener` (including block burn, anvil physics, and sign-change handling), `ExplodeEventListener`, `HopperEventListener`, `InventoryEventListener` (container open/close and access checks), `PistonEventListener` (push and retract), `RedstoneEventListener`, `RaidDetectionListener`: updated lockable checks to use per-world overloads, fixing `RuntimeException: Given block X is not a lockable block/tile entity` (such as `BEE_NEST`) under `per_worlds_config: true`.
- `/bp recommended blocks|config|all`: fixed auto-reload trigger after applying configuration, now scheduling a quiet-period reload via `ConfigFileWatcher.requestProgrammaticReload()` that respects `auto_reload_delay_seconds` when `auto_reload_configs: true` is active.
> Note: owner-name-from-UUID resolution, integration double-registration handling, and localized strings in `AnvilInput`/`BlockInfoInventory`/`EntityInfoInventory`/`PlayerListInventory`/`InventoryEventListener`/`BlockInspectContentsInventory` were previously listed here but are not present in the 1.3.4 commit range (`84f2bed`..`main`): those files are unchanged since 1.3.3 and the claims have been removed.
## Command Permissions, Lock Limits, and Configuration Fixes
The following fixes ship with 1.3.4.
### Command visibility and permission gating
- The player-facing subcommands `/bp settings`, `/bp statistics`, `/bp transfer`, `/bp friends addall`, and `/bp hints` now require the `blockprot.user` permission node. Without it they are hidden from tab-complete and rejected with the permission message instead of executing. `/bp about` and `/bp help` are always available from the console and otherwise also require `blockprot.user`.
- `HelpCommand` no longer lists admin, op-only, or debug-only entries to players who lack those permissions.
- Tab-complete now checks permissions for sub-arguments as well as the first command level: completing e.g. `/bp unlock <player>` no longer leaks player names to users who cannot run the command.
- `AdminUnlockCommand` gained the same permission gate as every other admin command, and the duplicate condition that made the friends entry unreachable in `/bp user` was removed.
### Lock-limit enforcement
- The manual lock buttons (lock menu and lock dialog) previously bypassed the configured lock limit, spawn protection, and lock events. Both now go through the regular lock path, and a failed lock shows the actual reason (e.g. "you have reached your maximum number of protected blocks") in the action bar.
### Configuration fixes
- `worldedit.enabled` (integrations.yml) is now honored: the WorldEdit paste auto-lock feature previously ignored the master toggle and only checked `worldedit.paste_autolock.enabled`.
- `fallback_string` (config.yml) is now used: translation keys missing in both English and the active language previously displayed the raw key name, and now display this string instead.
- The dead `blockprot.max_blocks` permission node was replaced by `blockprot.lockmax`, with dynamic `blockprot.locklimit.<N>` nodes.
- A config file missing the `redstone_disallowed_by_default` key no longer silently disables redstone interactions; it now defaults to allowing them.
- `blocks.yml` header comment corrected: the file can be rewritten for structural merges, format conversion, and repair.
### Documentation
- The player and admin guides were updated to match the current behavior: corrected the audit log database path, the lock limit permission keys (`lockmax`/`locklimit.<N>`), the Knowledge Book material, the shulker box admin exception, the villager workstation targeting rules, the timed-access note, and the `/bp transferall <player>` description. The plugin description for Modrinth and Hangar was cleaned up to remove claims that no longer apply.
## Credits
- **TankObliterator**: proposed the Paper dialog system ([Issue #1](https://github.com/VictorGugug/BlockProt-Reloaded/issues/1)). His idea of replacing inventory/anvil/chat interactions with Minecraft's native dialog API became the central feature of this release.
## Language Maintenance Policy
Only **English** (`translations_en.yml`) and **Spanish** (`translations_es.yml`) are actively maintained by the author. The other 18 bundled language files (13 community-contributed languages `cs`, `de`, `fr`, `it`, `ja`, `ko`, `pl`, `pt-br`, `ru`, `sk`, `tr`, `zh-cn`, `zh-tw`, plus 5 empty templates `hu`, `nl`, `th`, `fi`, `id`) are **not** modified by the author between releases. Missing keys fall back to English automatically.
## Known Issues
- Dialog system requires Paper 1.21.7+. Falls back to legacy inventories on Spigot or older Paper.
- `use_dialogs` and `use_menus` interaction: when `use_dialogs: true`, all interfaces use dialogs regardless of `use_menus`. When `use_dialogs: false`, behavior is unchanged from prior versions.
- `ReloadCoordinator.executeReload` captures the "before" snapshot from the plugin's live in-memory config for `AUTOMATIC`/`EXTERNAL_FILE` sources instead of re-reading disk, since by that point the external edit has already landed on disk for both reads.
- When `auto_reload_configs: false`, an external file edit or dialog change is written to disk but not applied automatically; it takes effect on the next manual reload or server restart. No in-chat preview of the pending change is shown in this mode.
## Language File Maintenance
Cleaned up stale language files and added five new bundled language templates:
- Removed 43 orphaned keys from the 13 stale translation files (cs, de, fr, it, ja, ko, pl, pt-br, ru, sk, tr, zh-CN, zh-TW). These referenced removed features (pets, land claims, wand system, webhook dispatcher).
- Hungarian (translations_hu.yml), Dutch (translations_nl.yml), Thai (translations_th.yml), Finnish (translations_fi.yml), and Indonesian (translations_id.yml) added as bundled language templates, sourced from community draft templates. They ship in the JAR and are listed on GitLocalize, but are not yet registered in `Translator.DEFAULT_TRANSLATION_FILES` or `lang/lang.yml`, so they are not selectable or loadable at runtime yet (staged for 1.3.5). Empty templates; all keys fall back to English.
- All 18 non-EN/ES bundled language files now carry the complete key set of the English reference (880 keys). Newly added keys are blank in community languages and in the templates, and blank values fall back to English; no translation was written for any community language in this pass. The legacy quoted `'True'`/`'False'` keys and the stale `console.recommended_done` key were removed from the 13 community files.
- Spanish (translations_es.yml) brought to full parity with the English reference. 32 missing keys in the admin config section were added with natural Spanish translations.
- Translations now hosted on [GitLocalize](https://gitlocalize.com/repo/10833) for community contribution, including Finnish (fi) and Indonesian (id).
## Files
Verified against `git diff --stat a8c7c867..HEAD` (31 commits, `84f2bed` through `eaa0b36`, the full 1.3.4 development range following the 1.3.3 release commit `a8c7c867`). 145 files touched. Files that were unchanged in this range have been removed from the lists below even where an earlier draft of these notes attributed 1.3.4 work to them.
### New Files
Dialog infrastructure:
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogBridge.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogBridgeFactory.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogBodyEntry.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogOrigin.java`
- `spigot/src/dialogs/java/de/sean/blockprot/bukkit/dialogs/impl/PaperDialogBridge.java`: confirm button now uses `field.confirmLabel()` instead of `field.label()`
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/LangConfig.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/ReloadCoordinator.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/ReloadReport.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/logger/PluginActivityLog.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/listeners/EffectGeometry.java`
Dialog screens:
- `AboutDialog.java`, `AdminConfigDialog.java` (Language section split into two sub-menus), `AdminConfigValueDialog.java` (save button label fix), `AdminMenuDialog.java`, `AuditDialog.java`, `AutoDropDialog.java`, `AutoDropFamilyDialog.java`, `BlockInfoDialog.java`, `BlockLockDialog.java` (set block name uses dialog text input instead of anvil), `BlockSettingsDialog.java`, `DebugDialog.java`, `EntityBlockSettingsDialog.java`, `EntityFriendManageDialog.java`, `EntityInfoDialog.java`, `FriendManageDialog.java`, `InfoDialog.java`, `IntegrationsDialog.java`, `LockableCategoryDialog.java`, `LockablesDialog.java`, `ProtdelDialog.java`, `StatsDialog.java`, `UnlockDialog.java`, `UpdateDialog.java`, `UserMenuDialog.java`, `UserSettingsDialog.java` (all under `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/`)
Dialog utilities:
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogButton.java`
- `spigot/src/main/java/de/sean/blockprot/bukkit/dialogs/DialogTextField.java`: new `confirmLabel` field separates input label from confirm button text
Commands:
- `spigot/src/main/java/de/sean/blockprot/bukkit/commands/DebugCommand.java`
Resources:
- `spigot/src/main/resources/lang/lang.yml`
- `spigot/src/main/resources/lang/translations_hu.yml`: new Hungarian translation template
- `spigot/src/main/resources/lang/translations_nl.yml`: new Dutch translation template
- `spigot/src/main/resources/lang/translations_th.yml`: new Thai translation template
- `spigot/src/main/resources/lang/translations_fi.yml`: new Finnish translation template
- `spigot/src/main/resources/lang/translations_id.yml`: new Indonesian translation template
- `images/RELEASE TITLES/R_N/RELEASE_NOTES_1.3.4.png`
Docs:
- `docs/RELEASE_NOTES/1.3.4.RELEASE_NOTES.md`: this file
- `docs/MODERN SYNTAX AND LEGACY/BLOCK_FAMILY_SYNTAX.md`: removed decorative separators
- `docs/MODERN SYNTAX AND LEGACY/LOCKABLE_BLOCKS_REFERENCE.md`: removed decorative separators, replaced non-ASCII characters
> Removed from this list (pre-existing since 1.3.3 or earlier, confirmed via `git ls-tree a8c7c867`): `ResidenceIntegration.java`, `GriefPreventionIntegration.java`, `ClaimChunkIntegration.java`, `IntegrationConfig.java`, `integrations.yml`.
### Modified Files
Commands:
- `AboutCommand.java`, `AdminMenuCommand.java`, `AdminUnlockCommand.java`
- `BlockProtCommand.java`: admin commands blocked in menu mode; tab-complete hides admin commands when menus enabled
- `RecommendedCommand.java`: split into independent `blocks`/`config`/`all` halves with per-half applied flags and a `force` argument; `AdminUnlockCommand.java`: `canUseCommand` gate
- `FriendsAddAllCommand.java`, `InfoCommand.java`, `IntegrationsCommand.java`, `LockablesCommand.java`, `SettingsCommand.java`, `StatisticsCommand.java`, `UserMenuCommand.java`, `WorldProtDeleteCommand.java`
- `HelpCommand.java`, `HintsCommand.java`, `TransferCommand.java`: gated behind `blockprot.user`; `HelpCommand.java` no longer lists entries the sender lacks permission for
- `ReloadCommand.java`: routed through `ReloadCoordinator`
- `UpdateCommand.java`: uses the new `UpdateChecker` `onComplete` overload
Config and infrastructure:
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/DefaultConfig.java`: 20+ setters; `auto_reload_delay_seconds` getters and setters; `isKeyInExpressionFormat()` per-key format fix; new `convertBlocksFileFormat()` sweep; bed materials recognized as lockable blocks; per-material and per-family auto-drop toggle methods for the new Auto Drop dialogs; `disallowRedstoneOnPlace()` no longer defaults to disallowing redstone when the key is missing from `config.yml`; `blocks.yml` header comment corrected
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/BlockFamilyParser.java`: added a BED sub-family
- `spigot/src/main/java/de/sean/blockprot/bukkit/nbt/BlockNBTHandler.java`: bed halves are treated as a merged unit, the same way double chests already are; lock-limit exemption check uses `Permissions.LOCKMAX.key()` instead of the hardcoded `blockprot.lockmax` string
- `spigot/src/main/java/de/sean/blockprot/bukkit/util/BlockUtil.java`: new `getOtherBedHalf()` helper
- `spigot/src/main/java/de/sean/blockprot/bukkit/config/ConfigFileWatcher.java`: refactored to generation-based quiet-period scheduler with route-based suppression; `requestProgrammaticReload()` used directly by `DefaultConfig.setAndSave()` and blocks.yml saves
- `spigot/src/main/java/de/sean/blockprot/bukkit/BlockProt.java`: dialog init; lang cleanup; logger init
- `spigot/src/main/java/de/sean/blockprot/bukkit/BlockProtLogger.java`: color code stripping; Java logger mirror Handler; mandatory activity logging
- `spigot/src/main/java/de/sean/blockprot/bukkit/BlockProtConsole.java`: pastel color palette applied to the startup banner and boot checklist (coffee-tone banner, active/inactive status dots); blank lines added before the banner and after the boot checklist; boot lines now route through `BlockProtLogger`
- `spigot/src/main/java/de/sean/blockprot/bukkit/Permissions.java`: `blockprot.max_blocks` renamed to `blockprot.lockmax` (kept as a deprecated alias); new `blockprot.locklimit.<N>` dynamic node documented
- `spigot/src/main/java/de/sean/blockprot/bukkit/VersionCompat.java`: dialog API version check (`hasDialogApi()`)
- `spigot/src/main/java/de/sean/blockprot/bukkit/TranslationKey.java`: new dialog keys; a dedicated `_TITLE` display-name key for every admin config setting, separate from its longer tooltip description; Placements keys; 8 new About dialog keys for database engine, cache, and integrations labels
- `spigot/src/main/java/de/sean/blockprot/bukkit/Translator.java`: completion-percentage computation; missing translation keys now fall back to the configured `fallback_string` instead of the raw key name
- `spigot/src/main/java/de/sean/blockprot/bukkit/nbt/StatHandler.java`: minor fix
- `spigot/src/main/java/de/sean/blockprot/bukkit/nbt/stats/LocationListEntry.java`: block title now includes the world name alongside coordinates
- `spigot/src/main/java/de/sean/blockprot/bukkit/nbt/PlayerSettingsHandler.java`: new per-player `blockprot_prefer_dialogs` preference (`getPreferDialogs()`/`setPreferDialogs()`), defaulting to the server's `use_dialogs` setting
- `spigot/src/main/java/de/sean/blockprot/bukkit/storage/HybridDatabase.java`: removed duplicate `[BlockProt]` log prefix
- `spigot/src/main/java/de/sean/blockprot/bukkit/tasks/BackupTask.java`: javadoc backup path updated to the `plugins/BlockProtReloaded/backups/` folder
- `spigot/src/main/java/de/sean/blockprot/bukkit/tasks/UpdateChecker.java`: new `onComplete` callback overload for `UpdateDialog`
Listeners:
- `InteractEventListener.java`: routes to `BlockLockDialog` when `use_dialogs: true`
- `LockEffectListener.java`: updated to use `EffectGeometry` perimeter particle sampling
- `InventoryEventListener.java`, `BlockEventListener.java`, `PistonEventListener.java`, `RedstoneEventListener.java`, `HopperEventListener.java`: lockable checks now use the per-world-aware overload so they agree with `BlockNBTHandler`, fixing a `RuntimeException` on container open under `per_worlds_config: true`
- `WorldEditPasteListener.java`: now checks `worldedit.enabled` (`integrations.yml`) in addition to `worldedit.paste_autolock.enabled` before auto-locking a paste
- `ItemFrameListener.java`, `VehicleProtectionListener.java`: dialog-mode handling
Inventories:
- `AdminMenuInventory.java`, `UserSettingsInventory.java`: dialog routing
- `UserMenuInventory.java`: dialog routing; Statistics slot renamed to Placements
- `BlockLockInventory.java`: back-button now returns to correct menu origin; `INSPECT_ENTITY` key rename; manual lock button now goes through the regular lock path (limit, spawn protection, lock events), showing the actual reason on failure
- `RedstoneSettingsInventory.java`: interaction fix
- `EntityFriendManageInventory.java`: "Player not found" message fix
- `EntityInspectContentsInventory.java`, `WorldLockableSelectionInventory.java`: localized string fixes
- `WorldLockableDetailInventory.java`: requests a programmatic quiet-period reload via the config file watcher after saving a per-world change to `worlds.yml`
- `LockablesInventory.java`, `AutoDropInventory.java`, `AutoDropFamilyInventory.java`: `NamedTextColor` replaced with the pastel color palette used elsewhere in the plugin
Dialogs:
- `AdminConfigDialog.java`: added Reload configuration button, `auto_reload_delay_seconds` setting; buttons now show a short display name with the description and raw config key moved into the tooltip
- `AdminMenuDialog.java`: Reload button runs an immediate reload and reports success or failure in chat
- `AboutDialog.java`: hardcoded English labels replaced with translation keys (db engine, cache, integrations); pastel color theme applied
- `BlockLockDialog.java`: pastel color theme applied; lock button now goes through the regular lock path (limit, spawn protection, lock events), showing the actual reason on failure
- `AuditDialog.java`, `BlockInfoDialog.java`, `BlockSettingsDialog.java`, `DebugDialog.java`, `EntityBlockSettingsDialog.java`, `EntityFriendManageDialog.java`, `EntityInfoDialog.java`, `FriendManageDialog.java`, `InfoDialog.java`, `IntegrationsDialog.java`, `LockableCategoryDialog.java`, `LockablesDialog.java`, `ProtdelDialog.java`, `UnlockDialog.java`, `UpdateDialog.java`, `UserSettingsDialog.java`: pastel color theme applied to all dialog screens
- `AdminConfigValueDialog.java`: pastel color theme applied; dialog title and input field label now use the short display name instead of the raw config key
- `StatsDialog.java`: pastel color theme applied; added `showUserStats()` for the Placements screen (limit display, no global toggle, click a block to edit it directly)
- `UserMenuDialog.java`: pastel color theme applied; Statistics button renamed to Placements, routed to `showUserStats()`
- `DialogBridge.java`, `DialogBridgeFactory.java`, `DialogBodyEntry.java`, `DialogOrigin.java`, `DialogButton.java`, `DialogTextField.java`: dialog infrastructure and utilities
- `spigot/src/dialogs/java/de/sean/blockprot/bukkit/dialogs/impl/PaperDialogBridge.java`: pastel color theme applied
Resources:
- 13 stale `translations_*.yml` files: orphaned keys removed (43 keys referencing removed features); later completed to the full English reference key set (64 dialog and admin-config keys added per file, blank until community-translated); the legacy quoted `'True'`/`'False'` icon keys and the stale `console.recommended_done` key removed
- `translations_en.yml`, `translations_es.yml`: auto reload delay and pending reload review keys added; short `_TITLE` display-name strings for admin config buttons; Placements strings
- `translations_hu.yml`, `translations_nl.yml`, `translations_th.yml`, `translations_fi.yml`, `translations_id.yml`: bundled language templates, regenerated in the English reference key order
- `spigot/src/main/resources/config.yml`: added `auto_reload_delay_seconds` under Maintenance; cleanup
- `spigot/src/main/resources/blocks.yml`: header comment updated for the `/bp recommended blocks` split; `auto_drop_to_inventory.blocks` now ships with two blank template lines like every other lockable list instead of `blocks: []`
- `spigot/src/main/resources/worlds.yml`: header comment punctuation cleanup
- `spigot/src/main/resources/plugin.yml`: dialog API dependency; `blockprot.max_blocks` permission renamed to `blockprot.lockmax`, new dynamic `blockprot.locklimit.<N>` node added
Build and CI:
- `spigot/build.gradle.kts`: Paper dialog API dependency
- `gradle.properties`: version set to 1.3.4 with a blank `versionSuffix` (normal, non-beta release)
- `.github/workflows/publish.yml`: artifact upload/publishing jobs removed
- `.github/PLATFORM_DESCRIPTION.md`: session log path updated to the `plugins/BlockProtReloaded/logs/` folder
- `.gitignore`, `README.md`, `.gitlocalize.yml`: README language lists updated for the 20 bundled files (fi and id added to the GitLocalize languages); `.gitlocalize.yml` synchronize sources extended to `translations_fi.yml` and `translations_id.yml`
Docs:
- `docs/RELEASE_NOTES/1.3.3.RELEASE_NOTES.md`: "Coming next" section updated to point at these notes
- `docs/MODERN SYNTAX AND LEGACY/BLOCK_FAMILY_SYNTAX.md`: decorative separator and punctuation cleanup
- `docs/MODERN SYNTAX AND LEGACY/LOCKABLE_BLOCKS_REFERENCE.md`: decorative separator and punctuation cleanup
- `docs/MODERN SYNTAX AND LEGACY/LEGACY_BLOCKS_SYNTAX.md`: updated for the `/bp recommended blocks` split and added links to the admin/player guides
- `docs/READ_MEs/MODR_HANG_README.md`: Modrinth/Hangar plugin description cleaned up to remove claims that no longer apply; language row updated to the 20 GitLocalize languages
> Language file maintenance pass: the 13 community translation files now carry the complete English reference key set (64 dialog and admin-config keys added per file, blank until community-translated), and the five template files were regenerated in the English reference key order. Verified against the working-tree `git diff` (changes uncommitted at the time of writing) plus a programmatic key-parity check against `translations_en.yml` on every bundled file (880 keys each, no missing, no orphan, no duplicate) and YAML parsing validation.
> Removed from this list (pre-existing since 1.3.3 or earlier, unchanged in this commit range): IntegrationConfig.java, BlockProtAPI.java, SkinCache.java, BlockProtInventory.java, BlockInfoInventory.java, AnvilInput.java, EntityInfoInventory.java, PlayerListInventory.java, BlockInspectContentsInventory.java, PluginIntegration.java, LandsPluginIntegration.java, WorldGuardIntegration.java, TownyIntegration.java, PlaceholderAPIIntegration.java, ViaVersionIntegration.java, integrations.yml, root build.gradle.kts, .github/ISSUE_TEMPLATE/bug_report.yml.
>
> Corrected: BlockNBTHandler.java, HopperEventListener.java, PistonEventListener.java, InventoryEventListener.java, WorldEditPasteListener.java, BlockProtConsole.java, and HelpCommand.java were previously listed above as unchanged. All seven were actually modified within the a8c7c867..HEAD range and are listed in their correct sections below.
## Looking Ahead to 1.3.5: Language Snapshots
Starting in **1.3.5**, each new language contributed by the community will be distributed as an **independent snapshot resource** rather than bundled into the plugin JAR. This means:
- Languages can be added, updated, or removed without waiting for a full plugin release.
- Community translators maintain their own language files independent of the release cycle.
- The plugin will load external language files from the `lang/` folder, and any missing keys fall back to the bundled English reference.
- If you want to contribute a new translation or update an existing one, look for the language snapshot releases on the [Releases page](https://github.com/VictorGugug/BlockProt-Reloaded/releases).
This change reduces the plugin JAR size, eliminates YAML warnings from incomplete community translations, and lets the community drive language support at their own pace.
release
BlockProt Reloaded 1.3.3
1.3.39 июл. 2026 г.95Minecraft: 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2, 26.2folia, paper, purpur, spigot
Что нового

This page lists what changed in each release, in the order it shipped. Each entry describes the final, working behavior - not the intermediate steps taken to get there.
## Coming next
### 1.3.4 - dialog system research
A community member proposed replacing the current inventory/anvil/chat interaction system with Minecraft's dialog system ([issue #1](https://github.com/VictorGugug/BlockProt-Reloaded/issues/1)). It would unify every current interaction method into one interface and could add a button to the pause menu. Adopting it means either dropping support for versions below 1.21.6, or maintaining both interaction systems side by side. Research is starting; nothing about this is final yet.
### 1.3.5 - language overhaul
Every bundled language file except English and Spanish is currently outdated to varying degrees, some carrying leftover content from features that no longer exist in this fork. 1.3.5 replaces every one of those files wholesale with the equivalent file from the upstream project, then reconciles it with the strings this fork adds on top (integrations, per-world config, and so on).
Alongside that, a community translation system is planned: a dedicated languages section on the project's Discord (https://discord.gg/RRcjuMr9Jd), where contributors can submit translation updates and corrections for review instead of relying on a single pass to keep every language current.
## 1.3.3 is finally out
After a long development cycle, I'm officially releasing 1.3.3. This is the biggest update this fork has shipped: five new plugin integrations (WorldGuard, Lands, Towny, ClaimChunk, PlaceholderAPI), item frame and storage vehicle protection, villager workstation protection, raid detection, a rebuilt lockables GUI, and a long list of inherited and fork-specific bug fixes. Everything below this point describes what actually shipped.
## 1.3.3
### Breaking changes (0.1% of servers affected)
- **All lockable lists are empty by default.** On a fresh install, `blocks.yml` starts with `[]` for every list, including `lockable_entities`. The admin configures lockable blocks via `/bp lockables` in-game, by editing `blocks.yml` directly, or by running the `/bp recommended` console command to populate a sensible default set. Existing servers upgrading are unaffected: their `blocks.yml` is never overwritten.
- **Bidirectional blocks.yml startup conversion re-added with guard.** The `modern_family_blocks` flag now auto-converts blocks.yml format on `/bp reload` (via `convertBlocksFormatIfNeeded()`), but only when the file format actually mismatches the flag. This conversion preserves all material selections, only the format changes. On the first reload after changing the flag, the file is converted; subsequent reloads are no-ops. Manual edits are preserved (materials are never dropped, only reformatted). The infinite-reload-loop bug is prevented by `suppressNext()` before every save.
- **Config file writes only when dirty.** `cleanLegacyConfigKeys()` and `mergeMissingConfigKeys()` now only write to disk when a change was actually made. This stops the infinite auto-reload loop caused by the plugin overwriting its own config files.
- **File watcher console spam reduced.** The watcher logs one short line to the console ("Configuration change detected; reloading...") and one line to the session log per change. Previously it logged two console lines. World scan messages only print when worlds are actually added or patched.
- **Startup banner with ASCII art.** BlockProt prints an ASCII "BPR" logo on startup in a light coffee color. The plugin name, version line, and boot status lines that follow print uncolored.
- **`/bp recommended` console command.** Generates a sensible default blocks.yml. Console-only. See "First-start console guide" below for how new admins are pointed to it.
- **Per-world lockable GUI.** When `per_worlds_config: true`, the lockables GUI shows a MAP button (slot 48) that opens a world selection inventory. Each world shows its enabled/disabled status and protected block count. Click a world to configure its individual lockable lists.
- **Auto-disable modern_family_blocks.** When all lockable lists become empty via GUI toggling, `modern_family_blocks` auto-sets to `false` in config.yml.
- **Translation keys added:** `worlds.status`, `worlds.protected_count`, `worlds.no_worlds`, `worlds.world_config_hint`, `worlds.per_world_config`, `worlds.worlds`, `worlds.configured`.
## Additions
### Fixed menu layout for all block and entity types
### Auto-drop to inventory configuration GUI
A new GUI to configure `auto_drop_to_inventory.blocks` is accessible from the `/bp lockables` inventory (DROPPER item at slot 46). The page shows each family (Tile Entities, Shulker Boxes, Blocks, Doors, Entities) with a representative icon and its active/inactive/partial status.
- **Right-click** a family toggles all its members at once (enables or disables auto-drop for the entire family).
- **Left-click** opens a paged sub-menu listing every material in that family. Each material can be toggled individually.
- The back button returns to the lockables GUI.
New methods in `DefaultConfig`: `toggleAutoDropMaterial()`, `toggleAutoDropFamily()`, `representativeMaterialForFamily()`. All toggles persist to `blocks.yml` on disk.
### Lockables GUI blocks no longer move on toggle
The active-status sort was removed. Blocks stay in their family section sorted by name only. Toggling a block on or off no longer changes its position in the inventory.
### Fixed crash on non-item materials in auto-drop sub-menu
Materials that cannot be held in an ItemStack (LAVA_CAULDRON, WATER_CAULDRON, POWDER_SNOW_CAULDRON, wall-mounted signs) are resolved to display equivalents before creating ItemStacks. The sub-menu no longer crashes when opening the Blocks family.
The Block Lock menu previously placed its buttons using a counter that incremented for each button actually shown. When a button did not apply to the current block (for example, no Redstone button on a workstation), every button after it shifted one slot to the left. This meant the same menu looked different depending on which block type opened it, and the bottom-row buttons (Inspect, Audit Log, Paste, Copy, Info) ended up in inconsistent slots between block types.
Every button now has one fixed slot, used by every block and entity type. A button that does not apply to the current type simply leaves its slot empty; the other buttons never move.
**Fixed slots, top row:**
| Slot | Item | Shown for |
|---|---|---|
| 0 | Block icon | Always |
| 1 | Redstone | Storage and traversal blocks |
| 2 | Player Head | Always, unless friend functionality is disabled |
| 3 | Name Tag | Always |
| 4 | Ender Pearl | Always |
| 5 | Emerald | Workstation blocks only |
**Fixed slots, bottom row:**
| Slot | Item | Shown for |
|---|---|---|
| 9 | Spyglass | Storage blocks with an inventory, owner or admin |
| 13 | Clock | Owner or admin, audit logger active |
| 14 | Knowledge Book | Manager role, clipboard has data |
| 15 | Paper | Manager role |
| 16 | Compass | Manager role or admin |
| 17 | Barrier | Always |
The entity menu (`fillForEntity`) was fixed the same way: Name Tag stays at slot 0, Redstone and Ender Pearl only appear for storage vehicles (chest boats, storage/hopper minecarts) and always sit at slots 1 and 4, Player Head always sits at slot 2, Spyglass and Clock sit at 9 and 10 for storage vehicles, and Compass sits at 13.
### Entity protection rename
The protection system covering tamed animals (wolves, cats, parrots, horses, llamas) was renamed end-to-end from "pet protection" to "entity protection" across class names, package names, config keys, NBT persistent-data keys, and method names. This is purely a naming and organization change; behavior is identical to the previous pet protection feature.
The `pet_protection` key in `config.yml` is renamed to `entity_protection`. Upgrading servers do not need to edit anything: on first startup after the upgrade, the plugin reads the old key, writes its value under the new name, and removes the old entry automatically. Old NBT data stored under the legacy `pet_owner` / `pet_protected` keys is migrated to the new keys automatically as well.
### Villager workstation protection
A villager whose job-site memory points to a protected workstation block (grindstone, stonecutter, loom, cartography table, smithing table, enchanting table, fletching table, lectern, composter, brewing stand, blast furnace, smoker, barrel, cauldron) inherits that block's protection automatically - no separate configuration is needed per villager.
Protected actions:
- Damage to the villager by non-owners (melee and projectiles)
- Trading interaction by non-owners
- Breaking blocks in a search area around the workstation
- Interacting with blocks in that area (except the workstation block itself)
The search area is configurable independently of whether the feature is enabled:
```yaml
villager_workstation_protection:
enabled: true
radius: 2 # horizontal search radius in blocks, clamped to 0-8
vertical_radius: 1 # vertical search radius in blocks, clamped to 0-4
```
A new Emerald button ("Locate Linked Villager") appears in the lock menu for a protected workstation that has a villager linked to it. Clicking it closes the menu and shows a short particle effect at the villager's location, visible only to the clicking player, for a configurable duration (`entity_protection.villager_locate_seconds`, 1-10 seconds, default 6). If no villager is linked, nothing happens and no error is shown.
### Item frame protection and automatic block linking
`ITEM_FRAME` and `GLOW_ITEM_FRAME` are full members of the `ENTITIES` family under the `ITEM_FRAMES` sub-family. They appear in `/bp lockables` with `Status: INACTIVE` by default (not included in `lockable_entities`) or `ACTIVE` when listed.
A frame mounted on the face of a lockable block is automatically linked to that block at the moment it is placed. A linked frame has no protection state of its own: no owner, no friend list, no lock toggle. Interacting with it opens the underlying block's lock menu directly, and the frame's protection always matches the block's exactly - same owner, same friends, locks and unlocks together. The link is stored bidirectionally (the frame stores the block's coordinates, the block stores the frame's entity UUID) so it survives chunk reloads and server restarts, and is validated on each interaction in case the frame or block changed since linking.
A frame not mounted on a lockable block, or mounted on a block that is not currently lockable, keeps the standalone entity-protection flow: sneak and right-click with an empty hand opens the BlockProt entity menu directly, exactly like 1.3.2.
Supported token: `*-ITEM_FRAMES` to include only frames, or `-*ITEM_FRAMES` to exclude all frames, in a `lockable_entities` family expression.
### Storage vehicle protection completed
Chest boats, storage minecarts, and hopper minecarts use the same sneak-and-right-click flow as item frames. Once protected:
- Right-clicking without sneaking is blocked for non-owners and non-friends.
- Damaging or destroying the vehicle (`VehicleDamageEvent`, `VehicleDestroyEvent`) is blocked for everyone except the owner and admins.
- Hopper-pipeline extraction from the vehicle's inventory is blocked unless the owner has disabled that protection from the in-menu toggle.
- Placing the vehicle auto-locks it to the placing player if their "lock on place" setting is enabled and they are not sneaking, mirroring the behavior already in place for blocks and item frames.
`ChestBoat` is resolved at runtime via reflection so the same code path supports both the 1.20.x class location (`org.bukkit.entity.ChestBoat`) and the 1.21+ location (`org.bukkit.entity.boat.ChestBoat`).
### `EntityInfoInventory` location display
The info panel for a protected entity shows an Oak Sign in slot 1 displaying the entity's type and current world/coordinates, replacing the Compass-based block-info display that does not apply to entities (entities do not have NBT-stored placement coordinates the way blocks do).
### `BlockFamilyParser` cross-family validation and `/bp lockables`
`BlockFamilyParser` parses compact family expressions in `blocks.yml` and `worlds.yml`. Expressions are always parsed regardless of the `modern_family_blocks` flag in `config.yml` - that flag only controls whether flat material lists are auto-converted to expressions on startup.
A `NAME` or `-NAME` token inside an expression is now validated against the family of the config key it appears in. A material that does not belong to that family is rejected with a console warning and discarded, rather than silently producing an incorrect or empty result. For example, `FLETCHING_TABLE` (a `BLOCKS` workstation) inside a `lockable_tile_entities` expression is rejected with a warning, while `COPPER_CHEST` (a valid `CHEST` sub-family member) is accepted.
`/bp lockables` is a new admin command (`blockprot.user.admin`) that opens a six-row paged GUI listing every block and entity the family system knows about, regardless of whether it is currently enabled. Active entries show a green `Status: ACTIVE` label; disabled entries show a red `Status: INACTIVE` label. Left-clicking an entry sends a clickable chat message that copies the material name; right-clicking copies the exclusion token (`-MATERIAL_NAME`). The info book in the GUI shows server version, client version (via ViaVersion, if installed), and active/inactive counts.
Token reference:
| Token | Meaning |
|---|---|
| `*` | All members of the family |
| `*-TAG` | All members of the named sub-family |
| `-*TAG` | Exclude all members of the named sub-family |
| `NAME` | Include one specific material |
| `-NAME` | Exclude one specific material |
Sub-families per config key:
| Key | Sub-families |
|---|---|
| `lockable_tile_entities` | CHEST, FURNACE, SHELF, TRANSPORT, MISC, SIGN |
| `lockable_shulker_boxes` | SHULKERS |
| `lockable_blocks` | ANVIL, CAULDRON, WORKSTATION, TRAPDOOR, FENCE_GATE |
| `lockable_doors` | DOORS |
| `lockable_entities` | CHEST_BOATS, CHEST_MINECARTS, HOPPER_MINECARTS, ITEM_FRAMES |
Full syntax guide and worked examples: [`docs/MODERN SYNTAX AND LEGACY/BLOCK_FAMILY_SYNTAX.md`](../MODERN%20SYNTAX%20AND%20LEGACY/BLOCK_FAMILY_SYNTAX.md). Both the plain flat-list format (one material per line with `-`) and the bracketed expression format are accepted, and can be mixed across different lines of the same list - see the "Two valid formats" section of that document.
### ViaBackwards and ViaRewind detection
`ViaVersionIntegration` now detects ViaBackwards and ViaRewind in addition to ViaVersion, logging the version of each detected companion plugin.
### WorldGuard integration
`WorldGuardIntegration` registers a custom region flag, `allow-blockprot`, defaulting to allow. Setting the flag to deny on a specific region (`/rg flag <region> allow-blockprot deny`) blocks BlockProt protections from being created or accessed inside that region. Everywhere else behaves exactly as if WorldGuard were not installed. The flag is registered during plugin load, before WorldGuard finishes enabling, per WorldGuard's custom-flag registration timing.
Configured from `integrations.yml`:
```yaml
worldguard:
enabled: true
enable_flag_functionality: true
```
Setting `enable_flag_functionality: false` keeps WorldGuard detected (it still shows `Hooked` on the startup banner) without ever checking the flag.
### Lands integration
`LandsPluginIntegration` registers a custom role-flag, "Protect containers (BlockProt)", that land owners assign per role. A player without that flag in the claimed area covering a protected block is denied locking or accessing it. Unclaimed wilderness follows a separate config option instead of the role-flag.
An optional second role-flag, "Require \"Protect containers\" for friends (BlockProt)", lets a land owner require that both the block owner and the friend being added hold the protect-containers flag before that friend can access the block.
Configured from `integrations.yml`:
```yaml
lands:
enabled: true
allow_protecting_containers_in_wilderness: true
require_protect_for_friends_flag: false
```
Both role-flags are registered during plugin load, mirroring WorldGuard's registration timing requirement.
### Towny integration
`TownyIntegration` checks Towny protection on blocks and entities. A player must be a town resident to lock or access protected blocks within that town's claimed area. Ruined towns bypass the resident check entirely (cancelling the lock/access attempt before even checking, rather than allowing it when the resident check fails).
Three bugs fixed in this release:
1. **`onLockOnPlace` resident check was inverted**: a missing `!` caused locking to be denied in every town instead of being denied outside towns.
2. **`shouldBypassProtectionsInRuinedTowns` used `||` instead of `&&`**: the wrong operator meant all players bypassed protection in ruined towns.
3. **`shouldCleanupAfterUnclaim` used `||` instead of `&&`**: protection cleanup ran on every world change instead of only when a town was actually unclaimed.
Configured from `integrations.yml`:
```yaml
towny:
enabled: true
cleanup_plots_after_unclaim: true
restrict_access_to_residents: false
allow_mayor_to_see_block_info: false
bypass_protection_in_ruined_towns: true
```
Additional options: `restrict_access_to_residents` denies lock/access to non-residents even on unlocked blocks; `allow_mayor_to_see_block_info` grants the `/bp info` permission to the town mayor; `cleanup_plots_after_unclaim` removes protections when a plot is cleared or unclaimed; `bypass_protection_in_ruined_towns` allows container access in ruined towns without owning the block.
### ClaimChunk integration
Requested in [issue #298](https://github.com/spnda/BlockProt/issues/298).
`ClaimChunkIntegration` restricts block locking and full access (lock/unlock/edit) to the chunk owner or a trusted member:
- **Locking** (`onLockOnPlace`, `onPreLock`): only the chunk owner can create protections.
- **Full access** (`onPreventFullAccess`): only the chunk owner (or trusted members, if `restrict_access_to_chunk_owner` is false) can unlock or edit settings.
- `isFriend()`: only the chunk owner is accepted as a "natural friend"; there is no per-chunk friend list of its own, so the standard BlockProt friend-management page continues to work normally for owner-to-owner sharing.
Configured from `integrations.yml`:
```yaml
claimchunk:
enabled: true
restrict_access_to_chunk_owner: false
```
Setting `restrict_access_to_chunk_owner: true` restricts full access (lock/unlock/edit) to the chunk owner only, in addition to locking.
### PlaceholderAPI integration
`PlaceholderAPIIntegration` registers a `PlaceholderExpansion` providing BlockProt placeholders for the server's PAPI system. Available placeholders:
| Placeholder | Returns |
|---|---|
| `%blockprot_global_block_count%` | Total protections on the server |
| `%blockprot_own_block_count%` | Number of protections owned by the querying player |
| `%blockprot_default_friends%` | The player's default friend list |
Configured from `integrations.yml`:
```yaml
placeholderapi:
enabled: true
```
### ViaVersion integration
`ViaVersionIntegration` detects ViaVersion, ViaBackwards, and ViaRewind at startup and logs the version of each detected companion plugin. The `/bp debug run` command includes `ViaVersionIntegration.getDetailedStatus()` for the full version summary.
Configured from `integrations.yml`:
```yaml
viaversion:
enabled: true
```
### Centralized `integrations.yml` configuration
All integration configuration is now in a single `integrations.yml` file inside the plugin data folder (`plugins/BlockProtReloaded/integrations.yml`). The old per-integration files (`integrations/worldguard.yml`, `integrations/lands.yml`, `integrations/towny.yml`, etc.) are no longer shipped or read.
Each integration section has an `enabled: true/false` toggle. Setting `enabled: false` for an integration stops it from registering hooks and listeners without requiring the external plugin to be removed from the server; the integration is simply ignored at startup.
The WorldEdit paste-autolock settings (`paste_autolock.enabled`, `paste_autolock.radius`, `paste_autolock.delay_ticks`, `paste_autolock.block_limit`) were moved from `config.yml` into `integrations.yml` under the `worldedit` section. Old keys in `config.yml` are still read (marked `@Deprecated` in code) but no longer written.
Full `integrations.yml` structure:
```yaml
worldguard:
enabled: true
enable_flag_functionality: true
lands:
enabled: true
allow_protecting_containers_in_wilderness: true
require_protect_for_friends_flag: false
towny:
enabled: true
cleanup_plots_after_unclaim: true
restrict_access_to_residents: false
allow_mayor_to_see_block_info: false
bypass_protection_in_ruined_towns: true
claimchunk:
enabled: true
restrict_access_to_chunk_owner: false
worldedit:
paste_autolock:
enabled: false
radius: 24
max_blocks_per_paste: 5000
delay_ticks: 20
placeholderapi:
enabled: true
viaversion:
enabled: true
```
### First-start console guide
On the very first startup of a fresh install, if no lockable blocks are configured yet, the console prints a short guide directly under the startup banner: use `/bp lockables` in-game, edit `blocks.yml` manually, read the full docs on GitHub, or run `/bp recommended` in console for a sensible default set. The guide prints once per fresh install, tracked by a `.first_start_done` marker file in the plugin data folder. A server migrated from a legacy install never sees it, since it is not a fresh install.
### Debug command expanded
`/bp debug run` now also tests:
| Check | What it verifies |
|---|---|
| Lockable entities | Lists all ENTITIES family members with ACTIVE / INACTIVE status |
| Item frame protection | Reads `isLockableEntity(ITEM_FRAME)` and `isLockableEntity(GLOW_ITEM_FRAME)` and logs the result |
| Raid detection config | Reads `raid_detection.enabled` and confirms the audit logger is active |
| Integrations (expanded) | Calls `ViaVersionIntegration.getDetailedStatus()` for the full Via summary including companion plugins |
| NBT entity write/read | Spawns a temporary ArmorStand, writes an owner UUID, reads it back, then removes the entity |
### Audit log action classification
Clarified and corrected audit-trail event meanings:
- `ACCESS_DENIED` - a player attempted to access a protected block/entity and was blocked
- `OPENED` - a player with access opened the inventory of a protected block
- `RAID_EXPLOSION` - an explosion affected a protected block
- `ITEM_TAKEN` / `ITEM_PLACED` - a player moved items in a protected inventory
### StatHandler rewrite
`StatHandler.saveFile()` was rewritten. The previous implementation called `Files.move(ATOMIC_MOVE)` unconditionally, which throws `IOException: Failed to swap backup NBT file` on Windows and on Linux filesystems that do not support atomic cross-directory moves. The new implementation writes to a temp file, validates it with NBT-API before touching the live file, copies the validated temp file to the backup location, then replaces the live file. When atomic move is unavailable it falls back to a standard copy-and-delete. A `synchronized` block prevents concurrent writes. The dirty flag is preserved across the rewrite.
### Performance improvements
`purgeStalePbsEntries` now checks `World.isChunkLoaded()` before calling `Block.getType()`. Previously, every stored block location whose chunk was not already resident in memory triggered a synchronous chunk load, freezing the server thread for up to 20 seconds for players with large block lists. The fix skips any entry whose chunk is not already loaded and revisits it on a later call.
A Caffeine cache (`purgeThrottle`, 60-second TTL, 512 entries) throttles the per-player stale-entry scan to at most once per 60 seconds, preventing the scan from running on every block-place event for active players.
### Block family expression system
See "`BlockFamilyParser` cross-family validation and `/bp lockables`" above for the full token reference and validation behavior.
### Config and blocks auto-merge on every reload, with content preserved
`reloadConfigAndTranslations()` runs all merge and sync operations on every `/bp reload` call, not only on startup: `cleanLegacyConfigKeys()`, `mergeMissingConfigKeys()`, `mergeMissingBlocksKeys()`, language-file key merging, and the world-config re-scan all run on reload.
The merge guarantee for `blocks.yml`, `config.yml`, and `worlds.yml` is: any top-level section that is entirely missing from the file on disk is added from the bundled JAR defaults, and a console line records what was added. Any key or section that already exists is never overwritten - this means user-configured lockable lists, family expressions, and all other values are preserved across reloads and version upgrades. A future version that adds a brand-new top-level key (for example, a new boolean toggle) will see that key appended automatically; a family expression you already wrote, such as `'[*-CHEST_BOATS ITEM_FRAME]'`, is never rewritten, reordered, or stripped, regardless of how many versions you upgrade through.
Individual entry-level merge (appending new materials to existing flat lists) was removed in 1.3.3 to prevent accidental population of user-configured lists. Only missing top-level sections are merged.
### Renamed config keys with automatic migration
`worlds_config_enabled` is renamed to `per_worlds_config`. On first startup after upgrading, the plugin reads the old key, writes its value under the new name, and removes the old entry from `config.yml`. No manual action is required.
### `auto_reload_configs` flag
New config key, default `true`. When set to `false`, the `ConfigFileWatcher` does not start and config files are not reloaded automatically; use `/bp reload` to apply changes manually. Useful on high-load servers or when editor tooling causes spurious filesystem events.
### SQLite usercache moved into plugin folder
`blockprot_usercache.sqlite` is now created inside `plugins/BlockProtReloaded/` rather than next to `server.jar`. On first startup after upgrading, any file found at the old location is moved automatically.
### Legacy folder migration improved
`migrateFromLegacyFolders()` also calls `mergeYamlUserValues()` after copying files. Admin values from `config.yml` and all language files in the legacy folder are merged key-by-key into the new location. The destination's existing value always wins on conflict, so no configured value is ever overwritten by the migration.
### Raid detection
`RaidDetectionListener` monitors every explosion (`BlockExplodeEvent` and `EntityExplodeEvent`) for proximity to lockable blocks. It does not cancel the explosion; it only detects and notifies.
Behavior:
- Any lockable block in the explosion's block list triggers a `WARN` line in the session log with block type, world, coordinates, and the actor (player name, entity type, or "environment").
- If the block is protected and its owner is online: an action-bar alert fires immediately, followed by a chat message with full coordinates. If the owner has `blockprot.blocks.tp`, a clickable `[Teleport]` link is appended.
- If the owner is offline: the alert is queued in memory and delivered as a chat message the next time they join, with the teleport link included if they have `blockprot.blocks.tp` at join time.
Controlled by `raid_detection.enabled` in `config.yml` (default `true`). Set to `false` to stop all detection and notification without removing the listener.
New translation keys: `messages.raid_alert`, `messages.raid_coords`, `messages.raid_tp_label`, `messages.raid_pending`.
### Support policy change
Starting with 1.3.3, support tiers are:
| Version range | Tier |
|---|---|
| 26.x (Paper/Purpur/Pufferfish), no upper cap | Primary development target |
| 1.21.1 through 1.21.x | Active support |
| 1.20.x and below | Not supported |
The compile target is raised from `paper-api:1.20.6` to `paper-api:1.21.1`. Servers below 1.21.1 no longer load the plugin (enforced by `api-version: 1.21.1` in `plugin.yml`). Legacy 1.20.x users must stay on 1.3.3 or earlier.
### Documentation policy change
Starting with 1.3.4, the project's `README.md` will be condensed to a short summary of all current features rather than documented feature-by-feature in full detail. `RELEASE_NOTES.md` becomes the single authoritative place where what changed between every version is recorded, including this entry. `docs/READ_MEs/MODR_HANG_README.md`, the short description used on Modrinth and Hangar, will continue to be updated for store listings but is not a substitute for this file.
### BEACON added to lockable tile entities
BEACON is now recognized as a lockable tile entity. It can be locked via flat list (add `BEACON` to `lockable_tile_entities`) or family expression (`*-MISC` catches it as an ungrouped tile entity). The default `blocks.yml` now includes `BEACON`.
### SIGNS enabled by default in blocks.yml
All sign variants (floor, wall, hanging, wall-hanging for all 12 wood types) are now enabled by default via the family expression `[*-SIGN]` in `lockable_tile_entities`. This works in both flat-list and modern-expression modes since family expressions are always parsed.
### FLETCHING_TABLE added to WORKSTATION sub-family
FLETCHING_TABLE was present in the default flat list of `lockable_blocks` but was missing from the `isWorkstationMaterial()` check in `BlockFamilyParser` and the `blockValidator` in `DefaultConfig`. This meant it was silently rejected during family expression resolution and the `loadBlocksFromConfig()` validator. It is now a proper member of the `*-WORKSTATION` sub-family and the `lockable_blocks` BLOCKS family.
### `/bp lockables` click-to-toggle
Left-clicking a material in `/bp lockables` toggles it active or inactive and saves the change immediately. Right-click copies the material name; shift-right-click copies the exclusion token (`-MATERIAL_NAME`). This is permanent, built-in behavior with no config option to disable it. Every toggle is logged to the session log with the player and the resulting state.
### `/bp lockables` modern mode compliance
`toggleLockable()` now respects `modern_family_blocks`. In legacy mode, toggling adds/removes flat material names as before. In modern mode, the current config list is parsed into a material set via `BlockFamilyParser.parse()`, the target material is added or removed, and the set is converted back to a compact family expression via `BlockFamilyParser.toFamilyExpression()`. This keeps blocks.yml clean and avoids mixing flat names with expressions.
### `/bp lockables` "Enable all" entry per category
A NETHER_STAR "Enable all" entry appears at the top of every category section (Chests, Shulkers, Furnaces, Storage, Signs, Doors, Trapdoors, Fence Gates, Workstations, Interactive, Entities). Clicking it adds the appropriate family expression (e.g. `[*-CHEST]`, `[*]`, `[*-WORKSTATION]`) to blocks.yml, enabling every material in that category at once. The change is saved to disk and logged.
### `/bp lockables` active-first sorting
Both the category-grouped entries and the entity entries in the lockables GUI are now sorted with active (currently lockable) items first, followed by inactive items. Previously the order was inactive-first.
### External plugin API: `BlockProtAPI.registerIntegration()`
External plugins can now register their own `PluginIntegration` subclasses to hook into BlockProt's protection flow:
```java
// From onEnable() of the external plugin:
Bukkit.getScheduler().runTaskLater(this, () -> {
BlockProtAPI api = BlockProtAPI.getInstance();
if (api != null) {
api.registerIntegration(new MyIntegration());
}
}, 1L);
```
`registerIntegration()` tracks BlockProt's own lifecycle internally: if BlockProt is already past the `load()` or `enable()` phase when the external integration is registered, those phases are called immediately. This means the one-delay-tick pattern above is only needed because `BlockProtAPI.getInstance()` is not available until BlockProt's `onEnable()` completes; the register call itself handles lifecycle automatically.
`PluginIntegration` is fully public and abstract. Subclasses must provide:
- a `name` string (used in boot logging)
- a `load()` method (runs during `BlockProt.onLoad()`)
- an `enable()` method (runs during `BlockProt.onEnable()`)
The `ConfigurationSection` for the integration is available via `getSection(name)` (reads from `integrations.yml`), and the `enabled` toggle should be checked at the top of `enable()`.
Events available for integration hooks: `BlockAccessEvent`, `BlockAccessMenuEvent`, `BlockLockOnPlaceEvent`, all in `de.sean.blockprot.bukkit.events`.
---
## Fixed & Improved
### Bug fixes
- **README.md stale config reference**: The `worldedit_paste_autolock` section in README.md still listed these as live `config.yml` options. They were moved to `integrations.yml` in this release. Changed to a DEPRECATED comment block. The `blockprot.debug` permission default was also corrected from `false` to `op` to match `plugin.yml`.
- **`isKeyInExpressionFormat()` ignored `modern_family_blocks: false`**: when the flag was set to false but `blocks.yml` still contained family expressions like `- '[*-CHEST]'`, every GUI toggle stayed in expression format instead of converting to flat material names. The flag now determines the output format unconditionally: when `false`, all keys are written as flat sorted material lists regardless of the file's current format.
- **`toggleLockable()` and `toggleFamily()` had two code paths**: the expression branch parsed both formats correctly, the flat branch only handled flat input. When `modern_family_blocks` toggled from true to false, the flat branch would not convert existing expressions: toggles silently did nothing. Both methods now use a unified path: parse the raw value (handles both formats), modify the material set, then write in the flag-determined format.
- **`blocks.yml` key order shuffled**: SnakeYAML writes keys in insertion order, so any `blocksConfig.set()` call moved the modified key to the end. Repeated toggles left the file with keys in random order. Added `DefaultConfig.reorderBlocksKeys()` which returns a new `YamlConfiguration` with keys in the fixed order (`lockable_tile_entities`, `lockable_shulker_boxes`, `lockable_blocks`, `lockable_doors`, `lockable_entities`, `auto_drop_to_inventory`). Applied to all save paths: `saveBlocksConfig()`, `mergeMissingBlocksKeys()`, and `convertBlocksFormatIfNeeded()`.
- **Auto-format conversion on reload**: new `convertBlocksFormatIfNeeded()` in BlockProt.java runs during every `reloadConfigAndTranslations()`. It reads blocks.yml, checks if the file's format matches `modern_family_blocks`, and if not, converts all 5 lockable keys to the correct format (expressions or flat names) while preserving every material selection. This means setting `modern_family_blocks: false` and doing `/bp reload` now correctly converts `- '[*-CHEST]'` to flat names like `- CHEST\n- TRAPPED_CHEST\n...`.
- **Translation incomplete message spammed console on every reload and GUI toggle**: `loadFromConfigs()` logged the "N incomplete key(s)" message to `getLogger().info()` every time translations were loaded, which happened on every file-watcher-triggered reload (i.e., after every `/bp lockables` toggle). Changed to a static `translationIncompleteLogged` flag: the message is printed once per server session.
- **Auto-reload console message was removed entirely**: the `ConfigFileWatcher` previously logged "Configuration change detected; reloading..." to the console but was changed to session-log-only to reduce spam. The message is restored to console (one line): the session log retains the additional detail.
- **Block Lock menu button shifting**: every button used a shared incrementing slot counter, so any block type missing one button (for example, no Redstone on a workstation) shifted every later button one slot to the left. The same menu rendered differently for a chest versus a workstation versus a door. Fixed by giving every button a fixed slot in both `fill()` and `fillForEntity()` - see "Fixed menu layout" above.
- **StatHandler NBT save crash**: `Files.move(ATOMIC_MOVE)` failed on cross-device paths. Rewritten to temp-write, validate, backup, replace with fallback copy.
- **Server freeze on stats purge**: `purgeStalePbsEntries` called `Block.getType()` on unloaded chunks, triggering synchronous chunk loads. Fixed with a `World.isChunkLoaded()` guard.
- **EntityChangeBlockEvent AIR crash**: missing early-return for AIR blocks caused a `RuntimeException` in `BlockNBTHandler`.
- **Shulker auto-lock NPE**: wrote NBT via `block.getState()` on freshly placed shulkers whose `BlockEntity` was not yet initialized. Fixed with `block.getState(true)` and a `TileState` guard.
- **`/bp protdel` typo**: was registered as `protdell` (double L); corrected to `protdel`.
- **`/bp protdel` missing non-tile-entity blocks**: the non-MySQL fallback path only scanned `chunk.getTileEntities()`, missing all non-tile lockable blocks (doors, trapdoors, fence gates, anvils, cauldrons, workstations, interactive blocks). The fallback now also scans every block in loaded chunks for lockable non-tile types.
- **`/bp protdel` missing double-chest and door cleanup**: `handler.clear()` was called without `handler.applyToOtherContainer()`, leaving protection data on the other half of double chests and double doors. Added the missing call.
- **Update checker silent failure**: produced no output when running ahead of the latest release; now logs silently instead of erroring.
- **EntitySettingsInventory permission**: used the raw string `"blockprot.admin"` instead of `Permissions.USER_ADMIN` and lacked an `isOp()` fallback. Fixed.
- **CraftBukkit error path**: the error message shown to plain-CraftBukkit servers is now properly translated instead of showing a raw key string.
- **`BlockProtAPI` instantiation was too late for external integrations**: `BlockProtAPI.getInstance()` returned `null` until after all startup logging, the first-run guide, and the banner were printed. `new BlockProtAPI(this)` is now created right after integrations are enabled, making the API available to external plugins earlier in the startup sequence. Additionally, `registerIntegration()` now tracks BlockProt's internal lifecycle (`integrationsLoaded`, `integrationsEnabled`) and calls `load()`/`enable()` on newly registered integrations immediately if BlockProt has already passed that phase; external integrations registered via `Bukkit.getScheduler().runTaskLater(..., 1L)` no longer skip lifecycle hooks.
### Inherited bug fixes
| Issue | Title | Fixed in |
|---|---|---|
| [#302](https://github.com/spnda/BlockProt/issues/302) | 1.21.1 not supported properly | Upstream |
| [#304](https://github.com/spnda/BlockProt/issues/304) | Unknown warning/error occurred | Upstream |
| [#305](https://github.com/spnda/BlockProt/issues/305) | Taking map from Search Players slot | Upstream |
| [#319](https://github.com/spnda/BlockProt/issues/319) | Emptying large chests incorrectly on hoppers | Upstream |
| [#323](https://github.com/spnda/BlockProt/issues/323) | 1.21.3 not supported properly | Upstream |
| [#326](https://github.com/spnda/BlockProt/issues/326) | Redstone protection bugged with trapdoors | Upstream |
| [#327](https://github.com/spnda/BlockProt/issues/327) | Paper NoClassDefFoundError Container | Upstream |
| [#328](https://github.com/spnda/BlockProt/issues/328) | Colored shulker boxes reset when broken | Upstream |
| [#329](https://github.com/spnda/BlockProt/issues/329) | AIR block error on entity change | Upstream |
| [#330](https://github.com/spnda/BlockProt/issues/330) | Pale oak door/gate cannot be locked | Upstream |
| [#332](https://github.com/spnda/BlockProt/issues/332) | Unable to use BlockProt on 1.21.7 | Upstream |
| [#338](https://github.com/spnda/BlockProt/issues/338) | Support for Minecraft 1.21.9 | Upstream |
| [#339](https://github.com/spnda/BlockProt/issues/339) | Shulker box vanishes when broken | Upstream |
| [#165](https://github.com/spnda/BlockProt/issues/165) | Random inventory close on interaction | Upstream |
| [#266](https://github.com/spnda/BlockProt/issues/266) | `public_is_friend_by_default` setting | Upstream |
| [#294](https://github.com/spnda/BlockProt/issues/294) | Geyser players missing from friend search | Upstream |
| [#185](https://github.com/spnda/BlockProt/issues/185) | Hopper protection below chest not working | Upstream |
| [#214](https://github.com/spnda/BlockProt/issues/214) | Making doors public only half the door | Upstream |
| [#224](https://github.com/spnda/BlockProt/issues/224) | Locked shulker boxes break without dropping | Upstream |
| [#227](https://github.com/spnda/BlockProt/issues/227) | Hopper and piston protection swapped | Upstream |
| [#235](https://github.com/spnda/BlockProt/issues/235) | Lectern protection issues | Upstream |
| [#240](https://github.com/spnda/BlockProt/issues/240) | Hopper protecting not working | Upstream |
| [#250](https://github.com/spnda/BlockProt/issues/250) | Can get Player Head from menu | Upstream |
| [#256](https://github.com/spnda/BlockProt/issues/256) | Can't copy/paste settings between blocks | Upstream |
| [#263](https://github.com/spnda/BlockProt/issues/263) | Can take Telescope from Menu | Upstream |
| [#272](https://github.com/spnda/BlockProt/issues/272) | Can't move items as admin/op | Upstream |
| [#276](https://github.com/spnda/BlockProt/issues/276) | Items can still be placed into chests | Upstream |
| [#279](https://github.com/spnda/BlockProt/issues/279) | Items being deleted on interact | Upstream |
| [#280](https://github.com/spnda/BlockProt/issues/280) | Shulker box items deleted after breaking | Upstream |
| [#281](https://github.com/spnda/BlockProt/issues/281) | Dropper not working after unlock | Upstream |
| [#287](https://github.com/spnda/BlockProt/issues/287) | Double chest not handled on inventory click | Upstream |
| [#289](https://github.com/spnda/BlockProt/issues/289) | Chest locked but friends can open | Upstream |
| [#296](https://github.com/spnda/BlockProt/issues/296) | Item lost on interact | Upstream |
| [#297](https://github.com/spnda/BlockProt/issues/297) | Item drops can't be picked by hopper | Upstream |
| [#321](https://github.com/spnda/BlockProt/issues/321) | Wither explosions breaking protected blocks | Upstream |
### Fork-specific fixes
| Issue | Title | Fix |
|---|---|---|
| [#268](https://github.com/spnda/BlockProt/issues/268) | Friend list copy/paste should replace instead of appending | Paste replaces friend list |
| [#306](https://github.com/spnda/BlockProt/issues/306) | Plugin causes server lag (hopper checks) | ProtectedBlockCache with O(1) early-exit |
| [#324](https://github.com/spnda/BlockProt/issues/324) | Option to allow all protected blocks to be broken | `allow_break_protected_blocks` config key |
| (not tracked upstream) | Players can access second row of large chest | Inventory double-chest gating |
| [#349](https://github.com/spnda/BlockProt/issues/349) | Warn spam in console (NBT swap error) | StatHandler rewrite with temp-write-validate-replace |
| [#238](https://github.com/spnda/BlockProt/issues/238) | Piston Protection Shulker Box | Shulker box check added to piston retract logic |
### Dependency updates
| Dependency | Old | New | Reason |
|---|---|---|---|
| `paper-api` (compile) | `1.20.6-R0.1-SNAPSHOT` | `1.21.1-R0.1-SNAPSHOT` | Support baseline raise |
| `FoliaLib` | `0.4.3` | `0.5.1` | Bug fixes, latest stable |
| `item-nbt-api` | `2.15.6` | `2.15.7` | 26.1.x and 1.21.11 support |
| `MockBukkit` (test) | `v1.20:3.93.2` | `v1.21:4.8.0` | Aligns with new compile baseline |
### Known Issues
- **MockBukkit unresolvable**: `MockBukkit-v1.21:4.8.0` returns HTTP 401 from jitpack.io. Build with `-x test` to skip tests.
- **Gradle `shadowJar` false up-to-date**: on some local setups, running `:blockprot-spigot:shadowJar` after only source changes (no `clean`) can report `BUILD SUCCESSFUL` while reusing a stale or absent output if Gradle's up-to-date check does not detect the change. If the jar is missing or unexpectedly small after a build, rerun with `--rerun-tasks`, or run `gradlew clean :blockprot-spigot:shadowJar` to force a full rebuild.
## Complete Issue Reference (>= #250)
Every non-trivial issue from the upstream repository sorted by category. Issues closed upstream are fixed in this fork by inheritance. Issues open upstream but resolved in this fork are noted as fork-specific fixes.
### Bugs fixed upstream (inherited)
These were closed in the upstream repository and are fixed in this fork:
| Issue | Title |
|---|---|
| [#339](https://github.com/spnda/BlockProt/issues/339) | Shulker box vanishes when broken |
| [#338](https://github.com/spnda/BlockProt/issues/338) | Support for 1.21.9 |
| [#337](https://github.com/spnda/BlockProt/issues/337) | Bug (untitled) |
| [#336](https://github.com/spnda/BlockProt/issues/336) | Bug (untitled) |
| [#335](https://github.com/spnda/BlockProt/issues/335) | Bug (untitled) |
| [#332](https://github.com/spnda/BlockProt/issues/332) | Unable to use on 1.21.7 server |
| [#330](https://github.com/spnda/BlockProt/issues/330) | Pale oak door/gate cannot be locked |
| [#329](https://github.com/spnda/BlockProt/issues/329) | Air block error on entity change |
| [#328](https://github.com/spnda/BlockProt/issues/328) | Colored shulker boxes reset when broken |
| [#327](https://github.com/spnda/BlockProt/issues/327) | Paper NoClassDefFoundError Container |
| [#326](https://github.com/spnda/BlockProt/issues/326) | Redstone protection bugged with trapdoors |
| [#323](https://github.com/spnda/BlockProt/issues/323) | 1.21.3 not supported properly |
| [#319](https://github.com/spnda/BlockProt/issues/319) | Emptying large chests incorrectly on hoppers |
| [#305](https://github.com/spnda/BlockProt/issues/305) | Taking map from Search Players slot |
| [#304](https://github.com/spnda/BlockProt/issues/304) | Unknown warning or error occurred |
| [#302](https://github.com/spnda/BlockProt/issues/302) | 1.21.1 not supported properly |
| [#297](https://github.com/spnda/BlockProt/issues/297) | Item drops can't be picked by hopper |
| [#296](https://github.com/spnda/BlockProt/issues/296) | Item lost on interact |
| [#293](https://github.com/spnda/BlockProt/issues/293) | Problem with chests regarding hoppers |
| [#290](https://github.com/spnda/BlockProt/issues/290) | Bug (untitled) |
| [#289](https://github.com/spnda/BlockProt/issues/289) | Chest locked but friends can open |
| [#281](https://github.com/spnda/BlockProt/issues/281) | Dropper not working after unlock |
| [#280](https://github.com/spnda/BlockProt/issues/280) | Shulker box items deleted after breaking |
| [#279](https://github.com/spnda/BlockProt/issues/279) | Items being deleted on interact |
| [#276](https://github.com/spnda/BlockProt/issues/276) | Items can still be placed into chests |
| [#275](https://github.com/spnda/BlockProt/issues/275) | Hoppers can take items from protected chests |
| [#274](https://github.com/spnda/BlockProt/issues/274) | Players can access second row of large chest |
| [#272](https://github.com/spnda/BlockProt/issues/272) | Can't move items as admin/op |
| [#263](https://github.com/spnda/BlockProt/issues/263) | Can take Telescope from Menu |
| [#256](https://github.com/spnda/BlockProt/issues/256) | Can't copy/paste settings between blocks |
| [#255](https://github.com/spnda/BlockProt/issues/255) | Can't remove everyone from settings |
| [#250](https://github.com/spnda/BlockProt/issues/250) | Can get Player Head from menu |
| [#240](https://github.com/spnda/BlockProt/issues/240) | Hopper protecting not working |
| [#236](https://github.com/spnda/BlockProt/issues/236) | Copy Paste not working properly |
| [#235](https://github.com/spnda/BlockProt/issues/235) | Lectern protection issues |
| [#232](https://github.com/spnda/BlockProt/issues/232) | Sign not in lockable_blocks |
| [#230](https://github.com/spnda/BlockProt/issues/230) | Can't unlock wall sign |
| [#227](https://github.com/spnda/BlockProt/issues/227) | Hopper and piston protection swapped |
| [#226](https://github.com/spnda/BlockProt/issues/226) | Chest unlocked but shown as locked |
| [#224](https://github.com/spnda/BlockProt/issues/224) | Locked shulker boxes break without dropping |
| [#221](https://github.com/spnda/BlockProt/issues/221) | Chest locked but friends can open |
| [#215](https://github.com/spnda/BlockProt/issues/215) | Chests cannot be placed on public |
| [#214](https://github.com/spnda/BlockProt/issues/214) | Making doors public only half the door |
| [#185](https://github.com/spnda/BlockProt/issues/185) | Hopper protection below chest not working |
### Bugs open upstream, fixed in fork
| Issue | Title | Fork Fix |
|---|---|---|
| [#306](https://github.com/spnda/BlockProt/issues/306) | Plugin causes server lag | ProtectedBlockCache with Caffeine O(1) early-exit |
| [#324](https://github.com/spnda/BlockProt/issues/324) | Allow breaking protected blocks | `allow_break_protected_blocks` config key |
| [#349](https://github.com/spnda/BlockProt/issues/349) | Warn spam in console (NBT swap error) | StatHandler rewrite with temp-write-validate-replace |
| [#344](https://github.com/spnda/BlockProt/issues/344) | Console spam (NbtApiException) | Same NBT swap warning as #349, covered by the same StatHandler rewrite |
### Features open upstream, implemented in fork
| Issue | Title | Fork Implementation |
|---|---|---|
| [#298](https://github.com/spnda/BlockProt/issues/298) | Integration support for ClaimChunk | `ClaimChunkIntegration`, see "ClaimChunk integration" above |
| [#295](https://github.com/spnda/BlockProt/issues/295) | Lock trapdoors and iron doors | Trapdoors are members of the `TRAPDOOR` sub-family under `lockable_blocks`; all `*_DOOR` materials, including `IRON_DOOR`, are members of the `DOORS` family under `lockable_doors` |
| [#318](https://github.com/spnda/BlockProt/issues/318) | Ability to configure lockable blocks per world | `per_worlds_config` in `config.yml` plus `worlds.yml`, see "Per-world lockable GUI" above |
| [#303](https://github.com/spnda/BlockProt/issues/303) | Respect spawn protection radius | `respect_spawn_protection` in `config.yml` (default `true`); non-op, non-admin players cannot lock a block inside the server's spawn-protection radius |
| [#282](https://github.com/spnda/BlockProt/issues/282) | MySQL Support | `HybridDatabase`, a Hikari-pooled MySQL/MariaDB index configured in `mysql/mysql.yml`. NBT stays the source of truth for ownership and friends; the database mirrors block locations and global trust lists for auditing and search on large servers |
| [#334](https://github.com/spnda/BlockProt/issues/334) | Colored prompt messages | Fully supported via both MiniMessage and legacy color codes in Translator |
| [#192](https://github.com/spnda/BlockProt/issues/192) | Support Inspect contents block name i18n | Inspect contents inventory titles are now localized |
| [#346](https://github.com/spnda/BlockProt/issues/346) | New configuration option | Added `clear_protection_on_shulker_break` config |
| [#322](https://github.com/spnda/BlockProt/issues/322) | Toggle for simplified hopper logic | Added `simplified_hopper_logic` config |
| [#269](https://github.com/spnda/BlockProt/issues/269) | Shows the owner of the box | Implemented via Action Bar on interact |
| [#267](https://github.com/spnda/BlockProt/issues/267) | Expire locks after owner offline for x time | Implemented via world expiry subsystem |
| [#228](https://github.com/spnda/BlockProt/issues/228) | Separate Redstone in config | Implemented via `redstone_disallowed_by_default` |
| [#225](https://github.com/spnda/BlockProt/issues/225) | Stats more Features | Covered by the `StatisticListInventory` GUI |
| [#183](https://github.com/spnda/BlockProt/issues/183) | Support Residence | `ResidenceIntegration` added |
| [#154](https://github.com/spnda/BlockProt/issues/154) | Support for GriefPrevention | `GriefPreventionIntegration` added |
## Reporting an Issue
If you reached this point in the document, thank you for reading. When reporting a bug, please include the following information so the issue can be diagnosed and fixed faster:
| Field | What to include |
|---|---|
| Discord (optional) | Your Discord username so I can follow up directly |
| Error description | Exactly what the error says and step-by-step how to reproduce it |
| Multimedia | Screenshots or videos showing the issue |
| Server info | Server version, software (Paper / Purpur / Spigot), and a list of other plugins installed |
| Error log | The full error log (use a paste site like https://pastes.dev if it is long) |
release
BlockProt Reloaded 1.3.2
1.3.24 июн. 2026 г.122Minecraft: 1.20, 1.20.1, 1.20.2, 1.20.3, 1.20.4, 1.20.5, 1.20.6, 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2bukkit, folia, paper, spigot
Что нового
Added the option to remove ALL protections from a world individually
release
BlockProt Reloaded 1.3.1
1.3.131 мая 2026 г.187Minecraft: 1.20, 1.20.1, 1.20.2, 1.20.3, 1.20.4, 1.20.5, 1.20.6, 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1.1, 26.1.2bukkit, folia, paper, spigot
Что нового
Release from 1.3.0-SNAPSHOT-2
New: /bp unlock GUI
The old coordinate-based /bp unlock [world] command has been replaced with a full paginated GUI. Running /bp unlock opens a six-row inventory listing every block currently protected by the target player, using the real block icon for each entry. Left-click any block to inspect its inventory contents in read-only mode — no items can be taken or placed. Right-click any block to remove its protection entirely; an action-bar message confirms the block name, the owner it was removed from, and the coordinates. Supports pagination and works for offline players. Requires blockprot.user.admin.
New: Duration Parser
Timed access and protection expiry now share a single DurationParser that accepts human-readable duration strings with combined units. Accepted suffixes: s (seconds), m (minutes), h (hours), d (days), mo / mon (months), y (years). Units can be freely combined: 1d12h30m, 2mo3d, 1y6mo. All max-per-unit limits are enforced and configurable. Previously the timed-access parser was a separate inline implementation with no support for combined units.
Fix: Inventory title and item name color injection
All GUI menu titles and item display names are now rendered as plain text, letting Minecraft apply its default white color. Previously LegacyComponentSerializer was used to set display names, which caused section-sign color codes embedded in translation strings or hardcoded prefixes to produce colored text — most visibly the §4Admin §f prefix on the /bp unlock inventory title shown in the screenshot below. Every inventory class has been updated: BlockProtInventory now strips §x and &x codes before passing any string to Component.text(). Lore lines and chat/action-bar messages are unaffected and still support legacy color codes from translation files.
Fix: InventoryConstants.singleLine duplicate removed
singleLine was a duplicate constant of lineLength (both equal to 9). All seven call sites across BlockInfoInventory, FriendDetailInventory, FriendManageInventory, and UserSettingsInventory have been migrated to lineLength and the duplicate constant removed.
Fix: Unused PlayerTextures import removed from BlockProtInventory
Fix: Dead actionIcon() method removed from AuditInventory
The method was only used to prepend colored §cX / §aO / §e- / §2+ symbols to audit entry display names. With the color injection fix, display names are now plain text and the symbol-based prefix was replaced by the already-existing actionLabel() string. The dead method has been removed.
Fix: Inline color codes removed from TimedAccessInventory, AuditInventory, and AdminMenuInventory
Hardcoded §a / §c / §e / §7 / §8 / §f / §6 prefixes were removed from item labels, audit entry display names, lore lines, and the integrations action-bar output. Text that had no meaningful color intent is now plain; text in lore that was intentionally styled continues to use the legacy serializer from the translation file.
Documentation: Command and permission audit
A full cross-reference of all command source files against plugin.yml and the README was performed. Corrections applied: /bp timed is documented as a chat-input flow rather than a tab-completable CLI subcommand (it was never registered in BlockProtCommand's CLI map); /bp friends bare invocation was undocumented and has been added; /bp reload, /bp update, and /bp integrations require op, not blockprot.user.admin — corrected in the README; /bp about and /bp help are CLI-only and are hidden in GUI mode — the incorrect "Universal Commands" section has been removed; the permissions table now distinguishes between permissions declared in plugin.yml (with defaults) and runtime-only nodes (blockprot.debug, blockprot.lockmax, blockprot.locklimit.*) that must be granted manually.
Documentation: README User Menu table corrected
The User Menu slot table now reflects the actual UserMenuInventory layout: four items at slots 11–14 (Settings, Friends, Statistics, About). The previous table listed six items across slots 10–16 including Transfer and Timed Access hints that are not present in the current implementation.
beta
BlockProt Reloaded 1.3.0-SNAPSHOT-2
1.3.0-SNAPSHOT-221 мая 2026 г.27Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2bukkit, paper, spigot
Что нового
Here is the release notes for Snapshot 2. The changes were mentioned in the last version. Snapshot 3 is expected sometime this week, but it might be delayed because I have exams to get into high school, so please be patient. I appreciate your support, and if you find any bugs, please report them in this repository. Have a nice evening.
beta
BlockProt Reloaded 1.3.0-SNAPSHOT-1
1.3.0-SNAPSHOT-121 мая 2026 г.19Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2bukkit, paper, spigot
Что нового
# Snapshot Release Notes | Development Cycle Consolidation and Core Refactoring
This major snapshot release marks the official deployment and architectural consolidation of development builds Dev 3, Dev 4, and Dev 5 into a single synchronized build.
## Versioning Methodology and Release Pipeline
To establish a more rigorous and predictable development cycle, the project infrastructure is transitioning to an automated version tracking pipeline. Moving forward, version sequences will follow a strict milestone rule: upon the compilation and completion of the fifth iterative development build (Dev 5), the release system will automatically transition and generate a new major snapshot release branch.
> [!IMPORTANT]
> Example Progression: Version `1.2.9-dev-5` will automatically trigger the generation of the subsequent major release, `1.3.0-SNAPSHOT-1`. This structural framework has been introduced to significantly improve long-term version management, dependency tracking, and update deployment predictability. This specific versioning pipeline is currently provisional and remains subject to modification as the continuous integration requirements evolve.
---
## Technical Performance and Architectural Optimization
* **Console Streamlining and Runtime Efficiency:** The core architecture has undergone extensive optimization to enhance processing speeds and overall server stability. A key objective of this refactoring was the drastic reduction of continuous console output logging. By suppressing redundant tracking data and routine informational messages, the build prevents unnecessary disk write overhead, maximizes console readability for administrators, and ensures that critical system errors or alerts are highly visible without log spam.
* **Hierarchical Configuration Documentation:** Comprehensive administrative documentation has been embedded directly into the project ecosystem. This asset provides a highly organized structural framework for configuration files. It outlines exactly how properties, values, and localized parameters should be formatted, allowing server operators to maintain organized file directories and deploy custom local alterations with minimal risk of formatting errors.
---
## Security and Protection Infrastructure
* **Pet Protection Subsystem (Disabled by Default):** A specialized protection mechanism has been engineered to preserve the safety and security of player-owned pets and tamed entities. When activated, this subsystem completely immunizes protected entities from damage vectors caused by external players, hostile attacks, and unauthorized interactions or physical interventions by non-whitelisted individuals.
* **Isolated MySQL Database Architecture:** To maximize database reliability and operational segregation, the data storage layer has been updated. The infrastructure now forces all MySQL directories, storage tables, and configuration outputs to reside within an entirely independent, dedicated sub-folder separate from standard runtime assets.
* **Integrated Protection Feedback Particles:** Visual confirmation systems developed and tested during iterations 3 and 4 have been officially compiled into the production build. The engine now triggers real-time particle rendering routines to provide explicit gameplay feedback for security interactions. These custom particle vectors are executed upon successfully locking or unlocking a storage container, enabling local protection filters over active redstone networks, establishing active protection criteria over hoppers, and enforcing security parameters over piston mechanics to prevent illegal block movement.
---
## User Interface and Experience Engineering
* **Action Bar Information Routing:** To preserve chat aesthetics and prevent standard text saturation, user query outputs have been completely rerouted. Execution of the friend lookup utility will no longer post raw text blocks or status confirmation strings directly into the global or local player chat log. Instead, the requested user data is sent straight to the client screen via the action bar overlay, ensuring a non-intrusive HUD readout that keeps active gameplay visible.
* **SkinRestorer Integration for Offline-Mode (Cracked) Servers:** To enhance player identification thresholds within offline-mode or hybrid network topologies, formal compatibility bridges have been engineered for the SkinRestorer API. The system is now fully capable of pulling, caching, and rendering individual user skin head textures directly inside the plugin's graphical menus and player reference lists. This integration ensures that players operating on cracked servers can instantly recognize and confirm the identity of individuals they add to their trusted access lists via accurate visual cues.
---
## Future Objectives and GUI Migration Roadmap
Development has officially commenced on the upcoming Snapshot 2 build. While the automated bulk-processing macro `/bp friends addall` has already been fully integrated (successfully addressing the top-voted community request sourced from historical Bukkit discussion comments), the upcoming development phases will follow a specific transitional roadmap from command-line dependencies toward full graphical user interface (GUI) management.
### Snapshot 2: Feature Expansion and Command Implementation
The immediate next phase will focus on deploying critical structural features requested by the community alongside essential performance patches. Consequently, Snapshot 2 will introduce a higher volume of manual text commands than traditionally expected. Scheduled implementations include:
* **Authorization and Ownership Transfer Commands (`/bp transfer <player>`):** A secure ownership migration utility allowing a protection builder to permanently delegate full administrative rights over a specific container directly to another verified user identity.
* **Access Control List Replacement Matrix:** Addressing GitHub ticket #268, the copy-and-paste utility will abandon entry-appending in favor of an explicit "Replace Mode," entirely flushing pre-existing access lists on target blocks to prevent permission stacking.
* **Temporal and Time-Decaying Access Protocols:** An advanced temporal authorization layer allowing users to extend block interaction privileges to auxiliary players that automatically self-terminate after a server-validated timestamp expires.
* **Administrative Verification Utilities (`/bp info <player>Code`):** A comprehensive lookup command granting authorized staff the ability to extract a full location list of all protected coordinates registered to any targeted player profile.
### Snapshot 3: Interface Refinement and Visual Migration
To resolve the heavy reliance on manual commands introduced in the previous cycle, Snapshot 3 will be dedicated almost entirely to interface engineering. The objective is to migrate newly added operational commands directly into the visual management GUI. This phase will introduce:
* **Granular Permission Controls via Graphical Interface:** Expanding the management menu to support individual permission toggles, allowing users to interactively cycle friend access levels between read-only parameters and full structural write access.
* **Explicit Lock-on-Place State Labels:** Deprecating the use of simple enchantment glints as status indicators in favor of definitive, clear textual labels indicating absolute enabled or disabled states within the menu.
### Snapshot 4: Complete GUI Standardization
The ultimate milestone for Snapshot 4 is the near-total deprecation of syntax-based execution for standard users. By this release, the objective is to ensure that the vast majority of the plugin's functionalities, configurations, and administrative tools are accessible entirely through intuitive graphical menus, virtually eliminating the need for manual command inputs during standard gameplay.
---
## Development Methodology and Research Documentation
The layout of this development roadmap is dictated by structural user data obtained by monitoring historical platform interactions. To guarantee that future milestones resolve authentic infrastructure demands, an empirical audit was conducted across the following major community nodes:
* **GitHub Repository Infrastructure:** Monitored open development logs and high-interaction tickets to isolate mechanical conflicts within file copying utilities, validating the requirement for absolute data-replacement mechanics over standard string appending.
* **SpigotMC Distribution Analytics:** Evaluated administrative and end-user review histories regarding menu clarity, establishing a clear technical requirement for replacing implicit texture indications with definitive alphanumeric state labels and transitioning toward interactive GUI-driven permission nodes.
* **Bukkit Community Forum Records:** Investigated automation bottlenecks within archival discussion threads, which guided the earlier completion of mass-addition macros and continues to define the trajectory toward full GUI standardization.
* **Network Infrastructure and Economy Case Studies:** Evaluated current operational demands within multi-user survival environments. The resulting data demonstrated an immediate necessity for regional block auditing, ownership translation tools, and decay-based permission keys to secure temporary player alliances.
Snapshot 2 will be released within minutes of the release of Snapshot 1, since the optimization changes were minimal. This snapshot (2) will be the version of the plugin with the most commands; this will be addressed in subsequent snapshots.
alpha
BlockProt Reloaded 1.2.9-dev-2
1.2.9-dev-219 мая 2026 г.33Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2bukkit, paper, spigot
Что нового
Added
3. Colored Particle Effects on Lock / Unlock / Settings Toggle
Lock → green dust-particle ring around the block + chest-locked sound.
Unlock → red dust-particle ring + sound.
Double chests are handled correctly: both halves receive the particle ring simultaneously.
Redstone setting toggle → red ↔ white DUST_COLOR_TRANSITION ring + lever click sound.
Hopper setting toggle → light-gray ↔ dark-gray transition ring.
Piston setting toggle → brown ↔ gray transition ring.
All effects respect block_lock_effects: true/false in config.yml (default: true).
24. Shulker Box — Shift+Right-Click Places Without Protection
Placing a shulker box while sneaking (Shift+right-click) skips the lock-on-place step.
The shulker is placed without any owner, so the recipient can open and lock it as their own.
Normal placement still auto-locks as configured.
Configurable via the existing lock_on_place_by_default flow; no extra config key needed.
25. Skin Resolution for Cracked / Offline-Mode Servers
SkinCache provides an async Mojang-API fallback for offline servers where UUIDs are name-derived and don't correspond to Mojang profiles:
On first GUI open for a player, a plain (no-texture) head is shown immediately.
In the background, BlockProt queries api.mojang.com to resolve the real Mojang UUID from the username, then fetches the skin texture from the session server.
On the next GUI open the skinned head is returned from cache.
SkinRestorer (if installed) always takes priority over the Mojang fallback.
Fetch failures (network errors, rate limits, unknown names) are silently skipped; the plain head continues to be shown without any console errors.
26. Admin Teleport from Statistics Inventory
In the Statistics → Your Blocks list, players with blockprot.admin permission can click any block entry to teleport directly to that block.
The inventory closes after teleporting.
Players without the admin permission see no change on click.
27. Amber Console Colors for BlockProt-Plus Messages
Integration registration and enable messages print in gold/amber via BlockProtConsole.
Informational startup messages use §e yellow, success messages use §a green, warnings §c red.
Uses Bukkit.getConsoleSender().sendMessage() with legacy color codes — rendered natively by Paper's Log4j2 console renderer on 1.21+ and falls back to plain text on Spigot.
Example: §6[BlockProt]§r §6Integration enabled: §eclaimchunk§r
28. Per-Player Sections in the Access Audit Log
The audit GUI overview now shows one head per unique player with a clear label: §cX §fname (access denied) or §aOK §fname (access granted).
Lore shows the last event timestamp, total event count, and world/coordinates.
Clicking a player head opens their full personal history (all events in order).
The detail view shows individual event timestamps and actions.
Navigation arrows are consistent across both views.
Dev 1 is dead kay don´t ask for him, his dead and will never revive, 🥹
alpha
BlockProt Reloaded 1.2.9-SNAPSHOT
1.2.9-SNAPSHOT19 мая 2026 г.27Minecraft: 1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10, 1.21.11, 26.1, 26.1.1, 26.1.2bukkit, paper, spigot
Что нового
All the information of this SNAPSHOT is in [BlockProt - Repo](https://github.com/VictorGugug/BlockProt-Plus) after this release all the changues will be documented on [Releases - Github](https://github.com/VictorGugug/BlockProt-Plus/releases)