Datapack Materials - hjake123/reactive GitHub Wiki

The Material system is data-driven, so data packs are able to add new default materials, add new base items for materials, and even customize the formulae that are used when crafting materials.

Adding Datapack Materials

New Materials can be added to a world manually using a datapack.

To get started, you'll need a datapack with a valid pack.mcmeta file.

Once this is made, create a JSON file at (your datapack's name)/data/(any namespace)/reactive/materials/(material id).json. (any namespace) can be the same as (your datapack's name), but doesn't have to be. The resulting power will be located at (any namespace):(material id).

For example, this path would create a Material called testpack:rocks:

testpack/data/testpack/reactive/power/rocks.json

Here's an example material file, showcasing optional fields:

{
  "name": "Firestone Example",
  "properties": {
    "reactive:color": {
      "red": 127,
      "green": 80,
      "blue": 0
    },
    "reactive:model_name": "squares",
    "reactive:magma_step": {},
    "reactive:light": 15,
    "reactive:fire_source": {}
  },
  "original_formula": {
    "base_material": "reactive:salt_block",
    "powers": {
      "reactive:blaze": 301,
      "reactive:verdant": 423
    }
  }
}

To understand how to make your own, let's break this down by section.

name (Optional)

The name field chooses a default name for the Material. If you define a name here, it will appear instead of "Undiscovered Material" when the Material's name is shown before it is discovered. The material can still be renamed, but the new name may be overwritten if you run /reactive material reload. Specifying the name as "" has the same effect as not including it at all.

properties (Mandatory)

The properties block defines what the material does and how it looks. It is comprised of a map of Property ids to values. Each value must be aligned with the proper type for that Property, or data pack loading will fail.

reactive:color

Determines the tint applied to the block. It is an RGB-8 value, specified like so:

"reactive:color": {
    "red": <number from 0 to 255>,
    "green": <number from 0 to 255>,
    "blue": <number from 0 to 255>
}

If this property is absent, a fully white color is used.

reactive:model_name

The model name property decides which model (texture and sound) the block uses. There are nine valid models:

salt
cracked
gel
streaked
smooth
circles
squares
static
wool

If the model is gel, the block will be able to be moved through similarly to Powder Snow; no other model has a gameplay effect. If this property is absent, the salt model is used by default.

Defined like so:

"reactive:model_name": "wool"

reactive:blast_resistance

Determines how hearty the block is against being exploded. For reference, Obsidian has a blast resistance of 1200, and most blocks have a hundred or less. If this property is absent, the block has a blast resistance of 1.

Defined like so:

"reactive:blast_resistance": 1.0

reactive:break_strength

Determines how difficult the block is to break. The player's dig speed is divided by this value / 0.75 when the game checks how much progress to make while digging -- high values make the block harder. Since no tool is effective on Materials, ensure this isn't too high!

Defined like so:

"reactive:break_strength": 1.0

reactive:enchant_power

When present, makes the block function as a source of enchant power for the Enchanting Table. For reference, a bookshelf offers 1.0 enchanting power.

Defined like so:

"reactive:enchant_power": 1.0

reactive:fire_source

When present, makes the block infinitely sustain Fire blocks on top of itself, like Netherrack does.

Defined like so:

"reactive:fire_source": {}

reactive:flammability

When present, makes the block be ignited and eventually consumed by fire. The provided value is how quickly that happens, on a scale of 1 to 300.

Defined like so:

"reactive:flammability": 10

reactive:friction

Sets the block's internal "friction" value. This value is somewhat finicky, but I've found that it works best in the range of about 1.0 to 0.8 or so. Values outside that range are allowed, but... well, your mileage may vary.

Defined like so:

"reactive:friction": 1.0

reactive:intangible

When present, the block cannot be collided with at all. Entities will pass through as if it was not there. Doesn't affect the hitbox for breaking the block or placing others.

Defined like so:

"reactive:intangible": {}

reactive:light

Defines a light emission for the block. When placed, the block's state will be set to emit that much light. As a consequence, this is one of the two properties (alongside model_name) that cannot be changed for already placed blocks just by updating the material definition. The value must be between 0 and 15.

Defined like so:

"reactive:light": 13

reactive:magma_step

When present, living beings stepping on (or standing inside of) the block will be hurt by fire damage unless they're sneaking.

Defined like so:

"reactive:magma_step": {}

reactive:redstone

When present, the block will emit a redstone signal of the specified strength at all times.

Defined like so:

"reactive:redstone": 13

reactive:redstone_melting

When present, the block, upon receiving a redstone signal, change its model temporarily to the gel model. Recall that the gel model allows entities to pass through the block.

Defined like so:

"reactive:redstone_melting": {}

reactive:self_defense

When present, the block will zap players who attempt to break it repeatedly, dealing the specified amount of damage with each hit.

Defined like so:

"reactive:self_defense": 2.0

reactive:semitangible

When present, the block will act as a solid block except for entities that are sneaking, who will be allowed to drop through. If present alongside intangible, it will not have any effect.

Defined like so:

"reactive:semitangible": {}

reactive:warping

When present, the block will periodically teleport to an adjacent unoccupied space.

Defined like so:

"reactive:warping": {}

original_formula (Optional)

If this section is defined, the material will be able to be crafted using a Crucible by providing the specified powers and base material. The subsections are defined as follows:

base_material

Defines which item the material needs to be used as the input. By default, the only valid options are these:

reactive:salt_block
reactive:adept_salt_block
reactive:creation_salt_block
minecraft:white_wool

