Skip to content

Datapack Guide

Theo edited this page Aug 18, 2026 · 7 revisions

Datapack guide

Almost everything in Portable Beacons is a datapack entry: which effects a beacon may project, what they cost, what augments do, what each tier is worth, and what burns as fuel. The mod ships its own content through exactly the mechanism described here — there is no private path.

Files go under your own namespace:

data/<your_namespace>/portablebeacons/effect/<name>.json
data/<your_namespace>/portablebeacons/augment/<name>.json
data/<your_namespace>/portablebeacons/tier/<name>.json
data/<your_namespace>/portablebeacons/fuel/<name>.json

The folder is portablebeacons/<registry> because these are datapack registries, so the path is data/<namespace>/<registry namespace>/<registry path>/. Since all four registries live in the portablebeacons namespace, that middle segment is always portablebeacons.

A typo makes an entry vanish, it does not crash. A file that fails to parse is dropped with a message in the log and nothing else — the symptom in game is an effect missing from the picker. If something you added is not showing up, read the log before re-reading the JSON.


effect — what a beacon may project

// data/mypack/portablebeacons/effect/fire_resistance.json
{
  "effect": "minecraft:fire_resistance",
  "cost": 2.0,
  "max_amplifier": 0,
  "min_tier": 2
}
Field Type Default Meaning
effect mob effect id required The projected effect. Any registered effect works — vanilla, another mod's, or datapack-added.
cost double 1.0 Fuel units per second at amplifier 0, self only. One unit ≈ one second of a basic effect.
max_amplifier int 0–3 0 Highest level this may be raised to. 0 means level I only.
min_tier int 1–4 1 Lowest beacon tier allowed to select it.
amplifier_cost_multiplier double 2.0 Cost factor per amplifier level above 0.

Cost at runtime is

cost × amplifier_cost_multiplier ^ amplifier × sharing surcharge × range factor

where the sharing surcharge is self 1.0, team 1.7, allies 2.0, allies_and_pets 2.4, and the range factor is 1 + range / 64 for shared effects only. The beacon's own mul_fuel and its movement multiplier then apply to the whole bill.

Only the part of the surcharge above 1.0 is what mul_aura_cost scales — so an augment can make sharing cheaper without touching what an effect costs you.

No icon is needed: effect icons come from the vanilla effect atlas.

fuel — what burns

// data/mypack/portablebeacons/fuel/copper_ingot.json
{ "item": "minecraft:copper_ingot", "units": 450 }
Field Type Default Meaning
item item id one of these A single consumed item.
tag item tag id one of these Every item in a tag — how one line covers every modded metal that follows the convention.
units int ≥ 1 required Fuel units any of them yields.

An entry must name exactly one of item and tag. Naming both, or neither, is rejected when the file is read rather than parsing into something that silently matches nothing.

// data/mypack/portablebeacons/fuel/steel.json
{ "tag": "c:ingots/steel", "units": 450 }

An item named directly beats one matched through a tag, so you can price a single metal without having to exclude it from whatever convention tag it belongs to.

For scale, the shipped values are iron 300, gold 900, emerald 1800, diamond 3600 and netherite 28800 — five minutes to eight hours of one basic effect. A tier IV beacon's buffer holds 36000.

A registry rather than a tag, because a tag can say "this is fuel" but cannot carry a per-item value, and hardcoding the values would undo the point of the rest being data-driven.

The beacon refuses an item its buffer cannot hold whole, rather than burning most of a netherite ingot for a small top-up — which is what gives the Capacity augment a purpose.

tier — a beacon item's base stats

// data/mypack/portablebeacons/tier/verdant.json
{
  "level": 3,
  "effect_slots": 2,
  "augment_slots": 2,
  "base_range": 12.0,
  "fuel_capacity": 18000,
  "max_amplifier": 0,
  "aura_rank": 1,
  "effect_pool": [
    "portablebeacons:regeneration",
    "portablebeacons:haste"
  ]
}
Field Type Default Meaning
level int 1–4 required Used for ordering and for every min_tier check.
effect_slots int 0–5 required How many effects may be configured. Five is the ceiling: the screen lays out that many, and an effect past it would be charged and invisible. Augments count toward the same limit.
augment_slots int 0–4 required How many augment slots are unlocked, of the four the beacon has.
base_range double required Aura radius in blocks. Ignored by effects set to self.
fuel_capacity int required Internal buffer, in fuel units.
max_amplifier int 0–3 0 Highest amplifier without an Amplification augment.
aura_rank int 0–3 0 How widely it shares without an Attunement augment: 0 self, 1 team, 2 allies, 3 allies and pets.
effect_pool list of effect ids [] Which effects this tier accepts.

aura_rank is the whole sharing gate. A beacon offers every mode up to its rank, and Attunement adds to it. Set it to 3 and the beacon shares with everything from the start; leave it at 0 and sharing has to be earned with an augment. The shipped tiers use 0 for Beacons I and II and 1 for everything else, so that Attunement always has something left to unlock.

