Voxel Shop beta is live. Expect occasional bugs. Learn more
Chest protection plugin with anti-explosion and permission support.
The largest release so far. Every part of the plugin was reworked: storage, protection, threading, version support and translation. Several features that were configurable in 2.x but did nothing are now connected, and several ways to lose data or bypass protection are closed.
Updating from 2.x
Back up your plugins/PrivateChest/ folder. Then drop in the new jar and restart. No manual conversion, no downtime, no data file changes.
Done for you
Backups
data.yml.v2-backup, or privatechest.db.v2-backup plus a privatechest_data_v2_backup table
Data format
Unchanged, read as-is
Passwords
Old formats still work, upgraded to PBKDF2 as each is entered correctly
Plain text passwords
Hashed at first startup (pre-2.0 data only)
New config options
Added to config.yml, your values untouched
New messages
Added to messages.yml, your wording untouched
Needs your attention
1. SQLite users: trust and container names were never saved by 2.x. The SQLite backend accepted them and discarded them, so they vanished on every restart. 3.0 stores them properly but cannot recover what earlier versions threw away. Your players may need to run /trust again once.
2. Per-shulker-colour limits are gone. If you configured container-limits.types.white_shulker_box and friends, replace them with the single shulker_box entry. Old keys and the old per-colour permission nodes are ignored.
3. Four behaviour changes. All of them make the plugin stricter or fix something broken:
Trusted players can no longer break containers, only use them
Trust granted destruction rights by accident
Breaking half a double chest no longer unlocks the other half
It used to leave the surviving chest open
Hoppers can be placed next to containers you have access to
2.x refused next to your own chests, breaking players' own sorting systems
/privatechest requires a valid subcommand
It used to reload on any argument, including typos
4. Optional: set language: es (or your own translation) and delete messages.yml if you want it recreated in another language.
Data safety
Four ways to lose protections, all closed.
• Worlds not loaded at startup lost every protection inside them. Records were dropped from memory and the next save wrote that loss to disk permanently. Affects anyone unmounting a world or using a world manager that loads after plugins.
• An interrupted save could truncate data.yml and destroy every protection on the server. Writes are now atomic: a temp file moved into place.
• Worlds with a dot in the name (world.old) had their records silently mangled.
• A pre-2.0 plain text password containing : was mistaken for a hash, never upgraded, and could never be verified again, permanently locking its owner out. Also: unreadable records are now counted and reported at startup instead of vanishing, and a double chest that fails to lock halfway through is rolled back instead of leaving one protected half.
Performance
• Saves no longer happen per action. Every lock, unlock, break, /trust and rename used to rewrite the entire dataset on the main thread. Changes are now collected and written by a background thread on an interval. Ten players locking chests in one second produce one write, not ten full rewrites.
• InventoryMoveItemEvent was the plugin's biggest per-tick cost. It fires for every item transfer on the server, and 2.x built a full container snapshot, including a copy of its inventory, for both the source and the destination of each one. Handlers now start with one lookup in a per-chunk index.
• Chunk loads removed from hot paths. Limit checks read every one of a player's recorded positions out of the world on each lock attempt. /clearchests did the same for every record on the server. Neither does now, and cleanup only examines chunks that are already loaded.
• Double chest detection reads block data instead of block state.
• SQLite writes only changed rows, in a transaction, with WAL and an indexed owner column. It also falls back to YAML instead of starting with no protection if it cannot open.
Protection gaps closed
Pistons
Barrels and shulker boxes are pushable. A griefer could shove a locked barrel one block: the record stayed at the old coordinates and the container came to rest unprotected
Only right-clicks were checked
Any other route into a container's contents went straight through. Opening is now guarded at the inventory level too
Fire and mobs
Nothing stopped a protected container burning or being removed by a mob
Hopper minecarts
Item pickup into a protected container was not covered
Duplicate messages
A right-click fires once per hand and the handler did not check which, so every message arrived twice
Passwords
Stored as PBKDF2-HMAC-SHA256 with a random salt, instead of one pass of SHA-256 which is fast enough to brute force offline. Raising the iteration count later strengthens existing passwords as they are used, with no migration step. Measured cost at the default: about 9 ms per /unlockchest. Guessing was also unlimited and invisible. Now rate limited and optionally logged with the player name and container position.
Minecraft version support
One jar for 1.16.5 through 26.2. Everything version-specific resolves at startup.
• Copper chests can be protected, all oxidation and waxed stages, and crafters too. Neither was possible in 2.x, whose container list was twenty types written into the code.
• An oxidizing copper chest stays yours. Its block type changes as it weathers; every stage counts as the same container, so it stays locked and your count does not shift.
• [Private] signs read both sides. Signs have had a writable back since 1.20, and a tag written there locked nothing while appearing to.
• The container list is yours, and future containers work without a plugin update:
disabled never deletes existing data: the cleanup treats a disabled type as still being a container.
Folia
Folia support was advertised in 2.x and did not exist. /renamecontainer failed outright, the cleanup read blocks from an async timer, /clearchests read across regions, and repeating tasks could not be cancelled so they survived plugin disable. Block access now runs on the thread that owns the chunk, on Folia, Luminol, LightingLuminol, LeafMC and Kaiiju. Two side benefits on regular servers: cleanup is spread over ticks instead of running in one block, and it no longer forces chunks to load.
Features that did nothing
Three subsystems were fully written in 2.x and never called.
• Per-container-type limits. The whole container-limits section and every per-type permission node had no effect. /lockchest and [Private] signs now share one limit check, so they cannot disagree.
• Container names. /renamecontainer stored a name that was never displayed. Names now appear in access and denial messages through {container}, alongside {owner}.
• Bedrock message adaptation. Not one message ever reached it, so Bedrock players got identical text. It now runs for every message, and three bugs in it were fixed: it truncated at 100 characters (shorter than several of the plugin's own messages), it re-resolved Floodgate on every call, and its symbol list did not cover the characters the plugin actually uses.
Limit fixes
• A limit permission now beats the default. default-chest-limit was applied first and the larger of the two won, so privatechest.limit.1 on a server with a default of 5 granted 5. Permissions below the default could not restrict anyone.
• Any number works. Only eleven values were ever checked, so privatechest.limit.7 silently did nothing. Limits and permissions now key off a container family: chest, trapped_chest, copper_chest, barrel, shulker_box, crafter, other. A per-material limit can never work for a container whose material changes on its own.
Commands
/privatechest gained real subcommands, all under privatechest.admin:
reload
Reload configuration and messages
status
Backend in use, protected containers, trust relations, protectable types, unsaved changes
save
Write pending changes now
migrate <yaml
sqlite>
migrate was documented in 2.x config.yml but did not exist. It updates storage-type for you without stripping your comments, and leaves the old files as a backup. If it fails at any point the current backend stays in use, untouched.
Tab completion
Every command and subcommand completes, filtered by permission: a player who cannot run something is offered nothing for it.
• Passwords are never suggested. A command with no completer falls back to the server default, which suggests player names, so 2.x offered your players' names as password candidates.
• Vanish is respected. Players you cannot see are not listed.
• /untrust suggests only the players you actually trusted; /trust leaves out those you already have.
Smaller fixes
• Breaking your own [Private] sign said it was an admin action, because ownership was checked after the record had already been removed.
• /lockchest and /unlockchest used a hardcoded English message from console.
• Unresolvable player names in /trust list use a message key instead of a hardcoded word.
• A missing message key is logged with its name and shown as [key_name], instead of English prose.
Cleanup no longer deletes trust lists
2.x wiped a player's entire trusted list on every pass if they owned no containers at that moment. A player who ran /trust before locking their first container lost it within half an hour, and so did anyone who temporarily broke all their containers. Now off by default, and the rest is configurable instead of fixed in code:
Positions in unloaded chunks are never touched, on any setting.
Translation
Nothing shown to a player is hardcoded. These were baked into the code: the [Private] sign tag, container type names, "Unlimited", the hopper/dropper/dispenser names, the console-only refusal, the forbidden container names, and the missing-key placeholder.
Tag matching ignores case, colour codes and spaces. The aliases list lets you change language without invalidating signs your players already placed. Accented characters work in container names. The rule was a-zA-Z0-9, which rejected every accent, so players on a Spanish, French, German or Portuguese server could not use their own language. The default is now Unicode-aware and the whole rule is configurable, along with the forbidden word list. English and Spanish are bundled, in plugins/PrivateChest/lang/:
Previously an update always injected English into a translated file. With use-player-locale, missing entries fall back to messages.yml, so a partial translation is safe. Copy a file in lang/ to add a language. Nothing changes for a single-language server: messages.yml is still your file and your edits stand.
Known gap: copper golems
Copper golems (1.21.9+) carry items out of copper chests on their own. If your server reports that as a normal item transfer, existing protection already blocks it, since transfers involving a protected container are cancelled whatever starts them. If it is implemented purely as mob behaviour, there is no event to intercept and no plugin can stop it. This could not be verified, so it is not claimed as covered. Test it before relying on it. Also not included: a native Bedrock input form for passwords. Bedrock players use every feature by typing commands, and [Private] signs need no command at all.
New configuration
security, containers, container-names, language, use-player-locale, save-interval-seconds, and an expanded auto-cleanup. Every option is documented inline in config.yml.
New message keys
Added automatically, your existing wording kept:
Removed, because they could never be reached: limit_error, sign_not_your_chest. Reworded defaults, which your file keeps unless you delete the key: locked, not_your_chest, sign_chest_locked, the limit_* messages, and the access and break notices, all of which now support {container} and {owner}.
Compatibility
Minecraft
1.16.5 – 26.2
Java
8 or newer
Single-threaded
CraftBukkit, Spigot, Paper, Purpur, Pufferfish, forks
Regionised
Folia, Luminol, LightingLuminol, LeafMC, Kaiiju, forks
Cross-platform
Java and Bedrock, via Geyser and Floodgate
Release Date: 20/03/2026
Granular Command Permissions
privatechest.lock — Controls access to /lockchestprivatechest.unlock — Controls access to /unlockchestprivatechest.trust — Controls access to /trustprivatechest.untrust — Controls access to /untrustprivatechest.rename — Controls access to /renamecontainerprivatechest.sign — Controls access to [Private] sign-based lockingprivatechest.use now acts as a parent permission that grants all of the aboveprivatechest.sign) is independent from the command (privatechest.lock), so blocking /lockchest does not block [Private] signsShared Container Utility Class (ContainerUtils)
Explosion protection now covers both halves of double chests
EntityExplodeEvent and BlockExplodeEvent now check all container partsSign protection now uses its own permission (privatechest.sign)
/lockchest, meaning blocking the command also blocked [Private] signsprivatechest.sign permission, independent from privatechest.lockNull safety in ChestLocker.serializeLocation()
NullPointerException if a world was unloadedContainerUtils.serializeLocation() with proper null checksSign-based protection password is now cryptographically secure
hashCode() based on player UUID and location (predictable)SecureRandom to generate unpredictable 32-character hex passwordsThread Safety
ChestLocker: chestOwners and chestPasswords maps changed from HashMap to ConcurrentHashMapTrustManager: trustRelations map changed from HashMap to ConcurrentHashMap, inner sets use ConcurrentHashMap.newKeySet()ConcurrentModificationException when async cleanup runs alongside main thread operationsTiming-safe password comparison
PasswordManager.verifyPassword() now uses MessageDigest.isEqual() instead of String.equals()privatechest.use still grants all commands.# LuckPerms example — block only /lockchest but keep [Private] signs working
permissions:
- privatechest.lock: false
privatechest.use will continue to work identicallyThank you for using PrivateChest!
Release Date: January 2026
Minecraft: 1.16.5 - 1.21.x
Servers:
Cross-Platform:
No action required. Update and enjoy the new features!
hopper-protection: allow-hopper-access: true # Set to true to enable
/renamecontainer <name> or /renamecontainer remove/renamecontainer <name> - Set a custom name for the container you're looking at/renamecontainer remove - Remove the custom name from a containerAdd these to your config.yml if you want to customize the new features:
# Container-specific limits (optional)
container-limits:
enabled: false # Set to true to use granular limits
types:
chest: 10
barrel: 5
shulker_box: 2
# Automatic cleanup (enabled by default)
auto-cleanup:
periodic-enabled: trueprivatechest.limit.chest.X - Allows locking X chestsprivatechest.limit.barrel.X - Allows locking X barrelsprivatechest.limit.shulker_box.X - Allows locking X shulker boxesDownload PrivateChest v2.1 and enjoy enhanced security with powerful new features! 🎉
What's New
Enhanced Security
Trust System
Sign Protection
Chest Limits
⚡ Performance Improvements
Developer API
Migration from v1.x
✅ Fully Automatic Migration
Migration Steps:
⚙️ Configuration
New options in config.yml:
Permission Examples
# Chest Limits (when enabled)
privatechest.limit.unlimited # No limits
privatechest.limit.100 # Up to 100 chests
privatechest.limit.25 # Up to 25 chests
privatechest.limit.10 # Up to 10 chests
privatechest.limit.5 # Up to 5 chests
Compatible with Minecraft 1.16.x - 1.21.5 | Tested on Paper, Purpur, Pufferfish
This update focuses on fixing the long-standing double chest protection issue and brings several improvements to stability and usability.
/unlockchest), block breaking, and hopper interactions. This ensures complete protection for double chests and barrels./clearchests Logic: The /clearchests command now functions as intended, specifically targeting and removing only "orphaned" entries from data.yml (protections for containers that no longer exist or are invalid). It no longer affects valid, existing protections.DataManager: Added more robust error handling and console logging when loading data.yml. This will help server administrators diagnose issues with corrupted or invalid location entries.messages.yml: The messages.yml file will now automatically add any new message keys from future plugin updates, preserving existing user customizations.config.yml: Removed non-functional options (allow-double-chests, unlock-duration-seconds, allow-shared-access) to prevent confusion. Added clearer comments.messages.yml: Added new messages for recent changes, improved wording on existing ones, and added detailed comments to explain each message's purpose.plugin.yml: Corrected version number and added /pc as an alias for /privatechest.🚫 Hoppers can no longer extract items from any protected container.
🔐 Applies not only to chests and barrels, but automatically supports any future container types added to PrivateChest (like furnaces, droppers, shulkers, etc.).
🧠 Uses smart event handling via InventoryMoveItemEvent to detect and cancel unauthorized item transfers.
Protection now checks container ownership via ChestLocker.isChestLocked(...), ensuring consistent behavior.
No performance impact; event runs only when hoppers are in use.
Any server using hoppers, redstone automation, or container protection systems.
Servers upgrading from 1.6.1 or earlier.
Thank you for using PrivateChest Free!
If you find the plugin helpful, please consider leaving a ⭐ review or joining our support community.
Support available in English and Spanish.
📦 PrivateChest v1.6
🧹 New Feature: Smart Auto-Cleanup on Startup
• The plugin now detects and removes invalid chest entries from data.yml when the server starts.
• If a chest no longer exists in the world (e.g., was broken externally or by other plugins), it will be skipped and cleaned.
• Keep your data file clean and accurate without running manual cleanup commands.
🛠 Configurable Option:
• Toggle this behavior in `config.yml`:
auto-cleanup-on-start: true
📋 Console Feedback:
• [PrivateChest] Loaded locked chests: 48
• [PrivateChest] Auto-cleaned 3 invalid chest entries.
---
🌐 Multilingual Ready
• All messages and settings remain fully translatable via `messages.yml` and `config.yml`.
✅ Compatibility
• Minecraft Versions: 1.16.x → 1.21.5
• Supported Forks: Paper, Pufferfish, Purpur
📊 Plugin Statistics:
https://bstats.org/plugin/bukkit/PrivateChest
---
✨ Looking for More Power?
🔒 [PrivateChest Plus] is now available!
💎 Features include:
• Shared chest access with trusted players
• Timed auto-unlock
• GUI-based password input
• Holograms and visual effects
• Separate storage for Plus chests
• And much more...
Upgrade your protection system now 👉 [View Premium Version]
📦 PrivateChest v1.5
🆕 New Features:
✔️ Block Whitelist for Lockable Blocks
➤ You can now define which block types can be protected.
➤ Controlled via the new config section:
protectable-blocks:
- CHEST
- TRAPPED_CHEST
- BARREL
✔️ Player Feedback on Locked Chest Interactions
➤ Players who attempt to open a protected chest they don't own will now receive a configurable message.
➤ New config entry:
locked-chest-message: "&cThis chest is locked and you cannot open it."
📁 Configuration Changes:
• `config.yml` updated with new keys: `protectable-blocks` and `locked-chest-message`.
• Fully reloadable with `/privatechest reload`.
🌐 Multilingual Ready:
• All messages remain customizable in `messages.yml` and `config.yml`.
---
✨ **Looking for more power and features?**
🚀 [PrivateChest Plus is now available!]
Unlock premium features including:
✅ Shared chest access
✅ Timed auto-unlock
✅ GUI-based lock system
✅ Sounds and holograms
✅ And much more...
Level up your server protection with PrivateChest Plus!
---
✅ Fully tested on:
• Minecraft 1.16.x → 1.21.5
• Compatible with Paper, Purpur, Pufferfish
📊 Plugin stats: https://bstats.org/plugin/bukkit/PrivateChest
📦 PrivateChest v1.4
🆕 New: Public Developer API
• Introduced `PrivateChestAPI` under `me.tuplugin.privatechest.api`.
• Developers can now easily:
- Check if a block is locked ➔ `isLocked(Block)`
- Check if a player is the owner ➔ `isOwner(Block, Player)`
- Get the UUID of the owner ➔ `getOwner(Block)`
- Lock a block programmatically ➔ `lockBlock(Block, Player, String)`
- Unlock a block programmatically ➔ `unlockBlock(Block)`
• Static, safe, and ready for direct integration without touching internal classes!
📚 New: API Documentation
• Added a dedicated section in README.md showing how to use the PrivateChestAPI with examples.
🛠 Improvements:
• Better internal structure for future feature expansion.
• Clean and separated API to prevent future compatibility issues.
🌐 Multilingual Ready:
• All messages and configurations remain fully editable for translations!
✅ Tested and verified on:
• Minecraft 1.16.x → 1.21.5
• Paper, Pufferfish, Purpur forks
📊 Plugin Statistics:
• View anonymous plugin usage at: [bStats - PrivateChest](https://bstats.org/plugin/bukkit/PrivateChest)
---
🎯 Tip: Even though the plugin is in English by default, you can fully translate it by editing `messages.yml` and `config.yml`!
📦 PrivateChest v1.3
🆕 New Features:
✔ Added /clearchests command (Admin only)
↳ Automatically clears orphaned chest entries from data.yml if the chest no longer exists.
↳ Requires permission: privatechest.admin
✔ Added full prefix control in config.yml:
↳ New options:
- use-prefix: true/false
- prefix: "&7[&6PrivateChest&7] "
↳ Admins can now enable/disable or customize the plugin prefix easily.
🛠 Improvements:
• Messages.yml is now purely for messages, no longer holds prefix settings.
• Prefix changes and config updates are hot-reloadable using /privatechest reload.
• Internal optimizations for data and location handling.
• Cleaner Maven build with shaded and relocated bStats.
🌐 Multilingual Ready:
• While the plugin is by default in English, all messages are fully configurable.
• You can easily translate the plugin into any language by editing messages.yml and config.yml!
✅ Tested on:
• PaperMC 1.16.5 – 1.21.5
• Compatible with forks: Paper, Pufferfish, Purpur.
📊 View plugin usage stats at:
https://bstats.org/plugin/bukkit/PrivateChest
PrivateChest 1.2.1 - BugFix Update
Changes:
✅ Recommended for all users to update for full stability and proper metrics reporting.
Quick Summary:
Thank you for supporting PrivateChest!
If you enjoy the plugin, consider leaving a ⭐ on Spigot!
Have any issues? Feel free to report them!
PrivateChest v1.2
New Features:
✔ Added support for bStats! Now we can see anonymous stats like plugin usage and Minecraft versions.
✔ New admin command: /privatechest reload
↳ Allows reloading config.yml and messages.yml without restarting the server.
↳ Requires permission: privatechest.admin
Improvements:
• Internal code optimizations.
• Updated plugin metadata for better compatibility.
Bug Fixes:
• None in this release — everything is stable!
Permissions:
• privatechest.use → Allows use of /lockchest and /unlockchest
• privatechest.admin → Allows use of /privatechest reload
You can view usage statistics at:
https://bstats.org/plugin/bukkit/PrivateChest
✅ Tested on: Paper 1.16.5 – 1.21.5
✅ Update v1.1:
Added support for barrels (/lockchest now works on barrels too!)
Thanks for the feedback — more features coming soon!