https://github.com/lucacicada/VanillaSort
Minecraft chest sorting is a problem as old as the game itself. For fifteen years, players have been manually organising storage rooms, building elaborate hopper systems, memorising which chest holds which materials, and occasionally just giving up and throwing everything into a single double-chest until the chaos becomes unbearable. The server plugin ecosystem responded to this problem with a wave of sorting plugins, all of which share the same fundamental flaw: they feel like plugins. They feel like software bolted onto the outside of a game that was never designed to support them.
The typical sorting plugin requires a configuration file. You define categories. You map item types to chest labels. You place signs. You run commands. You learn a plugin-specific language of rules and filters. And after all of that, the system sorts items according to the rules you wrote — not according to where you actually put things.
Luca approached this problem differently. The question he asked was not "how do I sort items efficiently?" The question was: "how does a player already organise their storage naturally, and how do I reinforce that behaviour instead of replacing it?"
The answer became VanillaSort.
One trapped chest. One name in an anvil: Sorter. That is the entire setup.
Place the trapped chest anywhere in your storage room. Name it. Now whenever you close it, every item you put in gets automatically moved to whichever chest in the surrounding 15-block radius already holds the most of that item type.
That is all. No config. No commands. No categories. No signs. No learning curve.
The plugin works with your memory. You already know where your logs are — you put them there. You already know where your stone is. The next time you dump a mining haul into the Sorter chest, every oak log goes to the chest that already has oak logs, every cobblestone goes to the chest that already has cobblestone, every iron ore goes where your iron ore lives. The organisation you have built up over hours of play is exactly the organisation the plugin reinforces.
This is the insight. Not clever algorithms. Not config files. Not a smart system that decides where things should go. A system that observes where things already are and honours that.
The core logic lives in a single file: Plugin.java. It is 299 lines. The entire sorting mechanism is driven by a single InventoryCloseEvent listener — the moment a player closes the Sorter chest, it fires.
The event handler first validates the trigger: is this a trapped chest? Is its custom name Sorter? If not, return immediately. The plugin is completely invisible to every other inventory interaction in the game.
// Only allow trapped chests
if (chest.getBlock().getType() != Material.TRAPPED_CHEST) {
return;
}
// Only allow chests with a special custom name
if (!CUSTOM_SORTER_NAME.equals(chest.getCustomName())) {
return;
}
Then it scans the surrounding area for valid target containers — regular chests and barrels within the 15-block radius — using BlockFinder.java, a clean generic 3D block space iterator that walks a cubic bounding box and yields each block in sequence. No Bukkit API overhead for iterating nearby entities, no reflection — a straightforward custom iterator that scans X, Y, Z in nested order.
For each item in the Sorter chest, the target container list is sorted using a four-level comparator:
Collections.sort(targetContainers, (TargetContainer a, TargetContainer b) -> {
int materialAmountComparison = Long.compare(
b.getMaterialAmount(itemType),
a.getMaterialAmount(itemType)
);
// Get the one that has the most of this item type
if (materialAmountComparison != 0) {
return materialAmountComparison;
}
int occupiedSlotsComparison = Long.compare(
b.getOccupiedSlots(),
a.getOccupiedSlots()
);
// Get the one that has the most occupied slots
if (occupiedSlotsComparison != 0) {
return occupiedSlotsComparison;
}
int itemsAmountCountComparison = Long.compare(
b.getItemsAmountCount(),
a.getItemsAmountCount()
);
// Get the one that has the most item amount count
if (itemsAmountCountComparison != 0) {
return itemsAmountCountComparison;
}
// Get the closest one to the sorter chest
return Double.compare(
a.getContainer().getLocation().distanceSquared(chestLocation),
b.getContainer().getLocation().distanceSquared(chestLocation)
);
});
Once the best target is found, the item is added to that container's inventory using Bukkit's addItem() method, which handles partial stacks and overflow correctly. If the target is full, the comparator cascades to the next best option. If nowhere can accept the item, it stays in the Sorter chest.
The entire sorting pass for all items in the chest happens in a single synchronous tick, triggered by the close event. The player closes the chest and the items are gone — moved silently, without animation, without sound, without any feedback that software was involved. It feels like the game did it.
The genius of this implementation is not any single clever trick. It is the discipline of not doing more than necessary.
Most Minecraft plugins that touch inventories register listeners on InventoryClickEvent, InventoryDragEvent, and several other noisy events that fire constantly as players interact with any container anywhere on the server. VanillaSort listens to exactly one event — InventoryCloseEvent — and immediately discards every invocation that is not from its specific trapped chest. The performance footprint is essentially zero.
The BlockFinder class is a case study in clean separation of concerns. It knows nothing about sorting, nothing about Minecraft items, nothing about the plugin's purpose. It is a reusable 3D space iterator that takes a location, a radius, and an optional predicate, and yields blocks. The sorting logic in Plugin.java uses it without caring how the iteration works. These are the kinds of separations that matter — not architecture astronautics, but a genuine separation between "find blocks in space" and "decide what to do with them."
private void findNext() {
nextBlock = null;
while (currentX <= maxX) {
while (currentY <= maxY) {
while (currentZ <= maxZ) {
Block block = world.getBlockAt(currentX, currentY, currentZ);
currentZ++;
if (predicate == null || predicate.test(block)) {
nextBlock = block;
return;
}
}
currentZ = minZ;
currentY++;
}
currentY = minY;
currentX++;
}
}
The four-level comparator is the heart of the algorithm, and it is elegant because it encodes a human intuition rather than an abstract sorting rule. Humans who play Minecraft organise storage by item type. The comparator's first level directly captures that. The remaining levels are progressively more abstract tiebreakers that happen to produce sensible behaviour in edge cases — without the author needing to specify those edge cases explicitly.
There is a common confusion between things that are simple and things that are easy. Rich Hickey drew the distinction in Simple Made Easy: easy means familiar, close at hand, not far from what you already know; simple means not interleaved, not complex in the literal sense of twisted together. Most Minecraft sorting plugins are easy to find and hard to use — they are familiar software, but they interleave their logic with your gameplay. VanillaSort is neither immediately easy to discover nor simple in implementation, but it is simple in the sense that matters: it does not interleave itself with your play. It has one job, it does that job at exactly one moment, and then it disappears.
Steve Jobs said: "Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains." The Sorter chest is a mountain-mover. Players who use it do not think about it. They do not configure it. They do not learn its rules. They just play, and the chest does its quiet work when they close it.
Antoine de Saint-Exupéry wrote: "Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away." VanillaSort has nothing left to take away. One block type. One custom name. One event. One algorithm. Done.
The reason VanillaSort feels different from every other sorting plugin is not the algorithm — it is the interaction model. The plugin was designed to feel like a feature that Mojang forgot to ship. Notch could have added this. It fits the design language of vanilla Minecraft perfectly: a trapped chest has a clear in-game meaning (it triggers redstone), the anvil renaming system already exists, the 15-block radius is a natural spatial concept. Nothing in the setup requires knowledge that a modded server exists.
Players who discover VanillaSort often describe the same reaction: they close the Sorter chest for the first time and watch their storage room organise itself, and for a moment they wonder if they somehow missed this feature in the base game. That is the highest compliment a plugin can receive.
Most sorting mods break immersion. The interface is a command. The feedback is a chat message. The configuration is a YAML file that lives outside the game. VanillaSort has no interface, no feedback, and no configuration. The only artifact it leaves in the world is a trapped chest with a name — which is itself a Minecraft object, placed and named using Minecraft mechanics.
The source is at github.com/lucacicada/VanillaSort. Three Java files. 299 lines for the main plugin logic, 133 lines for the block iterator, and a small WorldAreaBlockIterator utility. The entire plugin compiles to a single JAR that any Spigot server can drop into its plugins folder.
The project was later renamed EasySort internally — an appropriate name, because the experience it creates is exactly that.