MC 1.13 - Server side modding - new blocks?

Discussion in 'Spigot Discussion' started by sirati97, Feb 20, 2018.


What do you think?

  1. I am interested in helping

  2. I am interested in using this later

  3. I think no one ever wants to add new blocks or items

  1. Hello,
    I am looking forward to the technical update part of Minecraft 1.13. In the past, I have often worked in the NMS environment and thus know very well how the internals of a Minecraft server work. I cannot promise anything yet, but I believe it might be possible to introduce new blocks and items server-side without requiring a modded client. This heavily depends on how it is implemented and which consistency checks the client makes. It is definitely possible. The question just is how efficiently can it be done and is it efficient enough to deliver the same experience as server-software not offering this feature. This is what I like to explore and hopefully also implement. However, I am a uni student and time is spare, and I cannot really do it alone or without people motivating the heck out of me.

    This may be a bit blunt, but I want to avoid some negative answers to this thread (for my sanity). I have put a massive amount of thought into this over the past four years and if you come up with a possible issue I probably already have sorted it out. So please check the following list and if this even remotely covers what you are about to say really think if its wise to say it. Actual content continues afterwards.
    Sadly I had to deal with all those points before when discussing with people about this on discord or here on the IRC. And I just cannot deal with this negative and ignorant attitude
    All packets reaching the client will only contain NBT that the client is able to process.
    Yes obviously. This is a server-side mod.
    No, it is not. While the Bukkit API is a great API, it is build to support plugins that allow modifying game mechanics as well as managing the game. While this in a way indirectly leads to new game content, it is not the same as straight out adding new content like blocks and items. With lots of hacking this can indeed be simulated with the Bukkit API, but this will always be highly inefficient, hard to maintain and easy to break.

    Further details regarding this are available in their own points
    To a very limited extent, this is true and has been done. Anyhow, this requires one to listen to every event regarding items and thus is inefficient. (You need to make string comparisons each time. Most events are for other items just increasing the overhead.) As soon as you try to add more complex items as backpacks this hack just blows up and becomes unfixable:

    One can store the content hidden as colour codes in the lore. This is very inefficient as you need 4 bytes (2 characters) to represent 4 bits. You need to send every update to the client (otherwise creative mode just breaks it completely) which could potentially generate lots of traffic.

    So you opt for an id system with a database. JUst be ready for lots of dead entries:
    - oops, a world got deleted
    - oops, forgot to listen to despawning items
    - oops, there are ways items get destroyed that doesn't fire an event to listen to.
    - oops, world edit deleted a chest with your item
    - oops, a player did not join the server for ages, so another plugin deleted the player's inventory.

    If you try to fix it, you just make it worse. Now people will suddenly have empty backpacks and will cry leave your server. You want me to elaborate on that too? No? Yes? arggg
    - Matching the inventory id with a last used timestamp doesn't work: A player puts his backpack in a chest and just forgets about it. A year later it's suddenly empty.
    - Matching the inventory id with the player UUID also doesn't work: his friend only ever used the backpack and puts it in a check. The player did not open the chest for a year when he finally wants to use it its content is gone.
    - and so on

    If you are fine with any of these, you are just a horrible person. And btw, did you see how much effort you need to put into fixing weird bugs that should never have been a bug in the first place. For something as simplistic as a fucking backpack. Do you see how much of an awful hack your creation is? So no. just don't ever consider this. Just put that dev power into developing my fork, and you will make everyone happier and avoid such awful code

    If you have another example. It's just the same story, so please don't.
    No, it won't. I have done with before. I know how the NMS code looks like. So no it won't.
    In current versions of Minecraft, a creative player can say an arbitrary item with arbitrary NBT exists inside of its inventory. This can lead to three problems:
    1. Items getting destroyed because the Minecraft client replaced it with what it sees. - Just have some NBT clues what item the player actually is holding. This is also good if anyone wants to make a clientside mod to give the new items new textures.
    2. Lots of object instances created when decoding an item packet received from a player. Just treat these items differently replace them we the real server-side instance as soon as possible.
    3. Security-critical items like 'mobile command blocks' can be used to get op. Yes, this is an issue. I recommend mod programmers to just not make such an item as this solves this problem. In case they still want to do it, just check incoming data okay?
    Yes totally. That is why it is done on top of Spigot. Just as spigot is done on top of Craftbukkit. Maybe if we are done, and it turns out that our performance is as good as the original and it's implemented super neat one can think about merging it into spigot
    I am. You are not able to judge that,
    Goot point. However, most plugins also rely on more than just Bukkit. (Why? Because Bukkit does only offer the most essential APIs). So all implementations of the Bukkit API only allow a small fraction of Plugins to actually run on those platforms.
    Why not just use Sponge? Sponge Vanilla does not allow you to add new blocks or items. Sponge Forge requires Forge with is not an unmodded client.

    Also, this API will hopefully offer an API that does not require mods to ever use NMS. So it might be easy to also implement this API for Sponge and Forge.
    Let's hope this is enough and I do not need to add any

    What is the goal of this project:
    1. to create a Spigot fork which offers a separate API, extending and supplementing the Bukkit API. Easily allowing mods to add their own blocks, items, enchantments, potions (this probably requires an NMS inventory API (but again independent of NMS)
    2. To make full use of the abstractions done in Minecraft 1.13
    3. to stay 100% compatible with vanilla Spigot and Bukkit plug-ins
    4. to be completely version independent. Mods/Plug-ins using this API will not require to update after a Minecraft update
    5. little to no overhead
    6. Have APIs for things like NBT without actually exposing NBT. Also, this API will only be used to save states of new items in a very abstract manner. Exposing NBT in any other way is very bad and I totally agree with MD5 here.
    7. Reuse as much code from my earlier attempt making it pretty straightforward

    So you seem to have a pretty good plan. Why do you not just make it and release it?
    - I am at university. studying two subjects at the same time: Physics and Japanese. Basically, I do not have much time. That said I will have enough time to work on the project together with others. Also, I generally think that such a project should not be done alone. Multiple minds will have different insights and will ensure that such an API is as usable and efficient as possible. So please if you are interested in helping, drop me a message or join this discord. If you cannot program, it is still fine. We need people to test stuff and find bugs. If you can program then you can help program. Please note tho that you need to know how to program, which includes having a deep understanding of Java and OOP. If you do not know NMS or Bukkit well that's fine. You will just need some time where you can read the code of it and develop some understanding. That's how everyone gets there.

    Do not forget that it's also really important for us to get feedback. If you want to program using this API please also join our discord. There we can inform you about releases and you ask questions about the API.

    So if you have not read my frequent concerns sections (which I hope you haven't, because I am not the politest in there. But it's probably also entertaining to read tho idk) then you do not know about this yet. I have actually implemented a big chunk of this already and it is working and ready to be demonstrated. You can read about it here, just keep in mind that not all links and pictures work - I forgot to pay my server and they formatted it. Anyhow, I am able to give you some code demonstrations. Obviously only for items, because blocks and stuff will only become possibly with 1.13.

    Code Examples:

    Item API:
    Code (
    public class BasicExampleItem extends OilItem { //Base class for all modded Items (Items=/=ItemStacks)

        public BasicExampleItem(OilKey key) {
            super(key, Material.STICK, 0, 2, "Basic Example Item");
            //VanillaSees=Material.STICK, MaterialData=0, MaxStackSize=2, DisplayName="Basic Example Item"

        public boolean onUseOnBlock(OilItemStack itemStack, Player player, Action action, Block blockClicked, BlockFace blockFace) {
            Block block = blockClicked.getRelative(blockFace);
            if (block.getType().equals(Material.AIR)) {
                block.setType(Material.FIRE); //will set the clicked block face on fire
            return true;
    Code (
    public class ExamplePlugin  extends JavaPlugin{
        private OilMod mod;
        private ItemRegistry itemRegistry;

        public void onEnable() {
            mod = new OilMod("example_mod", "Example Mod");
            itemRegistry = new ItemRegistry(mod);
            itemRegistry.register(new BasicExampleItem(mod.createKey("basic_example_item")));
    Code (
    public class BackpackItem extends OilItemBase<BackpackItemStack> {

        public BackpackItem() {
            super(Material.LEATHER, 0, "Backpack", 1, "Backpack"); //defines Backpack item
            //Material=Material.LEATHER, MaterialData=0, ItemIdentifer="Backpack", MaxStackSize=1, DisplayName="Backpack"

        public BackpackItemStack createOilItemStackInstance(NMSItemStack nmsItemStack) {
            return new BackpackItemStack(nmsItemStack, this);
           //Uses custom itemstack class (for handling nbt/the inventory)
    Code (
    public class BackpackItemStack extends OilItemStack {
        private final ModInventoryObject inventory;

        public BackpackItemStack(NMSItemStack nmsItemStack, BackpackItem item) {
            super(nmsItemStack, item);
            //Creates inventory attached to itemstack
            inventory = InventoryFactoryBase.getInstance().createBasicInventory("inv", this, 27, "Backpack", PortableInventoryFilter.INSTANCE, true);

        public BackpackItem getItem() {
            return (BackpackItem) super.getItem();

        public boolean onUse(Player player, Action action) {
            player.openInventory(inventory.getBukkitInventory()); //onUse event - opens inventory
            return true; //suppress normal minecraft actions
    Code (
    public class PortableInventoryFilter implements ItemFilter {
        public final static PortableInventoryFilter INSTANCE = new PortableInventoryFilter();
        public boolean allowed(ItemStack itemStack) {
            if (itemStack instanceof OilBukkitItemStack) {
                OilItemStack oilItemStack = ((OilBukkitItemStack) itemStack).getOilItemStack();
                return !(oilItemStack instanceof BackpackItemStack);
                //Will disallow you to add an Backpack to inventories using this filter
            return true;
    Code (
    public class ExamplePlugin extends JavaPlugin {
        private ItemRegistry itemRegistry;

        public void onEnable() {
            itemRegistry = new ItemRegistry("exampleMod");
            itemRegistry.register(new BackpackItem());

    UI / Container API:
    Code (
    public class InvseeUIBuilder extends UserInterfaceBuilder<InvseeUIBuilder.InvseeArgument> {

        public void displayNewUI(Player player, Player other) {
            displayNewUI(player, new InvseeArgument(other));
            //will called protected method with player as argument

        protected UserInterface buildDisplay(Player player, InvseeArgument argument, UserInterfaceFactory userInterfaceFactory) {
            Player other = argument.other;
            UserInterface ui = userInterfaceFactory.createChestInterface(player, this, other.getName() + "'s Inv", 5);
            //player=player, builder=this, name=other.getName() + "'s Inv", rows=5
            UIPanel playerPanel = ui.createPlayerPanel(true, false, false, true);
            //hotbarPosSwitched=true, displayArmor=false, displayOffhand=false, filterItems=true
            UIPanel otherPanel = ui.createPlayerPanel(other, false, true, true, true);
            //player=other, hotbarPosSwitched=false, displayArmor=true, displayOffhand=true, filterItems=true
            ui.showPanel(playerPanel, otherPanel);
            //displays playerPanel at the buttom and otherPanel at the top
            return ui;

        protected static class InvseeArgument implements UIArgument { //created argument container for InvseeUIBuilder
            public final Player other;

            public InvseeArgument(Player other) {
                this.other = other;
    Code (
    public class InvseeCommand implements CommandExecutor {
        private InvseeUIBuilder invseeUIBuilder = new InvseeUIBuilder();

        public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args) {
            if (commandSender instanceof Player) {
                Player player = (Player) commandSender;
                if (args.length != 1) {
                    player.sendMessage(ChatColor.RED + "/"+label + " <player>");
                } else {
                    Player other = Bukkit.getPlayer(args[0]);
                    if (other == null) {
                        player.sendMessage(ChatColor.RED + "Cannot find player with name " + args[0]);
                    } else if (player == other) {
                        player.sendMessage(ChatColor.RED + "You must not look into your own inventory");
                        //prevents item duplication - nms bug
                    } else {
                        invseeUIBuilder.displayNewUI(player, other);
            } else {
                commandSender.sendMessage(ChatColor.RED + "This command can only be executed by players.");
            return true;
    Code (
    public class ExamplePlugin extends JavaPlugin {
        public void onEnable() {
            getCommand("invsee").setExecutor(new InvseeCommand());
    Compare the result with the code:

    Or check out the Test-Plugin I used before
    #1 sirati97, Feb 20, 2018
    Last edited: Mar 6, 2018
    • Informative Informative x 1
  2. MiniDigger


    This is interesting.
    I still think that the Bukkit API is completely unable to handle mods, so creating compatibility with plugins will be the hardest part of this project.
    How would an plugin check if the player just found a backpack when all the Bukkit Apis sees is a leather item stack? You could offer methods into your API, but that would mean that every plugin would need to add support manually. Sponges key based systems (while having their own problems) are well better suited for that.
    The other goals seem reasonable, there are already many spigot forks, setting up a new one is fairly easy (just copy paste papers build system, as that's the best).

    I still think that this is overkill tho. The issue you said you have with using the Bukkit API is that you lack a clear identifier for items. If you found out a good way to handle that with nms, you can just expose that identifier to the end user and he can just continue to use the normal Bukkit events, as they allow you to do most stuff you would want already.

    So yeah, I will prolly not contribute till the project gets a bit movement and only lurk around and leave feedback, as my free time is occupied with my own projects, but this is still an interesting project.

  3. There are multiple options.
    -We can do what mcpc+/cautroun did and just show bukkit that it is a modded item. Basically, an material that is not in the standard Material enum. Dunno how they did that, but I assume the answer is reflection.
    -We can show Bukkit the same random item for every modded item.
    -We can show Bukkit the item that the vanilla client would see (In this case this might require the mod to implement some bukkit apis for the custom item or accept that if the plugin threats the item as the item it sees it might crash)

    It's important to note that I use Bukkit for everything that Bukkit can efficiently be used for. Basically, OilMod is an extension of the Bukkit API allowing for low-level changes and low-level control while still being as high level and versionless as Bukkit.
    #3 sirati97, Feb 20, 2018
    Last edited: Feb 21, 2018
  4. Just add a nms tag to the item with the modded item id. No need for build to know that it is modded, you can handle that yourself.

    Store the backpack content in NBT tags too.
    #4 Jalau, Feb 21, 2018
    Last edited: Feb 21, 2018
  5. Yes, that is what is being done currently.
    #5 sirati97, Feb 21, 2018
    Last edited: Feb 21, 2018
  6. This would be much nicer than the current Slime Fun and Exotic Garden Plugins! I'm a big fan of Forge Mods but getting Players to modify there clients is always a hassle.
  7. This is one of my main motivation behind this. Give devs more tools that are noninvasive to the user experience.
    Obviously, this will never become something as big as forge or support forge mods. However, it will still provide some of the most necessary tools for modding and hopefully also a very easy to work with API.
    • Like Like x 1
  8. So to summarize/clarify, this just adds an abstraction layer over NBT data or what so that you can treat a vanilla item like it's a different item. And the client (if it has no special resource pack and refuses server packs) still sees a default normal vanilla item with extra lore and some hidden NBT stacks which could in theory be read out by some client side mod? Amirite?
  9. not really, we do not expose NBT directly to plug-ins. However, there are classes provided to attach arbitrary data to a modded item (not to vanilla items). This NBT is only used to, for example, store the content of a backpack.

    For example, here ModInventoryObject is all that the mod sees and only at NMS layer to actual logic of saving and loading items from/to nbt is realised.

    To NMS this will look just as a vanilla item. Server-side those are new items. This is done by deriving and modifying some NMS classes which the implement the OilMod API (an API like Bukkit)

    Yes. This is unavoidable because of the way creative mode works. I do not see this as a bad thing tho.
    • Informative Informative x 1
  10. Maybe this will finally be an incentive for people to update from 1.12 (though if the new blocks in 1.9 - 1.12 didn't encourage them then all hope is lost).
    • Funny Funny x 1
  11. I had one of those PvP servers relying on pre 1.9 PVP. If I ever reopen that I would use modern Minecraft and use some trickery to still have the old PVP mechanics.
    • Agree Agree x 1
  12. Progress update:
    I got my old code running on 1.12.
    Modded items: semistable/stable
    Crafting: unstable
    Inventory and UI api: semistable

    Please check out how the current api looks like and give me feedback:
    Please note that the UI api is going to be completely redesigned


    The next step is to change how I implement modded items nms wise. Currently, i use an itemstack based method which I would consider a hack. In the future modded items are going to be implemented just like vanilla items: by being added to the item registry.The next step is to change how I implement modded items nms wise. Currently, i use an item stack based method which I would consider a hack. In the future modded items are going to be implemented just as vanilla items.
    #12 sirati97, Mar 3, 2018
    Last edited: Mar 3, 2018
  13. You could do it like CustomUtils does it, If I understand you right.....
  14. I looked into it. What this mod is doing is very different. It adds new items and blocks to the game, just like forge would do, but only communicates information to the client that the client can understand.
    CustomUtils, on the other hand, uses already available features in the game to make mob spawners look like they have a custom texture. This is a nice trick and could be used to give blocks of this mod a custom texture in theory. However, there are a couple problems with this:
    - it requires a tile entity for every custom texture block (tile entities take a lot of bandwidth compared to normal blocks, and create lag)
    - it requires the uploading of a texture pack
    - people need to accept the texture pack otherwise the blocks are just see through
    - mod spawners lose their texture
    Imagine generating a custom ore. Now the client has a couple hundred tile entities in each chuck

    Oilmod only focuses on server-side. So it won't implement it. However, it is certainly possible for a plugin to come along and do this for oilmod mods.
  15. Mob spawner won't lose their textures afaik. Furthermore based on the client and whether it uses the resources you could alter packets.
  16. I am pretty sure there is no way to use the mob-spawner custom texture technique without also removing the mob-spawner texture. Anyway, as I said I do not think this technique is light enough to light enough for me to consider putting it into oilmod. Furthermore, this would also break things: People could no longer set their own resourcepack as the server now need to manage that. Yes, there are ways around it, but those are not pretty and that is why I won't consider it.
  17. Ah right I remember. However you can just add a block with a spawner texture back in then.
  18. Yes there are workarounds. Are they pretty? no.
  19. While OilMod focusses on adding a new item/block API, there are cases in which a mod needs to display custom user interfaces. Obviously, the client does not allow for this and such these need to be realised through already existing ui. Bukkits Inventory API is not sufficient here as it is very static and behaviour changes can only be realised through events. This is where the userinterface api of OilMod comes in. It allows one to build custom uis, which are realised at NMS level whenever possible (and thus there is no nms<->bukkit overhead). In addition, it easily allows changing slot behaviour:
    - one can restrict a slot only to blocks, only to helmets and so on.
    - Slots that don't exist server-side appear 'disabled' to the client
    - Slots types can be changed: normal inventory slot, crafting result slot, result slot, creative menu slot and custom types (such as a button slot)
    - Shifting behaviour can be adjusted to go into the right slot.

  20. @sirati97 the Bukkit API is enough to build a good inventory API. You need no NMS to build an well designed custom inventory API.

Share This Page