Minecraft XP Banking

For a while now I’ve used the XPKeeper Bukkit plugin by eccentric_nz on my multiplayer Minecraft worlds to provide some form of “XP banking”.

I’m now in the process of replacing XPKeeper with my own xpbank data pack which I’ve written as a replacement capable of functioning with a vanilla Minecraft server. It’s been an interesting foray into data pack creation as a form of programming within the bounds of the vanilla game.

The general background

For those unaware, XP (or experience points) in Minecraft are collected when the player takes certain actions, such as killing monsters, trading with villages, or smelting ore. XP can then be used to enchant or repair armour and tools. A good amount of XP is required – a high-level enchantment can require up to 1395 XP (the equivalent of killing over 280 zombies).  However, when you die, you lose (the vast majority of) the XP you’ve collected.

Plugins like this are not supported on vanilla Minecraft, which is why I normally rely on third-party Minecraft server software such as Bukkit or Spigot for my multiplayer servers.

XP banking plugins let you keep your XP safe by depositing the XP you have. Thus, when you die in-game, you only lose the XP you had not yet banked.

So, what exactly is XPKeeper?

XPKeeper is an XP banking plugin which is based around a sign which you interact with by either left- or right-clicking to either deposit or withdraw XP. The sign also displays your balance to the world, and also doesn’t particularly look nice.

An XPKeeper sign showing stwalkerster at Level 26 with 14 XP

It’s a bit of a hacky solution to a problem, especially in modern Minecraft where tools like the scoreboard, command blocks, and data packs are a thing.

To be completely fair, this plugin has been around for ages – well before the introduction of things like data packs. According to it’s page on the Bukkit site, it was first released in September 2012, which would put it around the Minecraft 1.3 era – around the same time as emeralds and the Ender Chest were introduced. Command blocks wouldn’t even be introduced until Minecraft 1.4.

So, time for an update? Yes, though I will admit this is motivated not by the seniority or good looks of the XPKeeper plugin, but more towards my own growth as a more technical Minecraft player. Some of the more interesting farms I’ve been working on have made ample use of item mechanics, especially while working in the Nether and thus using techniques such as pistons, slime blocks, packed ice, and glazed terracotta to punt items around where I’d normally use a water stream.

Bukkit/Spigot’s optimisations excessively interfere with the mechanics of item movement, and this effectively destroys the farms I’ve been building, testing and perfecting on local testing worlds. The mechanics introduced by Spigot are unpredictable and thus generally non-conducive to building reliable farms.

The new data pack

xpbank is my brand new data pack for 1.17[b] which allows you to deposit and withdraw XP. It’s primary user interface is either three functions which can be called from a command block (in the premise of a server operator-configured bank branch), or via triggers which can be called from anywhere (in other words “mobile banking”).

I’m not a huge fan of the mobile banking approach from a game balance perspective, but for a quick migration I’ve decided to go with that approach on my current server in the short term. Once we’ve built a bank, we can turn off the mobile banking commands.

Everything is done via these functions, and everything is stored as scoreboard objectives. This means you can even display everyone’s current balance in the scoreboard sidebar if you choose!

It also means there’s no prescribed user interface to the banking systems other than generating a redstone signal. You can build a large banking hall with pressure plates to trigger the data pack, or even have no visible indications that it even exists at all if you use mobile banking.

Three command blocks with signs on top

So, how do I use it?

The most up-to-date instructions will be on the data pack’s GitHub repository – here: https://github.com/stwalkerster/minecraft-xpbank/blob/master/README.md

Once you’ve installed it, you can run /trigger xpb_deposit one or more times in the game chat to deposit your XP. By default, this will deposit all your XP points down to the next level, plus one level, but it can be configured to take more than one level at once if you prefer.

When you want to reclaim your XP, run /trigger xpb_withdraw one or more times to get your XP back in chunks.

To see your current balance, you can run /trigger xpb_balance.

For server operators, you can call the xpbank:balance, xpbank:deposit, and xpbank:withdraw functions from a command block with the execution context set to the relevant (presumably the nearest) player. For example, for a balance enquiry command block, you’d set the command to run to be execute as @p run function xpbank:balance.

Details on the relevant configuration settings can be found on the README linked above.

Future work?

Definitely. What I’ve done so far is a working minimum viable product, and I’d definitely like to expand on it. I’ve not got any immediate plans to do work without real play testing, and I plan to get some play testing done on my current Minecraft multiplayer server.

On the horizon I can foresee a few enhancements though:

  • Customisable withdrawal amounts
  • Per-user customisable deposit and withdrawal amounts
  • Dynamic support for displaying more levels above level 200.[a]
  • Configurable minimum deposit value (for example, you can only bank your XP when you have more than 10 levels)

I’m perfectly happy to accept code changes, tweaks, new functionality, bugfixes, etc from others if you want to get involved.

The code in the data pack is licenced under the MIT licence, so you’re free to do what you want with it as long as you keep the copyright notice and thus credit to me intact.


  1. Currently, conversion from a total XP value to a level is done via a massive lookup table. Naturally, this is… unpleasant… to maintain (not to mention giving me /r/badcode vibes). Unfortunately, the conversion requires solving a quadratic equation, which requires a square root function… which Minecraft currently lacks. I feel approximating a square root will be prone to subtle conversion errors, which will lead to a bunch of bug reports and a feeling of general unreliability – something I don’t want in a banking tool. The alternative is a square root lookup table, but that’s probably just as bad as a lookup table for the end result.
  2. Yes, I’m aware Minecraft 1.18 is near to release. I do plan to update the datapack for 1.18 once it’s released, though I don’t anticipate any changes will be required.