Skip to content

Creating a Loot Table

Parker Hawke edited this page Aug 3, 2020 · 5 revisions

As of DragonEggDrop - Revival version 1.8.0, the loot system is now driven entirely by loot tables - a system inspired by Minecraft's loot table system. These loot tables are a powerful JSON file that define a set of loot pools to be generated when the dragon has been killed.

It is recommended to read Minecraft's wiki on loot tables (as linked earlier) for a more in-depth understanding on how loot tables work. While the keys and structure may be slightly different than that of vanilla, the concept of pools, rolls and weights remain the same.

What is a Loot Table?

A loot table is a JSON file that defines what and how much loot should be generated. This loot generation is defined by a set of pools which may have a set or random amount of rolls, each roll selecting an item in the pool. Every pool will be rolled based on the amount defined in said pool, whether that be an exact integer or a minimum and maximum time, randomly decided at time of generation.

The basic structure of a DragonEggDrop loot table is as follows:

{
    "egg": {
        "chance": 100.0,
        "name": "%dragon%'s egg - optional",
        "lore": [
            "The first line of lore for the dragon egg",
            "The second line of lore for the dragon egg",
            "Lore is optional"
        ]
    },
    "command_pools": [
        {
            "rolls": 1,
            "chance": 100.0,
            "commands": [
                {
                    "weight": 1.0,
                    "command": "minecraft:tellraw %dragoneggdrop_top_damager% {\"text\":\"Congratulations! You have killed \",\"color\":\"red\",\"extra\":[{\"text\":\"%dragon%\"}]}"
                }
            ]
        }
    ],
    "chest": {
        "chance": 100.0,
        "name": "&cThe name of the chest",
        "pools": [
            {
                "name": "my-first-loot-pool",
                "rolls": 1,
                "items": [
                    {
                        "weight": 1.0,
                        "type": "minecraft:diamond_sword"
                    }
                ]
            },
            {
                "name": "my-second-loot-pool",
                "rolls": {
                    "min": 1,
                    "max": 10
                },
                "items": [
                    {
                        "weight": 0.5,
                        "type": "minecraft:dirt",
                        "amount": {
                            "min": 1,
                            "max": 32
                        }
                    },
                    {
                        "weight": 2.5,
                        "type": "minecraft:stone",
                        "amount": 64
                    }
                ]
            }
        ]
    }
}

While the above may seem confusing at first glance, especially for those not familiar with JSON syntax, let's break things down in bite sized pieces to hopefully make a bit more sense of these options.

Basic JSON

First, before creating a loot table, you must have a basic understanding of JSON. If you would like to read more about how JSON works, I welcome you to read some online tutorials such as the one from W3Schools which explains the basic structure of JSON. Here is a quick rundown:

  • JSON is a key-pair data structure. Every key is assigned a value which can be one of three basic types
    • A primitive value (a string, whole or decimal number or true/false)...
      • This is the most basic type of data
      • e.x. "string": "Hello world!", "number": 10.0 or "boolean": false
    • An object...
      • Think of objects as a holder for more key-value pairs. All keys are children of the object
      • Denoted by curly braces: {}
      • e.x. "object": { "child": "Hello world!", "second_child": true }
    • An array...
      • This is a list of ordered elements (primitive or objects!) with no unique keys. These are JUST values!
      • Denoted by square brackets: []
      • e.x. "array": [ "First value", "Second value", "Third value!" ] or "array": [ { "object_key": 10.0 }, { "second_object": true, "still_second_object": 10.0 } ]
  • If an object has more than one value, the values MUST be comma-separated! If not, JSON treats it as a single element and will fail to parse.
    • { "first_key": "This is valid", "second_key": "The elements are separated by a ," }
    • [ "This is invalid" "because it is missing a comma between the elements" ]
  • There is no true way to write your JSON. Whitespace is supported (as you can see in the first example) or you may write it all on one line. For readability sake, having everything indented and spaced out properly is much nicer to edit!

Do not worry if you do not understand everything on the first try. JSON is difficult to understand if you're not experienced with it, however I seriously recommend taking a good effort at learning it as it's quite simple after spending a bit of time learning the structure. If you find yourself struggling to get things right, consider copy/pasting your JSON into a JSON linter which will tell you what is wrong, where and why. I suggest using https://jsonformatter.curiousconcept.com/, this is the same website recommended from the console by DragonEggDrop if a loot table fails to load.

What is a Loot Pool?

Take for example the following example of a stripped (but still valid) DragonEggDrop loot pool:

{
    "chest": {
        "pools": [
            {
                "name": "my-first-loot-pool",
                "rolls": 1,
                "items": [
                    {
                        "weight": 1.0,
                        "type": "minecraft:diamond_sword"
                    }
                ]
            },
            {
                "name": "this would be another loot pool"
            }
        ]
    }
}

Under the chest object is a pools array. This is an array of objects which act as the pool from which items may be selected. (You will find the same array titled command_pools in the root object). You may have as many pools as you would like. Every pool will be used when loot is generated. In every pool you will find a rolls option which may be defined as either of the following:

"rolls": 1
"rolls": {
    "min": 0,
    "max": 5
}

