Skip to content

Extension Examples

This page contains copy-paste-ready examples for building on Redstone Additions.

All examples follow conventions from GUIDELINES.md and current v4 runtime behavior.

Read How It Works first if you need lifecycle context for these snippets.

Example 1: Simple Custom Block (Pulse Beacon)

Goal: place a block that emits a short pulse when powered.

File Tree

data/ra_myaddon/
  function/
    load.mcfunction
    tick.mcfunction
    items/
      give_all.mcfunction
    blocks/
      pulse_beacon/
        give.mcfunction
        handle_placement.mcfunction
        register_block.mcfunction
        tick.mcfunction
        on_powered.mcfunction
        reset.mcfunction
        on_break.mcfunction
  recipe/
    pulse_beacon.json

load.mcfunction

# /ra_myaddon:load
function ra_myaddon:blocks/pulse_beacon/register_block

tick.mcfunction

# /ra_myaddon:tick
function ra_myaddon:blocks/pulse_beacon/tick

items/give_all.mcfunction

# /ra_myaddon:items/give_all
function ra_myaddon:blocks/pulse_beacon/give

blocks/pulse_beacon/give.mcfunction

# /ra_myaddon:blocks/pulse_beacon/give
give @s bat_spawn_egg[item_model="minecraft:lightning_rod",item_name="Pulse Beacon",custom_data={ra:{pulse_beacon:1b}},entity_data={id:"minecraft:bat",Tags:["ra.spawned","ra.place.pulse_beacon"],Silent:1b,NoAI:1b,Invulnerable:1b}]

blocks/pulse_beacon/handle_placement.mcfunction

# /ra_myaddon:blocks/pulse_beacon/handle_placement
execute unless entity @s[tag=ra.place.pulse_beacon] run return 0
function ra_lib:placement/place {block_id:"minecraft:lightning_rod",block_tag:"pulse_beacon",dir_type:0}
return 1

blocks/pulse_beacon/register_block.mcfunction

# /ra_myaddon:blocks/pulse_beacon/register_block
tellraw @a[tag=ra.debug] [{"text":"[RA] ","color":"gold"},{"text":"Pulse Beacon registered","color":"gray"}]

blocks/pulse_beacon/tick.mcfunction

# /ra_myaddon:blocks/pulse_beacon/tick

# Break detection
execute as @e[tag=ra.custom_block.pulse_beacon] at @s if block ~ ~ ~ #minecraft:air run tag @s add ra.broken
execute as @e[tag=ra.broken,tag=ra.custom_block.pulse_beacon] at @s run function ra_myaddon:blocks/pulse_beacon/on_break
tag @e[tag=ra.broken,tag=ra.custom_block.pulse_beacon] remove ra.broken

# Detect redstone and trigger on rising edge
execute as @e[tag=ra.custom_block.pulse_beacon] at @s run function ra_lib:redstone/detect
execute as @e[tag=ra.custom_block.pulse_beacon,tag=ra.powered,tag=!ra.was_powered] at @s run function ra_myaddon:blocks/pulse_beacon/on_powered
tag @e[tag=ra.custom_block.pulse_beacon,tag=ra.powered] add ra.was_powered
tag @e[tag=ra.custom_block.pulse_beacon,tag=!ra.powered] remove ra.was_powered

blocks/pulse_beacon/on_powered.mcfunction

# /ra_myaddon:blocks/pulse_beacon/on_powered
# Emit a short pulse in the surrounding shell
fill ~-1 ~-1 ~-1 ~1 ~1 ~1 redstone_block replace iron_block
schedule function ra_myaddon:blocks/pulse_beacon/reset 4t

blocks/pulse_beacon/reset.mcfunction

# /ra_myaddon:blocks/pulse_beacon/reset
execute as @e[tag=ra.custom_block.pulse_beacon] at @s run fill ~-1 ~-1 ~-1 ~1 ~1 ~1 iron_block replace redstone_block

blocks/pulse_beacon/on_break.mcfunction

