🗃 Ender Chest
OreoEssentials replaces the vanilla ender chest with a fully custom system. Every player gets a virtual ender chest that shows exactly as many slots as their rank deserves — the rest appear as locked red barrier slots. The chest can optionally sync across every server in your network (cross-server mode) so players keep the same inventory everywhere.
What Is This Module?
In vanilla Minecraft, every player gets exactly one ender chest size: 3 rows (27 slots). There is no way to give VIPs more slots. This module completely replaces that system.
When a player opens their ender chest (by right-clicking a physical ender chest block or by typing /ec),
OreoEssentials intercepts it and opens a virtual inventory instead.
This virtual inventory:
- Always shows 54 slots (6 full rows) visually.
- The first N slots are open (the player's allowed amount).
- The remaining slots show a red barrier item labelled "Locked slot" — they cannot be clicked.
- When the player closes the chest, contents are automatically saved to disk or MongoDB.
- Next time they open it, their items are loaded back into exactly the same slots.
/ec.
How It Works — Step by Step
Understanding the flow helps you configure it correctly. Here's exactly what happens when a player opens their ender chest:
/ec.
EnderChestListener catches the open event and cancels it immediately so the vanilla chest never shows.
InventoryCloseEvent fires. The plugin reads the top inventory, strips out any lock items, and saves the real items back to storage.
What happens if a player upgrades rank mid-session?
The slot count is resolved at the moment the chest is opened. If you give a player a new rank while they already have the chest open, their current session still uses the old slot count. They need to close and re-open the chest to get the new, larger size.
Quick Start — 4 Steps
This is the fastest path to a working setup. Full details follow further down.
Open the config file
Go to plugins/OreoEssentials/enderchests/enderchest.yml on your server.
Pick a sizing mode
Set permission-slots.enabled: true and rank-slots.enabled: false
(this is already the default). This means slot sizes are controlled by permission nodes
like oreo.tier.vip.
Set your slot values
Under permission-slots:, edit the keys and their slot counts.
For example: vip: 45, mvp: 54.
The key name becomes part of the permission node: oreo.tier.vip, oreo.tier.mvp.
Add permissions to LuckPerms groups
In LuckPerms, run:
/lp group vip permission set oreo.tier.vip true
/lp group mvp permission set oreo.tier.mvp true
Players in those groups now get the correct slot count automatically.
oreo.ec permission and type /ec in-game.
You should see a 6-row inventory with locked barrier slots beyond your allowed amount.
File Locations
| File | What It Does |
|---|---|
plugins/OreoEssentials/enderchests/enderchest.yml |
The main config. Controls slot sizes, which mode is active, and which rank/tier gets how many slots. |
plugins/OreoEssentials/enderchests.yml |
YAML storage only. This is where player ender chest data is stored when you are using the built-in YAML backend. Every player's items are serialised to Base64 and saved here. Do NOT edit this file manually — the data is binary-encoded. |
MongoDB collection <prefix>enderchest |
MongoDB storage only. If you have MongoDB configured in the main OreoEssentials config, player data goes here instead of the YAML file above. |
enderchest.yml — Full Breakdown
Here is the complete default config file with every line explained:
# OreoEssentials — Ender Chest configuration # Each row = 9 slots. Max is 54 (6 rows). # The highest matching value always wins if a player qualifies for multiple entries. # ── Permission-based slots ──────────────────────────────────────────────────── # Keys here map to the permission node "oreo.tier.<key>". # You must add those permissions to your LuckPerms groups manually. # e.g. "vip: 45" → requires "oreo.tier.vip" on the vip group in LuckPerms. permission-slots: enabled: true default: 27 vip: 45 mvp: 54 # ── LuckPerms group-based slots ─────────────────────────────────────────────── # Write your actual LuckPerms group names here. # No permissions to create or assign — the plugin checks group membership # directly via the LuckPerms API. Inherited groups are included. rank-slots: enabled: false default: 27 vip: 45 staff: 54
That is the entire config file. It is intentionally simple. Let's understand every single setting.
Permission-Slots Mode
This is the default mode. When permission-slots.enabled: true,
the plugin checks whether the player has certain Bukkit/LuckPerms permission nodes
to decide how many slots they get.
How the keys work
Every key you write under permission-slots: (except enabled and default)
becomes a permission node automatically. The formula is:
oreo.tier.<your-key>Example: If you write
vip: 45, the permission node is oreo.tier.vip.
You assign this node to a LuckPerms group. Any player in that group gets 45 slots. Let's trace through a real example:
permission-slots: enabled: true default: 27 # everyone gets at least 27 vip: 36 # oreo.tier.vip → 36 slots vip_plus: 45 # oreo.tier.vip_plus → 45 slots mvp: 54 # oreo.tier.mvp → 54 slots
The "default" key
default: 27 is a special key — it is not a permission node.
It is the fallback: if a player has no other tier permission, they still get this many slots.
Every player on the server gets at least default slots, no permission needed.
The "highest wins" rule
If a player has multiple tier permissions (e.g. they are in both a vip group
and a staff group), the plugin checks all of them and picks the highest slot count.
It never averages. It never uses the lowest. The biggest number always wins.
permission-slots: must be all
lowercase letters, numbers, underscores, or hyphens.
Spaces are not allowed. The permission node generated will be all lowercase.
So VIP: 45 creates oreo.tier.vip (lowercased).
Slot count rules
- Slots are clamped between 1 and 54. If you write
vip: 99, it becomes 54. - If you write
vip: 0, it becomes 1 (minimum). - Slot counts must be multiples of 9 for clean rows, but technically any value 1–54 works.
Rank-Slots Mode
When rank-slots.enabled: true, the plugin directly queries LuckPerms
to check which groups a player belongs to. You do not need to create any permission nodes —
you just write the group names directly in the config.
Why use this instead of permission-slots?
permission-slots
You manage custom permission nodes in LuckPerms.
More flexible — you can mix and match.
Works even without LuckPerms (any permission plugin).
rank-slots
You write group names directly.
No extra permissions to manage in LuckPerms.
Requires LuckPerms specifically (uses its Java API).
How to configure rank-slots
rank-slots: enabled: true default: 27 vip: 45 # must match the exact LuckPerms group name staff: 54 # "staff" group gets 54 slots mvp: 54 # "mvp" group also gets 54
The keys here are your exact LuckPerms group names (case-insensitive).
The plugin compares them in lowercase so VIP and vip are the same.
Inherited groups
LuckPerms supports group inheritance (one group inherits from another).
The plugin checks all inherited groups too, not just the player's primary group.
So if mvp inherits from vip, an MVP player gets the highest of both slot counts.
Can both modes be enabled at once?
Yes! You can set both permission-slots.enabled: true and
rank-slots.enabled: true simultaneously.
The plugin runs both checks and always picks the highest result from either source.
This is useful if you want to do most things via groups but have one special permission node for exceptional cases.
rank-slots,
the group lookup will silently return no groups and default slots will be used.
The plugin does not crash — it just falls back gracefully.
Choosing the Right Mode
| Feature | permission-slots | rank-slots |
|---|---|---|
| Requires LuckPerms? | No (works with any permission plugin) | Yes (uses LuckPerms API) |
| How you give the size | Give player the oreo.tier.X permission in LuckPerms |
Player just needs to be in the LuckPerms group named in the config |
| Extra permission nodes to manage | Yes — one per tier (e.g. oreo.tier.vip) |
None — group membership is all that matters |
| Works with temporary permissions (LuckPerms)? | Yes | Yes (checks active groups) |
| Inherited group awareness | N/A (it's a flat permission check) | Yes — inherited groups are included |
| Can both be active? | Yes — highest slot count from either source wins | |
permission-slots (the default).
It is simpler to reason about and works with any permissions plugin.
Switch to rank-slots if you want to avoid managing extra permission nodes.
Slot Size Reference
Slot counts should ideally be multiples of 9 so you get complete rows with no partial row at the bottom. Here are all valid row sizes:
| Slots | Rows | Use case suggestion |
|---|---|---|
9 | 1 row | Severely restricted (punishment / newcomer) |
18 | 2 rows | Restricted tier |
27 | 3 rows | Default (vanilla size) — everyone gets this |
36 | 4 rows | Donor Tier 1 / VIP |
45 | 5 rows | Donor Tier 2 / VIP+ |
54 | 6 rows | Maximum possible — MVP / Staff / Legendary |
Visual: 3 rows open (27 slots) + 3 rows locked
This is what a default player sees — 27 open slots (teal) and 27 locked slots (red barrier):
Teal = open (usable). Red = locked (barrier item, cannot place/take items).
default: 30 and it technically works —
30 slots will be open. But the 30th, 31st, 32nd slots in the 4th row will be open while slots
33–36 in that same row are locked, creating a visually odd partial row.
Stick to multiples of 9 for a clean look.
Setting Up LuckPerms — Permission Mode
If you are using permission-slots (the default), follow these steps.
Configure your tiers in enderchest.yml
Open plugins/OreoEssentials/enderchests/enderchest.yml and add your tiers:
permission-slots: enabled: true default: 27 vip: 36 vip_plus: 45 mvp: 54
Add the permissions to your LuckPerms groups
Run these commands in your server console or in-game:
# Give VIP group 36-slot permission /lp group vip permission set oreo.tier.vip true # Give VIP+ group 45-slot permission /lp group vip_plus permission set oreo.tier.vip_plus true # Give MVP group 54-slot permission /lp group mvp permission set oreo.tier.mvp true
Verify
Log in as a player in the VIP group and type /ec.
You should see 36 open slots and 18 locked slots.
Use /lp user <name> permission check oreo.tier.vip to confirm the permission is active.
default group (or whatever your lowest group is) a permission like
oreo.tier.default and map it to 27 slots.
But this is optional — the default: 27 setting already handles players with no tier permission.
Setting Up LuckPerms — Rank Mode
If you prefer rank-slots, no extra permission nodes are needed. Just match the config keys to your real group names.
Find your LuckPerms group names
Run /lp listgroups in-game to see all groups. Note the exact names.
Edit rank-slots in enderchest.yml
rank-slots: enabled: true default: 27 vip: 36 # must exactly match the LP group name elite: 45 # "elite" LP group → 45 slots legend: 54 # "legend" LP group → 54 slots staff: 54 # "staff" LP group → 54 slots
Disable permission-slots (optional)
If you only want rank-based sizing, also set permission-slots.enabled: false
so you do not accidentally give extra slots via the oreo.tier.* nodes.
Reload and test
Restart the server (or reload OreoEssentials if it supports hot-reload).
A player in the elite group should now get 45 slots.
VIP, vip, and Vip all match the LuckPerms group named vip.
Still, for clarity, write them in lowercase to match your LuckPerms group names exactly.
Commands
/ec — Open Your Ender Chest
| Detail | Value |
|---|---|
| Command | /ec |
| Alias | /enderchest |
| Permission | oreo.ec |
| Player only? | Yes — console cannot use this (there is no chest to open) |
| What it does | Opens the player's own virtual ender chest with the correct slot count for their rank. |
| Cross-server note | If cross-server mode is disabled, a yellow message appears: "Note: cross-server EC is disabled. This EC is local to this server." |
/ecsee <player> — View Any Player's Ender Chest
| Detail | Value |
|---|---|
| Command | /ecsee <player> |
| Aliases | None |
| Permission | oreo.ecsee |
| Player only? | Yes |
| Target player | Can be online, offline, or a UUID. Also supports cross-server PlayerDirectory lookup. |
| What it does | Opens the target player's ender chest for the admin to view and edit. When the admin closes the GUI, all changes are automatically saved to the target player's storage. If the target is online and has their chest open, their open GUI is updated in real time. |
| Tab completion | Shows online player names and cross-server names from PlayerDirectory. |
/ecsee SomeOfflinePlayer for a player who is not online.
The plugin looks up their UUID from Bukkit's cache or the cross-server PlayerDirectory.
You can add/remove items and everything saves correctly.
Physical Ender Chest Block
When a player right-clicks a physical ender chest block in the world, it also opens OreoEssentials' virtual chest
(not the vanilla one) — but only if cross-server mode is enabled.
When cross-server mode is off, the vanilla ender chest opens normally and the /ec command
opens the virtual one instead.
Permissions
| Permission Node | Default | Description |
|---|---|---|
oreo.ec |
true | Allows a player to use /ec to open their own ender chest. |
oreo.ecsee |
op | Allows an admin to use /ecsee <player> to view and edit any player's ender chest. |
oreo.tier.<key> |
manual |
Only used in permission-slots mode.
Replace <key> with the tier key from your config (e.g. oreo.tier.vip).
Grant this to a LuckPerms group to give that group the corresponding slot count.
Not needed at all for rank-slots mode.
|
Assigning permissions in LuckPerms
# Give the default group access to open their EC /lp group default permission set oreo.ec true # Give admins the ability to peek inside other players' chests /lp group admin permission set oreo.ecsee true # Give VIP players 45 slots (permission-slots mode) /lp group vip permission set oreo.tier.vip true
YAML Storage (Default)
If MongoDB is not configured in your main OreoEssentials config,
all ender chest data is saved to a single file:
plugins/OreoEssentials/enderchests.yml
What is stored
The file stores one entry per player UUID:
players: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx: rows: 3 # how many rows were used when this was last saved data: "BASE64DATA..." # binary-serialised ItemStack array, Base64 encoded updatedAt: 1715000000000 # Unix timestamp (milliseconds)
data field manually!
It is a Base64-encoded binary blob of Java-serialised ItemStack objects.
Editing it will corrupt the player's chest data.
If you need to clear a player's chest, delete their entire UUID block and save the file.
Data safety
- Data is saved synchronously every time a player closes the chest.
- If the file save fails, the player sees a red error message: "Failed to save your ender chest. Please contact an administrator."
- A warning is also printed to the console:
[EC] YAML save failed for <UUID>: ...
Upgrading slot size
The rows field stores how many rows were saved.
If you upgrade a player's slot count, the plugin reads all 6 rows worth of data (even if
previously only 3 rows were stored). The extra rows are simply empty.
Items are never lost when you expand a player's chest.
MongoDB Storage
When you have MongoDB configured in OreoEssentials' main config, the plugin uses it
for ender chest storage automatically.
Data is stored in the collection <prefix>enderchest
(e.g. if your prefix is oreo_, the collection is oreo_enderchest).
Document structure
// One document per player { _id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // player UUID as string rows: 3, data: "BASE64ENCODEDDATA...", updatedAt: 1715000000000 // Unix ms timestamp }
How saves work
The plugin uses an upsert operation: if the document for this UUID already exists, it is replaced entirely. If it does not exist yet, it is created. This is atomic — there is no risk of a half-written state.
YAML vs MongoDB — Comparison
| Feature | YAML (built-in) | MongoDB |
|---|---|---|
| Setup required | None — works out of the box | Requires MongoDB server + URI in main config |
| Data file location | plugins/OreoEssentials/enderchests.yml |
Collection <prefix>enderchest in your MongoDB |
| Performance (large servers) | Slower — whole file read/write per operation | Faster — single document upsert per player |
| Human-readable? | Partially (data field is still Base64 binary) | Same (data field is Base64) |
| Cross-server possible? | No — file is local to one server | Yes — all servers point to the same MongoDB |
| Backup | Copy the YAML file | Use mongodump or Atlas backups |
Admin Feature: /ecsee — View & Edit Any Player's Chest
/ecsee <player> is a powerful admin tool. It opens the target player's ender chest
inside a GUI for the admin. The admin can add items, remove items, move things around —
exactly like having the player's chest open themselves.
How saves work after editing
When the admin closes the GUI, the plugin:
- Reads all items from the GUI.
- Saves them to the target player's storage (YAML or MongoDB).
-
If the target player is online and has their chest open at the same moment:
- If the target is viewing their OreoEssentials virtual EC: their open inventory is updated instantly — they see the changes in real time without having to close and reopen.
- If they are viewing the vanilla ender chest (first 27 slots): the vanilla chest contents are updated immediately.
- Sends the admin the message: "Saved changes to <player>'s ender chest."
How player resolution works
You can provide the target player in three ways:
| Input | What the plugin tries |
|---|---|
Online player name (e.g. Steve) |
Looks up directly from online players on this server. |
UUID string (e.g. 550e8400-e29b-...) |
Parsed directly as a UUID — useful for players with name changes. |
| Offline player name |
First tries Bukkit's offline player cache. Then tries the cross-server PlayerDirectory (if configured).Finally falls back to Uuids.resolve() (Bukkit's mojang lookup cache).
|
Example: Giving items to a player
# Admin wants to put a diamond sword in a player's EC /ecsee PlayerName # GUI opens — admin places the sword in an empty slot # Admin closes the GUI # Console: "[EC] Saved 1 items for PlayerName" # The player's next /ec shows the sword
Cross-Server Mode
When cross-server mode is enabled in OreoEssentials' main config, the ender chest module stores data in MongoDB (which all servers in your network share). This means a player can open their ender chest on Server A, take items out, switch to Server B, and their chest is still correct.
What cross-server mode changes
- Physical ender chest blocks are intercepted: When a player right-clicks an ender chest block, the event is cancelled and the virtual EC opens instead. Without cross-server mode, the block opens the vanilla chest normally.
- A message is shown: Players see "Opening your cross-server ender chest..." when the virtual chest opens from a block click.
- Storage must be MongoDB: YAML is per-server, so cross-server requires MongoDB. Make sure your MongoDB URI is configured in OreoEssentials' main config.
Local-only mode
If cross-server mode is disabled, players get a local chest only.
When they type /ec, a yellow note appears:
"Note: cross-server EC is disabled. This EC is local to this server."
Physical ender chest blocks open the vanilla chest as normal.
Locked Slots — How the Barrier Works
Slots beyond the player's allowed count are filled with a special BARRIER item (the red no-entry-sign block). This is not a real barrier block — it is just used as a GUI filler item.
Technical details
- The barrier item has a persistent data tag (
ec_locked) set to1on its ItemMeta. This is how the plugin recognises it as a lock item — not just by material type. - The item's display name comes from the lang key
enderchest.gui.locked-slot-name(default: "&cLocked slot"). - The lore comes from
enderchest.gui.locked-slot-loreand supports the placeholder%slots%which shows the player's current allowed slot count. - Clicking a locked slot is cancelled — both direct clicks and drag events. Shift-clicking from the player's inventory into the chest only works if there is free space in the allowed area. If there is no space, the shift-click is cancelled.
- Placing the lock barrier item itself is also blocked. If somehow a player had a copy of the barrier with the lock tag, they could not place it in the chest.
Customising locked slot text
To change the locked slot name or lore, edit your OreoEssentials lang file and set:
enderchest.gui.locked-slot-name: "&cLocked slot" enderchest.gui.locked-slot-lore: - "&7You have &e%slots% &7slots." - "&7Upgrade your rank to unlock more!"
Full Example — Permission-Slots (Rank Tiers)
This is a complete, copy-paste ready setup for a server with 4 donor tiers. The default group gets 27 slots; each paid tier unlocks more.
1. enderchest.yml
permission-slots: enabled: true default: 27 # all non-donors get 3 rows iron: 36 # oreo.tier.iron → 4 rows gold: 45 # oreo.tier.gold → 5 rows diamond: 54 # oreo.tier.diamond → 6 rows (max) rank-slots: enabled: false # not using group mode default: 27
2. LuckPerms commands
# Everyone can open their EC /lp group default permission set oreo.ec true # Iron donors /lp group iron permission set oreo.tier.iron true # Gold donors /lp group gold permission set oreo.tier.gold true # Diamond donors /lp group diamond permission set oreo.tier.diamond true # Admins can view/edit any chest /lp group admin permission set oreo.ecsee true
3. What players see
| LuckPerms group | Slots open | Rows open | Rows locked |
|---|---|---|---|
default | 27 | 3 | 3 |
iron | 36 | 4 | 2 |
gold | 45 | 5 | 1 |
diamond | 54 | 6 | 0 (fully open!) |
Full Example — Rank-Slots (LuckPerms Groups)
Same result as above, but using the rank-slots mode.
No extra permission nodes to manage in LuckPerms.
1. enderchest.yml
permission-slots: enabled: false # disabled — using rank-slots instead default: 27 rank-slots: enabled: true default: 27 # everyone not in any listed group gets 3 rows iron: 36 # players in LP group "iron" get 4 rows gold: 45 # players in LP group "gold" get 5 rows diamond: 54 # players in LP group "diamond" get 6 rows
2. LuckPerms commands
# Just the /ec command and admin ecsee — no tier nodes needed! /lp group default permission set oreo.ec true /lp group admin permission set oreo.ecsee true # Players just need to be in their group — no extra permissions # /lp user Steve parent set iron ← this is all that's needed
Behaviour with inherited groups
Say your LuckPerms groups have this inheritance: diamond → gold → iron → default
(diamond inherits all parents).
A player in the diamond group technically also inherits iron and gold.
The plugin sees all three and picks the highest — 54 slots. Correct.
Frequently Asked Questions
Q: A player's items disappeared from their ender chest. What happened?
This almost always means the server crashed while they had the chest open. Items are only saved when the chest closes. If the server goes down hard (not a clean shutdown), the close event never fires and changes since the last open are lost. To prevent this, consider using MongoDB (it persists to disk independently) and enabling regular server save intervals.
Q: I changed a player's rank but their slot count didn't change.
The slot count is resolved when the chest is opened. If the player had the chest open when you changed their rank, they need to close and reopen it. After that, the new size takes effect immediately.
Q: Can I reduce a player's slot count (downgrade)?
Yes, but items are never deleted automatically.
If a player had 54 slots and you downgrade them to 27, the next time they open the chest
they will only see the first 27 slots as open — but all 54 slots of data are still stored.
Items in slots 28–54 are "invisible" and can only be accessed by an admin with /ecsee.
If you re-upgrade them to 54 later, their items will still be there.
Q: How do I completely wipe a player's ender chest?
YAML mode: Open enderchests.yml, find the UUID block for that player, delete it, and save.
Restart the server or reload the plugin.
MongoDB mode: Delete the document with that player's UUID as _id
from the oreo_enderchest collection.
Q: Can two players on different servers have their ECs open at the same time?
Yes — but the same player cannot be on two servers at once (BungeeCord doesn't allow it).
If one admin is using /ecsee on Server A and the player opens their chest on Server B,
the last one to close wins. This edge case is rare and typically harmless.
Q: Does this affect the vanilla ender chest blocks in the world?
In cross-server mode: Yes — physical ender chest blocks are intercepted.
The virtual chest opens instead of the vanilla one.
In local mode: Physical blocks open the vanilla chest (unmodified).
Only /ec opens the virtual chest.
Q: The locked slot items show "Locked slot" in red. Can I change that text?
Yes. Edit your lang file (usually plugins/OreoEssentials/lang/messages.yml or similar)
and set enderchest.gui.locked-slot-name and enderchest.gui.locked-slot-lore.
The lore supports the %slots% placeholder.
Q: What if I set a tier to a number that is not a multiple of 9, like 30?
It works. Slots 0–29 are open, slots 30–53 are locked. The 4th row will have 3 open slots followed by 6 locked slots. It looks odd visually. Stick to 9, 18, 27, 36, 45, or 54 for clean full rows.
Q: Is there a reload command?
The enderchest module does not expose a standalone /ecreload command.
Use OreoEssentials' global reload command if one exists, or restart the server to pick up
config changes in enderchest.yml.
Q: Can I use both permission-slots and rank-slots at once?
Yes. Enable both. The plugin runs both checks and takes the highest result. This is useful for special cases, e.g. giving a staff member extra slots via a permission node without changing their LuckPerms rank.
Q: The /ecsee GUI title shows the player's name. Can I change it?
The title comes from the lang key ecsee.gui.title
(default: "<dark_purple>Ender Chest</dark_purple> <gray>(%player%)</gray>").
Edit that key in your lang file to change it. %player% is replaced with the target player's name.