If you wish to add a new valid base material, see the section below.

powers

A map of power names to integer amounts. The Crucible must have a power balance within 100 points of each specified power, and must actually contain each power (so, a balance of 0 does not count, even if the requirement is less then 50) in order for the result to be this Material.

Base Material Yield Datamap

To add a new kind of Base Material for material crafting, you'll need to add an entry to the reactive:material_bases data map. This allows the chosen item to be used for any material crafting, not just making your datapack materials.

To start, create a JSON file (your datapack's name)/data/reactive/data_maps/item/material_bases.json

Note that this is NOT inside your custom namespace -- the namespace must be reactive.

The file should have a structure like this:

{
    "values": {
        "minecraft:diamond": {
             "default_model": "circles",
             "max_input_items": 1,
             "power_effect_multiplier": 1.5,
             "yield_per_input": 64
        }
        (other values as desired...)
    }
}

For each value, the key is the id of the item, and the fields are as follows:

default_model

When the Power combination doesn't force a particular model, what model should this item make? In the example, diamonds use the circles model by default.

max_input_items

How many items can be consumed by material crafting at once?

power_effect_multiplier

Bases other then Salt cause the power level used to determine Properties to increase according to these proportions. In the base mod, this value is never higher then 2.0, signifying a 2x increase. Using 0 as the value causes the base to behave as cosmetic: this is used by wool in the base mod.

yield_per_input

For each single item consumed, how many are returned? In the example above, putting in one Diamond gives you back 64 of the new Material.

Altering existing yields

The data map format allows for existing yields (i.e. mine) to be changed by datapacks also. Here are some examples:

Changing the yield of Salt Blocks

{
    "values": {
        "reactive:salt_block": {
            "replace": true,
            "value": {
                "default_model": "salt",
                "max_input_items": 64,
                "power_effect_multiplier": 1.0,
                "yield_per_input": 2
            }
        }
    }
}

Removing the wool base material

{
    "remove": [
        "minecraft:white_wool"
    ]
}

Material Formula Datamaps

The material crafting system is fully data-driven, so it can be configured using datamaps. However, this is quite an advanced feature, and may be hard to understand and use without overriding the existing design. If you want to do this and find this customization lacking, please contact me at hyperlynx on Discord so we can talk about what you're trying to accomplish.

Requirements

The requirements map determines which properties are given to materials based on the powers used to make them.

The Formula Requirements datamap is located at (your datapack's name)/data/reactive/data_maps/reactive/material_proerties/formula_requirements.json

Here's an example of altering the requirements of one property:

"reactive:enchant_power": {
      "replace": true,
      "values": {
          "requirements": [
                {
                    "low_bound_maximum": 250,
                    "low_bound_minimum": 50,
                    "power": "reactive:soul"
                },
                {
                    "low_bound_maximum": 50,
                    "low_bound_minimum": 50,
                    "power": "reactive:mind"
                }
            ]
      }
}

For the property to be added, all of the requirements have to be met. The power can be any valid power, including custom powers defined by KubeJS or Json Things. The low bound minimum and maximum determine the threshold of the specified power that must be met to consider the requirement met: the actual threshold value is a world specific value between the two provided values, so it may vary per world.

An empty requirements section would mean that all materials have this property; in fact, this is used by a few properties like color that all things should have.

Outcomes

The outcome map determines the "strength" of each property.

The Formula Outcomes datamap is located at (your datapack's name)/data/reactive/data_maps/reactive/material_proerties/formula_outcomes.json

To change the outcome for a particular property, the entry would look like this:

{    
    "reactive:redstone": {
        "replace": true,
        "values": [
            {
                "type": "reactive:zero_to_max_integer",
                "value": {
                    "max_power": 2000,
                    "max_value": 15,
                    "min_power": 10,
                    "power": "reactive:mind"
                }
            }
        ]
    }
}

The array within "values" is a list of Formula Outcomes which apply to the given Property. Depending on the Property, different kinds of Outcome are allowed.

reactive:zero_to_max_integer

Defines an integer that varies from 0 to a max value as the level of the defined Power varies between its defined min and max.

Defined as:

{
    "type": "reactive:zero_to_max_integer",
    "value": {
        "max_power": (int),
        "max_value": (int),
        "min_power": (int),
        "power": "(power id)"
    }
}

Only a single of these can be defined for a given property -- they do not support chaining.

Applicable to light, redstone, and flammability

reactive:one_to_value_float

Defines a floating point multiplier that is applied to a base value of 1.0. The multiplier is first itself multiplied by (power - min_power) / max_power - min_power.

Defined as:

{
    "type": "reactive:one_to_value_float",
    "value": {
        "max_power": (int),
        "min_power": (int),
        "power": "(power id)",
        "value": (float)
    }
}

If multiple are used in the same list, they will chain together, and are all applied in sequence.

Applicable to: blast_resistance, break_strength, enchant_power, friction, self_defense

reactive:zero_to_max_float

Like the prior, but it defined a float from 0 a max_value instead. Only used by the base mod for the enchant_power property.

Defined as:

{
    "type": "reactive:zero_to_max_float",
    "value": {
        "max_power": (int),
        "max_value": (float),
        "min_power": (int),
        "power": "(power id)"
    }
}

If multiple are used in the same list, they will chain together, and are all applied in sequence via multiplication. Of course, at the lower end, this would nearly nullify all others as the value approaches 0.

Applicable to: blast_resistance, break_strength, enchant_power, friction, self_defense