# /ra_myaddon:blocks/pulse_beacon/on_break
kill @e[type=item,nbt={Item:{id:"minecraft:lightning_rod"}},distance=..2,limit=1,sort=nearest]
summon item ~ ~ ~ {Item:{id:"minecraft:bat_spawn_egg",count:1,components:{"minecraft:item_model":"minecraft:lightning_rod","minecraft:item_name":"Pulse Beacon","minecraft:custom_data":{ra:{pulse_beacon:1b}},"minecraft:entity_data":{id:"minecraft:bat",Tags:["ra.spawned","ra.place.pulse_beacon"],Silent:1b,NoAI:1b,Invulnerable:1b}}}}
kill @s

recipe/pulse_beacon.json

{
  "type": "minecraft:crafting_shaped",
  "category": "redstone",
  "pattern": [
    " C ",
    "RLR",
    " C "
  ],
  "key": {
    "C": "minecraft:copper_ingot",
    "R": "minecraft:redstone",
    "L": "minecraft:lightning_rod"
  },
  "result": {
    "id": "minecraft:bat_spawn_egg",
    "count": 1,
    "components": {
      "minecraft:item_model": "minecraft:lightning_rod",
      "minecraft:item_name": "Pulse Beacon",
      "minecraft:custom_data": { "ra": { "pulse_beacon": true } },
      "minecraft:entity_data": {
        "id": "minecraft:bat",
        "Tags": ["ra.spawned", "ra.place.pulse_beacon"],
        "Silent": true,
        "NoAI": true,
        "Invulnerable": true
      }
    }
  },
  "show_notification": true
}

Required Registration Hooks

Add your placement handler into:

  • data/ra/tags/function/placement_handlers.json

Also call your namespace load/tick from your own entrypoints, and make sure your pack entrypoint is wired through tags if this is a standalone addon datapack.

Example 2: Addon Namespace Scaffold

Minimal scaffold for a full addon namespace with two blocks:

data/ra_myaddon/
  function/
    load.mcfunction
    tick.mcfunction
    items/give_all.mcfunction
    blocks/
      alpha/{give,handle_placement,register_block,tick,on_break}.mcfunction
      beta/{give,handle_placement,register_block,tick,on_break}.mcfunction
  recipe/
    alpha.json
    beta.json
  advancement/
    tools/
      get_alpha.json
      get_beta.json

Recommended load pattern:

# /ra_myaddon:load
function ra_myaddon:blocks/alpha/register_block
function ra_myaddon:blocks/beta/register_block

Recommended tick pattern:

# /ra_myaddon:tick
function ra_myaddon:blocks/alpha/tick
function ra_myaddon:blocks/beta/tick

Example 3: Multiblock Extension Pattern

Goal: add a new multiblock type using existing ra_lib_multiblock lifecycle.

Files to Add

data/ra_multiblock/function/my_structure/
  validate.mcfunction
  check_structure.mcfunction
  setup_type.mcfunction
  tick.mcfunction
  on_break.mcfunction

validate.mcfunction

# /ra_multiblock:my_structure/validate
# Set ra.multiblock result objective to 1 when valid, 0 when invalid.
scoreboard players set #mb_result ra.multiblock 0

# Example minimal check: require blast_furnace at marker position
execute if block ~ ~ ~ minecraft:blast_furnace run scoreboard players set #mb_result ra.multiblock 1

setup_type.mcfunction

# /ra_multiblock:my_structure/setup_type
# Context: as marker
# Initialize typed data used by tick/process.
data modify entity @s data.type set value "my_structure"
data modify entity @s data.properties set value {enabled:1b}

tick.mcfunction

# /ra_multiblock:my_structure/tick
# Context: as marker
execute if data entity @s data.properties{enabled:1b} run particle minecraft:happy_villager ~ ~1 ~ 0.25 0.25 0.25 0.01 2

Hook Registration

Register your type in relevant ra_lib_multiblock function tags:

  • validate hook
  • setup hook
  • tick hook
  • on_break hook

Also ensure wrench assembly flow can set your intended type in storage ra:multiblock before assembly.

Sanity Checklist For New Blocks

  1. Give item custom_data matches placement handler tag.
  2. Placement handler returns success only for matching bats.
  3. Tick includes break cleanup.
  4. Recipe output entity tags exactly match give item tags.
  5. CDH and Goggles are extended if your block has properties/status.
  6. ra:placement_handlers includes your new handler.