Skip to main content

Porting Guide: Fabric → NeoForge

This document explains the differences between the original Fabric version (Apace100/origins) and the NeoForge rewrite (IAFEnvoy/Origins-NeoForge). Use it to convert existing data packs, add-ons, or documentation from the Fabric version to the NeoForge version.


Data Path Changes

All JSON files moved from custom paths to Vanilla DataPack Registry paths.

ContentFabric PathNeoForge Path
Origindata/<ns>/origins/data/<ns>/origins/origin/
Powerdata/<ns>/powers/data/<ns>/origins/power/
Layerdata/<ns>/origin_layers/data/<ns>/origins/layer/
Badge(not in Fabric)data/<ns>/origins/badge/
Global Power Setdata/<ns>/global_powers/ Not yet implemented

Action: Move files and add registry subfolder (origin/, power/, layer/, badge/).


Origin JSON Changes

FieldStatusNotes
name RemovedUse translation key origin.<ns>.<path>.name
description RemovedUse translation key origin.<ns>.<path>.description
loading_priority RemovedData packs now override by priority naturally
powersChangedNow supports #tag references. Prefer #tag over listing individual power IDs
iconChangedFrom Item+Damage+NBT to {"id": "minecraft:feather"}
orderChangedDefault changed from 0 to Integer.MAX_VALUE
impactSame0=None, 1=Low, 2=Medium, 3=High
unchoosableSame
upgradesSame

Action: Remove name/description/loading_priority from all origin JSONs. Add name/description via language files instead. Update icon to the new {"id": "..."} format. Use #tag references in powers instead of listing each power ID individually whenever possible.


Layer JSON Changes

FieldStatusNotes
replace RemovedUse data pack override behavior
name RemovedUse translation key layer.<ns>.<path>.name
missing_name RemovedNot needed
missing_description RemovedNot needed
originsChangedNow supports #tag references. Prefer #tag over listing individual origin IDs
gui_title.choose_originRenamedWas choose_origin (top-level); now nested under gui_title
gui_title.view_originRenamedWas view_origin (top-level); now nested under gui_title
orderSame
enabledSame
allow_randomSame
hiddenSame
auto_chooseNewAuto-choose if only one origin is available
default_originNewDefault origin for new players
allow_random_unchoosableNew
exclude_randomNew

Action: Move choose_origin/view_origin under gui_title. Remove replace/name/missing_name/missing_description. Use #tag references in origins instead of listing each origin ID individually whenever possible.


Power JSON Changes

FieldStatusNotes
hiddenSame
conditionSameEntity Condition
loading_prioritySame
badgesSameSupports inline {badge} objects
typeSamePower type ID

Action: Power JSONs are mostly compatible. Translate power names/descriptions via power.<ns>.<path>.name / .description keys.

origins:multiple — Split into individual files

Fabric's origins:multiple power type (which bundled several sub-powers into one JSON file) does not exist in NeoForge. Each sub-power must be extracted into its own standalone power JSON file.

FabricNeoForge
One multiple JSON with nested sub-powersOne file per power, referenced individually
"type": "origins:multiple" with "powers": [...]Each power gets its own file in data/<ns>/origins/power/

Action: For each entry in the powers list of an origins:multiple, create a separate power JSON file. Reference all the split power IDs in the origin's powers field or a power #tag.


Condition Type Changes

origins:attacker — Moved to BiEntity & Damage conditions

In Fabric, origins:attacker was an entity condition used inside bientity conditions. In NeoForge:

RegistryType IDCategoryField
origins:bientity_conditionorigins:attacker[Bi-entity Condition]Checks if the actor attacked the target
origins:damage_conditionorigins:attacker[Damage Condition]Checks the attacker via entity_condition

Action: Replace nested entity-condition attacker with the corresponding BiEntity/Damage condition variant.

origins:attack_target

Same as above: in Fabric it was nested inside bientity conditions. In NeoForge it's a direct BiEntity condition (origins:attack_target) checking if the actor is targeting the target.

RegistryType IDCategory
origins:bientity_conditionorigins:attack_target[Bi-entity Condition]

Removed Condition Types

Fabric TypeStatus in NeoForgeNote
origins:command Removed
origins:entity_group Removed1.21.1 no longer has entity groups, use origins:in_tag instead
origins:category (biome) Removed1.21.1 no longer has biome categories, use origins:in_tag instead
origins:high_humidity (biome) Removed1.21.1 no longer has humidity conditions, use origins:in_tag instead`
origins:owner (bientity) RemovedWill be added later

Not Yet Implemented

These features existed in Fabric but are not yet available in NeoForge:

FeatureStatus
origins:chose_origin advancement trigger Not yet implemented
/resource command Not yet implemented
origins:origin predicate Not yet implemented
apoli:power predicate Not yet implemented
Global Power Set Not yet implemented
Conditioned Origins in Layers Not yet implemented
origins:edible_item power type Not yet implemented
origins:modify_enchantment_level power type Not yet implemented

New Features

FeatureNotes
DataPack Registry SystemAll Origins JSON uses Vanilla's datapack registry
Power TagsReference #tag in origin powers and layer origins
Default OriginLayer field: assign default on join
Badge RegistryBadges use Vanilla registry at origins:badge
Inline Badge Definitionsbadges in powers can take inline {badge} objects
ColorSettingsred/green/blue/alpha floats + single color hex integer

Key API Differences

Fabric (Apoli) APINeoForge API
PowerTypeRegistryPowerRegistries.POWER_KEY via Registry
OriginsRegistryOriginRegistries.ORIGIN_KEY
OriginLayerRegistryLayerRegistries.LAYER_KEY
OriginsAPIOriginDataHolder.get(entity) as attachment
PowerType interfacePower abstract class with MapCodec
PowerHolderComponentOriginDataHolder (NeoForge attachment)
PowerTypeRegistry#registerBuiltInRegistries + DeferredRegister pattern

Action: For Java add-ons targeting NeoForge, port from Apoli's PowerTypeRegistry to NeoForge's DeferredRegister<MapCodec<? extends Power>> pattern.


AI Porting Prompt

When converting Fabric Origins data packs to NeoForge, use this prompt:

You are porting an Origins Fabric data pack to the NeoForge version (IAFEnvoy/Origins-NeoForge).

Changes to apply:
1. Move all JSON files to datapack registry paths:
- origin JSONs: data/<ns>/origins/ → data/<ns>/origins/origin/
- power JSONs: data/<ns>/powers/ → data/<ns>/origins/power/
- layer JSONs: data/<ns>/origin_layers/ → data/<ns>/origins/layer/
2. Remove from Origin JSONs: name, description, loading_priority.
Add translations to language file: "origin.<ns>.<id>.name" and ".description".
3. Remove from Layer JSONs: replace, name, missing_name, missing_description.
Move choose_origin/view_origin under a new "gui_title" object.
Add translations: "layer.<ns>.<id>.name".
Use #tag references in origins instead of listing individual origin IDs.
4. Update icon format: old "item"/"damage"/"nbt" → new {"id": "minecraft:..."}
Use #tag references in powers instead of listing individual power IDs.
5. Split any origins:multiple powers into individual power JSON files.
6. Replace removed condition types (command, entity_group, category, high_humidity, owner) with equivalent alternatives or JS scripts.
7. origins:attacker and origins:attack_target are now BiEntity conditions directly — no longer nested entity conditions inside bientity conditions.
8. Do NOT nest comparison/compare_to fields — they remain as flat top-level keys.
9. Check the porting guide at porting.md for the full list of differences.