The rolls are the amount of time the loot pool will select an element based on its weight (see What is a Weight?). If set to a specific number, the pool will always roll that amount of times. If rolls is an object with min and max, a number is generated between the minimum and maximum values (both inclusive. The above will be either 0, 1, 2, 3, 4 or 5) every time the loot is generated.

Every pool should define an items array (or in the case of commands, a commands array) from which the pool may select an element. This array is also an array of objects that will define the item (or command) that should be generated. More on items below.

Available Options

DragonEggDrop supplies you with 3 different types of loot, of which 2 are loot pools and 1 is a basic object. They are as follows:

"egg"

The egg object defines the dragon egg that will be generated either in a chest or in a world. The options here are simple and allow you to define a percent chance (0.0 - 100.0), the name of the egg (a string) and its lore (an array of strings). If a chest is generated, an item will be generated and placed in the chest. Otherwise it will be placed in the world and its name and lore will be applied when picked up.

"command_pools"

The command_pools array is an array of pool objects. Much like the item pools, you may have as many pools defined as you would like. rolls may be defined in a pool much like with item pools. The only differences are the chance element which defines the % chance that the pool will be used (i.e. if set to 50.0, it has a 50% chance to be ignored) and the commands element which is an array of strings... the commands to execute. All commands support PAPI placeholders.

"chest"

The chest object defines three keys. chance, the percent chance (0.0 - 100.0) that a chest will be generated. name, the name of the chest (& colour codes are supported here). Finally, the pools array as discussed earlier from which loot is selected. See What is a Loot Pool? for more information on loot pools.

Generating Items

In Vanilla Minecraft, items are very, very complex! There are many NBT values that may be defined for any given item and DragonEggDrop tries to support these all as best as possible. There are far too many options to list so for a full example on all options available to you, see the example_loot_table.json generated by DragonEggDrop in the plugin's DragonEggDrop/loot_tables directory, or on GitHub for an always up-to-date version. This section will cover the basic options that most server owners may want to configure.

{
    "weight": 1.0,
    "type": "minecraft:diamond_sword",
    "name": "Hello!",
    "lore": [
        "First line",
        "Second line!"
    ],
    "damage": 35,
    "unbreakable": true
}

Above you will see some of the basic options an item will allow you to choose. These are not ALL of the options (once again, please see the example loot table), but the ones which will be most commonly used.

weight: The item's weight for its loot pool. Please see What is a Weight? for more information on weights
type: The vanilla ID of the item to generate. This is the same ID you would use in-game with the /give command for example
name: The item's name. Chat colours are supported here
lore: An array of strings defining the item's lore. Chat colours are supported here
damage: The item's damage. Must be between 0 and the item's maximum damage value
unbreakable: Whether the item is unbreakable or not

What is a Weight?

Weights are numerical values used throughout loot pools to define an elements influence (or "commonality") when randomly selecting elements. If a weight is higher, it is more likely to be selected as opposed to those with lower values. In short, the % chance of an element to be selected in a weighted random is defined by the following:

(weight / (sum of all weights)) * 100

For instance, if you have three elements with the weights [ 10.0, 2.5, 0.5 ], the elements (in order) have the following chance of being selected:

  • (10.0 / (10.0 + 2.5 + 0.5)) * 100 = 77%
  • (2.5 / (10.0 + 2.5 + 0.5)) * 100 = 19%
  • (0.5 / (10.0 + 2.5 + 0.5)) * 100 = 4%

My Loot Table Won't Load!

If you are struggling with the loot table not loading in game, it's possible that DragonEggDrop could not recognize some of the options or you have malformated your JSON and it could not be read properly. Luckily for you, DragonEggDrop recognizes these issues quite well and will inform you of any startup errors with your loot tables in the console while the plugin is starting (or reloaded using /dragoneggdrop reload). A startup error may look something like this:

DragonEggDrop Loot Table Warnings

[Server thread/INFO]: [DragonEggDrop] Loading loot tables...
[Server thread/WARN]: [DragonEggDrop] Could not load loot table "example_loot_table.json"
[Server thread/WARN]: [DragonEggDrop] Unknown operation for attribute modifier "generic_max_health". Expected "add_number", "add_scalar" or "multiply_scalar_1"
[Server thread/WARN]: [DragonEggDrop] Could not load loot table "legendary_dragon.json"
[Server thread/WARN]: [DragonEggDrop] Could not create item of type "minecraft:iron_met" for item loot pool. Does it exist?
[Server thread/WARN]: [DragonEggDrop] Ensure all values are correct and run the JSON through a validator such as https://jsonformatter.curiousconcept.com/

As you can see, the errors should be clear enough to help you resolve any issues you may have. Unfortunately only one error will appear at any given time, but this in combination with the /dragoneggdrop reload command should help you get things resolved in no time! Still having issues? Contact support

How do I Use My Loot Table?

Now that you've created a loot table and made sure that DragonEggDrop can load it successfully, you have two options to use your loot table.

  1. Define the loot option in your dragon template (see Creating a Custom Dragon)
  2. Respawn a dragon template with a loot table override using /dragonrespawn start <time> <world> <template> your_loot_table

Questions?

I understand that this loot system may be confusing to many. For this reason, the default loot tables should be sufficient enough for most survival servers. However, if you insist on creating your own loot tables (which is encouraged!) but are still struggling with the structure, please contact Choco through the official Discord