Changing augment_slots is safe on a live world. It says how many slots are usable; the container itself is a fixed size decided by the mod, and fuel sits in the first slot with augments after it. Lowering the number on a beacon that already holds augments leaves them in place but locked — raise it again and they come back. Nothing is destroyed and nothing shifts.

An empty effect_pool means "anything the effect registry allows". That is what you get for free, but every shipped tier declares one explicitly so a themed beacon cannot quietly inherit the standard list when someone adds a new effect.

Keep ranges modest. The vanilla beacon reaches 20–50 blocks; a beacon that follows you is worth far more than a fixed one at equal reach, and the shipped tiers top out at 16 for that reason.

A tier entry alone does not create an item — the four numbered beacons and the three themed ones are registered in code, each pointing at a tier entry. A datapack can retune any of those seven, and can add a tier for its own use, but adding an eighth beacon item needs an addon mod.

augment — what slots into a beacon

// data/mypack/portablebeacons/augment/reach.json
{
  "max_tier": 3,
  "color": 5636095,
  "operations": [
    { "type": "add_range", "values": [4.0, 8.0, 12.0] }
  ]
}
Field Type Default Meaning
max_tier int 1–3 3 Highest tier this augment exists in.
color int 0xFFFFFF Tint applied to the augment texture. Alpha is forced opaque at render time.
operations list required What it changes.

A datapack augment draws as the generic tinted gem. Glyphs are selected by the augment's registry key, so giving yours its own shape means shipping a model that names it — there is no number to claim. (Older versions used a model_data integer for this; it is ignored now, and a file that still carries one loads fine.)

Each operation carries one value per augment tier, so "Reach I/II/III" stays a single file. Values shorter than max_tier clamp to the last entry.

type Effect
add_range Adds blocks to the aura radius.
add_effect_slot Adds configurable effect slots.
add_amplifier Raises the reachable amplifier.
mul_fuel Multiplies fuel cost — use values below 1.0 to make it cheaper.
mul_capacity Multiplies the fuel buffer.
unlock_aura Adds to the beacon's aura_rank, unlocking wider sharing. A negative value takes ranks away; the result floors at 0, so Self can never be removed.
hide_effects 1 hides the particle swirl, 2 also hides the status icon.
mul_aura_cost Multiplies the sharing surcharge alone, leaving what an effect costs you unchanged.
free_effect_slot Runs this many effects for nothing — always the dearest ones, so the value does not depend on the order they were configured in.
mul_cost_moving Multiplies cost while the carrier is travelling.
mul_cost_still Multiplies cost while the carrier is stationary.

The last four are the levers that change which strategy is affordable rather than how much of a stat you have. mul_aura_cost in particular is the only thing in the mod that modulates the price of sharing, which is otherwise fixed by the mode.

Movement is judged coarsely — horizontal only, above a threshold well clear of the drift a standing player produces — so an augment that pays differently for the two cannot flicker between them.

hide_effects is the one operation whose value names a behaviour instead of scaling one, so it is read as a threshold and the highest value wins rather than summing.

Only one augment of each type may go in a beacon at a time. That is enforced both by the slot and by the resolver, so a stack built by command cannot stack two of the same.

Getting your augment in game

Augments are all one item, portablebeacons:augment, whose identity comes from a component:

/give @s portablebeacons:augment[portablebeacons:augment={type:"mypack:reach",tier:2}]

A recipe produces one the same way:

{
  "type": "minecraft:crafting_shaped",
  "category": "misc",
  "key": {
    "A": { "item": "minecraft:amethyst_shard" },
    "B": { "item": "minecraft:amethyst_block" }
  },
  "pattern": ["BAB", "A A", "BAB"],
  "result": {
    "id": "portablebeacons:augment",
    "count": 1,
    "components": {
      "portablebeacons:augment": { "type": "mypack:reach", "tier": 2 }
    }
  }
}

This is exactly why augments are one item with a component rather than one registered item each: a datapack can introduce a brand new augment without any code, which registered items would make impossible.


Changing the shipped content

Same mechanism, same file paths, portablebeacons as the namespace. To retune the standard Speed effect, put your own file at data/portablebeacons/portablebeacons/effect/speed.json — later datapacks win, so yours replaces the shipped one.

To remove something, override it with an entry no beacon can select, for instance "min_tier": 4 on a tier-3-only pool. Beacons already carrying an effect whose entry disappears drop it cleanly the next time they tick; existing saves do not break.

Checking your work

These are datapack registries, which are read when the world loads — reload the world (or restart the server) after editing them, rather than relying on /reload. Recipes and tags you add alongside them do follow /reload normally.

Watch the log as the world loads: that is where a rejected file reports itself, and it is the only place it does. In game, an entry that loaded correctly shows up in the effect picker for any beacon whose tier allows it.

Clone this wiki locally