NeoOrigins Mod Compatibility
NeoOrigins ships with built-in support for a number of other mods. Every integration is a soft dependency: each is gated behind a mod-list check (or runtime reflection, an optional mixin, or the other mod’s own plugin discovery), so none of these mods are required. If a mod is absent the integration simply stays dormant; NeoOrigins runs normally without it.
If a prose doc disagrees with the code, the code wins.
Datapack formats
| Mod / format | What NeoOrigins does | Notes |
|---|---|---|
| Origins / Apoli | Reads Origins-format origin and power datapacks and translates them into NeoOrigins powers at load time. | Most power types are supported directly; a few translate with reduced fidelity. Unsupported types are logged at reload and become no-ops rather than crashing the pack. Action and condition fields are accepted in both Apoli forms: a single object or an array (an array is an implicit all-of). Apoli’s command action verb dispatches as execute_command, subject to the same command blacklist. |
| Apugli / Apace | Legacy power-type vocabularies are remapped to the 2.0 type names. | See MIGRATION.md for the remap table and the known DSL gaps. |
You do not need any of these mods installed; NeoOrigins reads their pack format natively. Drop an Origins pack into config/originpacks/ and it loads. If that folder is empty or absent, the older game-root originpacks/ folder is read instead, but that location is deprecated: it warns once at load and will be removed in a future release. Once config/originpacks/ holds a pack of its own, the game-root folder is ignored, and a warning names it so nothing goes missing in silence.
Legacy Origins packs
A pack written for the Fabric Origins mod on 1.19/1.20 runs as downloaded: no edits to the zip. NeoOrigins wraps the pack’s own resource provider and repairs the 1.20 → 1.21 breakages, and those 26.x added, while a file is being read, so vanilla and the power translator only ever see content the current game can parse. Nothing is written back to disk, and each kind of repair announces itself once per pack in the log rather than once per file.
The table below is the syntax-level layer. Power-type translation is a separate pass; its remap tables and gaps are in MIGRATION.md.
| Legacy form | Why it breaks | What NeoOrigins does |
|---|---|---|
Plural data folders (functions/, recipes/, loot_tables/, advancements/, plural tags/ subfolders…) | 1.21 renamed every one of these to its singular form, so vanilla’s loaders never look in the legacy folder and simply never see the content. The pack loads without error and does nothing. | Serves the legacy folders under their modern names on both access paths: a missed modern lookup falls through to the legacy path, and directory listings rewrite legacy locations into modern ones. Thirteen folders are mapped. Modern content wins wherever a pack ships both. |
minecraft:set_nbt loot function | Removed in 1.20.5. The whole loot table fails to parse (“Unknown registry key”), and that cascades into every function and advancement referencing the table, so items the pack hands out become unobtainable. | Retargets the function to minecraft:set_custom_data, which takes the identical tag field. Applied only to JSON under loot_table/, loot_tables/, item_modifier/ and item_modifiers/, and only when the file text actually contains set_nbt. See the note on set_nbt below the table. |
Item stacks written {"item": ...} in a recipe result or an advancement icon, and ingredient objects such as {"item": ...} or {"tag": ...} | 1.20.5 renamed the stack’s item field to id, and 1.21.2 reduced an ingredient to an item id, a #tag or a list of item ids. A recipe or advancement in the old shape fails to load. | For packs in originpacks/, renames item to id in the result of a vanilla recipe type and in an advancement’s display.icon, and rewrites vanilla recipe ingredients into the id, #tag or id-list form. An ingredient list that mixes in a tag has no modern equivalent and is left alone, as is a result carrying legacy nbt, because dropping it would craft a different item. World datapacks are not rewritten. |
A fire_projectile tag whose Item is written as 1.20 item NBT (Count, tag:{Potion:...}) | 1.20.5 changed how an item stack is stored, so the old Item compound was read without its tag and a potion projectile flew with no effect. | The legacy Item is rebuilt as a stack when the projectile is fired: Count carries over, and Potion, enchantments and the other legacy keys map onto data components exactly as they do for legacy give NBT. |
attribute ... modifier add <uuid> <name> <value> <operation> in an .mcfunction | 1.21 identifies a modifier by an id instead of a UUID and a name, and renamed the operations, so the function failed to load. | The name is dropped and the UUID is kept as the modifier id, so the pack’s own modifier remove <uuid> still matches. add, multiply_base and multiply become add_value, add_multiplied_base and add_multiplied_total. |
attribute <target> generic.<name>, gamerule <camelCase>, a bare particle flash, summon minecraft:potion and the horse.saddle slot in an .mcfunction | 26.x dropped the generic. prefix from attribute ids, moved game rules to snake_case registry ids, made flash a coloured particle, split the thrown potion into splash and lingering entities and moved the saddle to its own saddle slot. Each of these stops the function loading, and a broken function in #minecraft:tick breaks the whole tag. | The attribute argument loses its generic. prefix, a game rule takes the id vanilla’s own world upgrade gives it (with the value flipped for the rules that were inverted, such as disableRaids to raids), flash gets an opaque white colour, the potion becomes splash_potion, or lingering_potion when the command’s NBT names a lingering potion item, and horse.saddle becomes saddle. Sound ids and NBT that merely mention generic. are left alone. |
An origin icon naming a renamed item (minecraft:scute, minecraft:chain) | The item id no longer exists, so the icon fell back to stone. | For Origins-format origins, the renamed id is mapped to the current one (minecraft:turtle_scute, minecraft:iron_chain) before the icon is read. |
"exclude_random": true on a layer | Origins read exclude_random only when it was a list and ignored any other value. NeoOrigins expects a list, so the layer logged a parse warning. | A value that is not a list is ignored, as in Origins. A list is read as before. |
The alternative loot condition | Renamed any_of before 1.21, so a loot table, predicate, item modifier or advancement using it failed to load. | For packs in originpacks/, alternative becomes minecraft:any_of with the same terms. |
Tag entries naming a renamed or split id (minecraft:chain, the minecraft:boat and minecraft:potion entities) | The id no longer exists, so the whole tag failed to load. | For packs in originpacks/, item and block tags get minecraft:iron_chain; entity tags get #minecraft:boat, which holds every boat type the old entity covered, and both minecraft:splash_potion and minecraft:lingering_potion. An entry’s required flag is kept. |
origins:fire_projectile / apace:fire_projectile with "entity_type": "minecraft:potion" | 26.x has no minecraft:potion entity: the thrown potion is now two entities, minecraft:splash_potion and minecraft:lingering_potion. The power was refused at load as an unknown entity type. | Throws minecraft:splash_potion, or minecraft:lingering_potion when the power’s tag mentions lingering_potion, which is how such a power picked a lingering potion before the split. This applies to the power type in any pack, not only originpacks/. The fire_projectile action is not remapped: give it the new entity id. |
origins:starting_equipment with a singular stack | Packs in the wild use both the singular stack and the plural stacks. NeoOrigins read only stacks, so a pack using the singular spelling was skipped and granted nothing. | Reads stacks when present, otherwise promotes a single stack object to a one-element list. A power carrying neither is still skipped with a warning. |
origins:prevent_entity_render / apace:prevent_entity_render | The type had no NeoOrigins equivalent, so it was logged as unsupported and became a no-op. | Maps onto the native neoorigins:prevent_entity_render, carrying entity_condition through unchanged. Apoli’s bientity_condition variant is deliberately not translated: half of the pair it compares is the observer. See Vision, rendering & HUD for the native type’s behaviour and limits. |
origins:entity_glow / apoli:entity_glow / apace:entity_glow | It went to a handler that gave the holder the Glowing effect, so everyone saw the holder glow and the holder saw nothing new. In Apoli the holder sees the matching entities outlined, and nobody else does. | Maps onto the native neoorigins:entity_glow, carrying entity_condition, bientity_condition, use_teams, red, green and blue through unchanged. Both conditions take only verbs that can be tested against an arbitrary entity (see Vision, rendering & HUD); one that uses anything else loads, warns and outlines nothing. origins:self_glow still goes to the old handler, which makes the holder glow for everyone and ignores its entity_condition, bientity_condition, use_teams and colour fields. |
origins:conduit_power_on_land (as a type, or the bare id) | It granted permanent water breathing, night vision and Haste. In Origins it grants no effect: it only lets an active conduit reach the holder out of water. | Maps onto the native neoorigins:conduit_power_on_land. The type has no fields to carry. |
The bare origins:master_of_webs id | A pack referencing Origins’ Master of Webs without shipping the file got wall_climbing, which climbs every wall. | Now gets neoorigins:cobweb_affinity with climb on: no cobweb slowdown and climbing inside webs. The bare id can stand for one power only, so the rest of Master of Webs (webbing on hit, sensing creatures in webs, cobweb crafting) is not supplied this way. A pack that ships its own master_of_webs.json is translated from that file instead. |
The #origins:ranged_weapons and #origins:shields item tags | The Origins mod ships both tags and NeoOrigins did not, so a pack tag that names either one was missing a reference and failed to load. | Both ship under the origins namespace with the Origins contents: ranged_weapons holds the bow, crossbow and trident, and shields holds the shield. Each also takes in the matching common tags as optional entries (#c:tools/bow, #c:tools/crossbow and #c:tools/ranged_weapon; #c:tools/shield), so modded bows, crossbows and shields count too. |
Blazeborn’s damage_from_snowballs (a modify_damage_taken add with a projectile damage condition, or the bare id) | The translation dropped the projectile check, so the add became a 4x multiplier on all incoming damage, and it still never reached a snowball: a snowball hits a player for 0, and no damage event fires for a 0 hit. The bare id was not recognized. | Maps onto the native neoorigins:projectile_vulnerability with the condition’s projectile and the modifier’s value as amount. Only that shape is rewritten, and the match is exact: a flat add (addition, add_base_early or add_base_late) of a positive amount on one named projectile type, not inverted, with no target_condition and no power condition, and with projectile_condition, bientity_condition, apply_armor_condition, damage_armor_condition, attacker_action, bientity_action and self_action either absent or left at a no-op verb (Apoli’s allow / nothing). Every other modify_damage_taken translates as before, an add of 0 or less among them. The bare id gets +3 from snowballs. |
origins-classes:no_sprint_exhaustion / no_mining_exhaustion | They translate onto neoorigins:exhaustion_filter, which loaded but did nothing through 2.2.30. | exhaustion_filter now cancels the listed sources, so both work. |
item_condition on action_on_block_use / action_on_entity_use | The field is Apoli’s “only with this item in hand” gate. The translator never copied it, so the ability fired for whatever the player was holding. | Copies item_condition (and Apoli’s newer held_item_condition spelling, which maps to the same key) onto the translated action_on_event, and the gate reads the stack out of the interaction event: the stack in the hand that triggered it. The translator carries no item gate onto action_on_block_break, wake_up or bonemeal. |
origins:target_action_on_hit / apace:target_action_on_hit | It fired only on a kill, and it ran its entity_action on the holder. In Apoli it fires on every hit and the action runs on the entity that was hit, so a power written to poison what you hit poisoned the holder instead, and only when the hit happened to kill. | Fires on every hit through onDealDamage and runs entity_action on the entity that was hit. The power’s own condition and cooldown are honoured. A player target gets the full entity-action surface; a mob target gets the generalizable subset (effects, damage, fire, knockback, …) and player-only verbs no-op on it, exactly as under target_action. |
set_block as a block_action | In Apoli set_block is a block action, so it places at the targeted position. NeoOrigins registered only an entity-side form that placed at the player’s own feet, so a right-click power aimed at the clicked block modified the ground under the player instead. | set_block resolves the block from the dispatch context — a block_use or bonemeal interaction, a projectile or raycast block hit, or a block_action_at / offset wrapper — and falls back to the actor’s own block position when no block context is active. It is also a block-target verb now, usable directly inside block_target_action alongside strip, till, path, grow and transform_block. |
Pack with no pack.mcmeta (or shipped as a .jar) | Vanilla’s folder repository source rejects .jar files outright and refuses folders missing pack.mcmeta, and Origins mod JARs ship without one, so the pack never even registers. | originpacks/ entries are scanned by NeoOrigins’ own pack finder: .jar, .zip and plain folders are all accepted, and when pack.mcmeta is absent compatible metadata is synthesized so the pack registers anyway. A real pack.mcmeta, when present, is read normally and wins. |
origins:resource across a login | The power seeded its start_value whenever it was applied to a player, and a login applies every power the player already holds. A bar holding progress was therefore reset to its floor on every world join, and a power reading the resource read the floor. | A login keeps whatever value round-tripped, and seeds start_value only when the player has none stored, so a save from before the bar existed still gets a bar. A fresh grant, an origin change or an orb re-pick still resets it. |
A modifier on origins:modify_attribute with a resource | Apoli lets the modifier take its value from a resource, which is how an attribute is made to track a counter. A vanilla attribute modifier holds one fixed amount, so the value was taken from the modifier’s own value and the resource ignored. These powers declare "value": 0, because the resource is meant to supply all of it, so the power loaded and did nothing. | The resource id is carried onto the native type’s resource field, which re-reads the value every 5 ticks, so the attribute follows the resource. A modifier with no value at all is accepted and defaults to 0. Apoli’s nested modifiers over the resource value are not applied: the attribute tracks the raw value, and the load warns when a pack nests them. |
The bare origins:burn_in_daylight, origins:hotblooded and origins:water_vulnerability ids | Each stood in with a power that carried no configuration: a condition_passive with no condition and no action, and an effect_immunity naming no effect. All three loaded and did nothing. | They now stand in with what Origins gives, matching the mod’s own classic-mode content: burn_in_daylight catches fire for 6 seconds once a second while sun-exposed and not invisible, hotblooded blocks Poison and Hunger, and water_vulnerability deals 2 damage a second in water or rain. |
Item NBT read through tag | 1.20.5 deleted the tag field from ItemStack; a stack serialises as {id,count,components}. A path like SelectedItem.tag.Foo still parses and still runs; it simply resolves to nothing, so neither a parse check nor a compile error can catch it. | Repoints the step at components."minecraft:custom_data". Both spellings are handled: the dot path (SelectedItem.tag.Foo, including subscripts such as Inventory[0].tag.Foo) and the brace form inside a selector or NBT literal (Item:{tag:{Foo:1}}). This one runs unconditionally rather than behind a parse check, because on 1.21 no item stack carries a tag field in any context, so there is no valid path of that shape to break. |
The JSON shape repairs run only on config/originpacks/. The plural-folder, set_nbt, .mcfunction and tag-path repairs also run on world datapacks, but the item-stack, ingredient, alternative and tag-id rewrites do not, so a world datapack in the old shape has to be edited by hand. The fire_projectile, icon and exclude_random fixes apply to every pack. In config/originpacks/ a few shapes are still left to the author: another mod’s recipe type, a recipe result carrying legacy nbt (rewrite it as {"id": ..., "components": {...}}), an ingredient object with any key besides item or tag, and an ingredient list holding a tag alongside other entries. 26.x has no form for that last one: put the items in an item tag of the pack’s own and name it as #namespace:tag.
The set_nbt rewrite is not an NBT-to-components converter. set_custom_data is a faithful replacement only when the tag blob is pure pack data. A key that moved to a real data component on 1.21 would end up buried inside custom_data where nothing reads it, so a blob carrying one is left exactly as it was and reported in the log: the table still fails to load, but it fails loudly instead of quietly handing out items with the enchantments or the damage value missing. The keys treated as component-backed are Potion, CustomModelData, Damage, Unbreakable, RepairCost, Enchantments, ench, StoredEnchantments and display. A tag that is not a string, or whose SNBT does not parse, is also left alone with a warning. The brace form of the tag-path repair applies the same check, and additionally leaves any stack that already carries components untouched.
Legacy keys outside that set are not mapped. BlockEntityTag, EntityTag, AttributeModifiers, SkullOwner, CanDestroy and HideFlags all became data components on 1.21 but are absent from the set above, so a blob carrying only those is taken for pure pack data and routed into custom_data, where the game will not read it. SkullOwner → minecraft:profile is the one worth calling out: a legacy pack that hands out a named player head gets a head with no profile on it, and no warning. If a pack depends on any of these, that one file needs converting by hand.
Prose is never mistaken for a path. The tag-path repair skips quoted regions, so a tellraw payload or a title that happens to contain Item.tag.foo is left alone, and the verbs whose payload is unquoted free text (say, me, msg, tell, w, teammsg, tm) are excluded outright. In an execute chain only the tail after run is excluded, so the selectors ahead of it are still repaired.
Gameplay integrations
| Mod | Mod id | What it adds |
|---|---|---|
| Curios API | curios | Lets conditions inspect equipped curio slots: the equipped_item condition’s accessory slot (optionally narrowed by slot_type) and umbrella detection both read worn curios, and neoorigins:keep_inventory keeps matching curio-slot items through death. Reflection-based, no hard dependency. Curios is the only accessory mod read on this build: there is no Accessories (Wisp Forest) support. |
| Vampires Need Umbrellas | vampiresneedumbrellas | An equipped umbrella shields the holder from both weather-damage conditions: exposed_to_sun (sun-burn origins) and in_rain (rain/water-damage origins like Wet Fur and True Hydrophobia). Every item in the vampiresneedumbrellas namespace is treated as an umbrella, detected in either hand or any Curios slot. |
| Artifacts | artifacts | The Artifacts umbrella (artifacts:umbrella) shields the holder from exposed_to_sun and in_rain, the same as a Vampires Need Umbrellas umbrella. Wired through the neoorigins:umbrellas item tag as an optional entry — no dependency, and the entry no-ops when Artifacts is absent. Datapacks can add their own umbrellas to that tag; see Umbrella items. |
| Ars Nouveau | ars_nouveau | A player whose neoorigins:entity_group power uses a group with invert_instant_effects (the undead behaviour) is healed rather than harmed by a spell containing Ars Nouveau’s Harm effect, mirroring vanilla undead behaviour. Reflection-based. |
| FTB Teams | ftbteams | Players on the same or an allied FTB team are treated as trusted for mount consent: a teammate or ally can ride your mountable origin without sending a consent request. Reflection-based. |
| Open Parties & Claims | openpartiesandclaims | Same as FTB Teams, but using OPAC party membership. Reflection-based. |
| FTB Quests | ftbquests | Two routes, both rolling a loot table into the player’s inventory (overflow drops at their feet). Reward type: a “NeoOrigins: Grant Loot Pool” reward (neoorigins:loot_pool) in the quest editor, with a loot_table id and rolls (1 to 256, default 1); it rolls for the player who claims it. Tag marker: a quest tagged neoorigins_loot_pool_grant:<table_id> rolls that table once, on completion, for every online member of the completing team. Each route grants at most once per player per reward or per quest-and-table, and a roll that yields no items is not counted, so it can grant later. Compile-only soft dependency. See FTB Quests for what the other Minecraft versions support. |
| FTB Ultimine | ftbultimine | Powers the neoorigins:ultimine power: NeoOrigins registers a restriction handler so vein-mining is gated to players holding an active ultimine power. The integration is completely dormant unless a loaded pack defines a neoorigins:ultimine power; while no pack uses it, FTB Ultimine behaves exactly as vanilla. Once at least one ultimine power is loaded, vein-mining is restricted to players who hold one. Block count, tool requirement, and shape follow FTB Ultimine’s own server config; the restriction API exposes no override for them. Compile-only soft dependency. |
| Dragon Survival | dragonsurvival | The neoorigins:become_dragon power drives Dragon Survival’s own dragon state, so an origin can make its holder a DS dragon of a configured species and stage; DS supplies the actual traits, growth, abilities, altar economy and hunters. Ships with three built-in origins (Cave / Forest / Sea Dragon) gated behind "required_mods": ["dragonsurvival"], so they only load and appear in the picker when DS is installed. Reflection-based, no hard dependency. See the Dragon Survival section and the caveat below. |
| Pehkui | pehkui | No live integration: origin body-scale powers set the vanilla minecraft:scale attribute and never write Pehkui’s scale. What exists is a stand-in for Pehkui’s /scale command, registered only when Pehkui is absent, so Origins packs whose functions call scale ... still parse and run their other lines. The stand-in accepts any arguments; set, add or reset with pehkui:base, pehkui:width, pehkui:height, pehkui:model_width or pehkui:model_height and a numeric value set the executing player’s vanilla scale to that value (add behaves like set); every other form, including a reset with no value and types such as pehkui:flight, does nothing and still reports success. See the caveat below. |
| Epic Fight | epicfight | Origin scaling is applied to Epic Fight’s custom entity renderer via a client-side mixin (it scales Epic Fight’s pose by the entity’s scale), so scaled origins render correctly with Epic Fight installed. The mixin is optional and skipped when Epic Fight is absent. |
| Build A Spell | buildaspell | The neoorigins:cast_spell action casts an inline Build A Spell spell (delivery plus an ordered components list) from an origin power. Without Build A Spell installed the action logs a warning and does nothing. Compiled against a checked-in API stub, never bundled. See Targeted, block & integration verbs. |
| GeckoLib | geckolib | The neoorigins:trigger_morph_animation action starts or stops a triggerable animation on the morph model a player is drawn as, when that model is a GeckoLib entity. Only animation names the mob’s own author registered can be triggered. Reflection-based. See Targeted, block & integration verbs. |
| Aliens vs Predator | (targets com.alien.common.util.AlienPredicates) | A player holding a neoorigins:xeno_passive power is not a viable facehugger host: an optional mixin makes the mod’s host check return false for them. Nothing ships that grants the power; pair it with a mobs_ignore_player power for the targeting half. The mixin is skipped when the mod is absent. |
| Iron’s Spells ‘n Spellbooks | irons_spellbooks | Three surfaces: the neoorigins:cast_iron_spell action casts an Iron’s spell from an origin power; a neoorigins:resource power can back its bar with the player’s Iron’s mana pool ("backing": "irons_spellbooks:mana"); and attribute_modifier powers can modify Iron’s custom attributes (max mana, spell power, cooldown reduction, …). Compile-only soft dependency (never bundled). See the full Iron’s Spells ‘n Spellbooks section below. |
| Modded attributes | (any) | attribute_modifier powers can target attributes added by other mods (e.g. Iron’s Spells, Apothic Attributes). Attribute IDs resolve with or without the generic./player. prefix. For Iron’s specifically, see the Iron’s Spells ‘n Spellbooks section. |
| Figura | figura | Exposes a read-only neoorigins Lua global to Figura avatars, so a custom-avatar script can react to the wearer’s origin, active powers, capabilities, and evolution tier (e.g. swap models per origin or per tier). Origins declare opaque model keys via the figura_model / figura_models datapack fields. Compile-only soft dependency; Figura only ever reads NeoOrigins state. Full reference: FIGURA.md. |
| Cold Sweat | cold_sweat | Two author-facing primitives (the neoorigins:modify_temperature action writes a temperature trait, the neoorigins:body_temperature condition reads and compares one) plus a built-in resistance package: 18 origins ship hidden heat/cold resistances via cold_sweat:* attributes, so a Cold Sweat install makes them feel at home (or vulnerable) in the right biomes. Compile-only soft dependency (never bundled). See the full Cold Sweat section below. |
1.21.1 vs 26.x: Accessories and Sable are read on 1.21.1 only. FTB Ultimine works on 1.21.1 and 26.1 but is an inert marker on 26.2 and 26.3. FTB Quests gets a reward type and the tag marker on 1.21.1 and 26.1, and nothing that works on 26.2 or 26.3. See Availability by Minecraft version.
Iron’s Spells ‘n Spellbooks
irons_spellbooks is a compile-only soft dependency; it is never bundled, and nothing here is required. A pack that uses these surfaces runs fine without Iron’s installed: each degrades to a logged no-op rather than crashing. Where a whole origin or power only makes sense with Iron’s present, gate it with the top-level "required_mods": ["irons_spellbooks"] array so it neither loads nor shows up in the picker when the mod is absent. (required_mods is an all-of gate: every id listed must be loaded.)
Three integration surfaces are available.
1. Cast an Iron’s spell: neoorigins:cast_iron_spell action
Casts an Iron’s spell as the player from an origin power: pick the spell id, level, and instant/channel mode. By default the cast is free from Iron’s mana (the cost is charged on the NeoOrigins power); set consume_mana: true to draw from and gate on the player’s Iron’s mana pool instead. Without Iron’s installed the action is a logged no-op. See Targeted, block & integration verbs for the full field list.
2. Mana-backed resource bar: neoorigins:resource with backing
Set "backing": "irons_spellbooks:mana" on a neoorigins:resource power to make its bar read from and write to the player’s Iron’s mana pool rather than NeoOrigins’ own per-player store. The mana pool stays authoritative:
- The bar auto-scales. Omit
min/max. It usesmin = 0andmax =Iron’s live max mana (theirons_spellbooks:max_manaattribute, which moves with gear, level, and effects), so Iron’s own bar and this one fill identically. - Writes are additive-only:
change_resource,regen_rate, andresource_costeach add or subtract a delta; NeoOrigins never overwrites mana absolutely, so it won’t fight Iron’s regen and casting bookkeeping. Drains floor-clamp at 0. - Without Iron’s installed the bar reads empty and writes do nothing (logged once); it does not fall back to an internal value.
See the backing docs under Resources, toggles & state → neoorigins:resource for the full behaviour.
3. Modify Iron’s attributes: neoorigins:attribute_modifier
neoorigins:attribute_modifier (and the auto-translated Apoli origins:attribute / origins:modify_attribute) resolve any registered attribute id from the game registry, so they can target Iron’s custom attributes directly: no NeoOrigins-side list to opt into. Point the power’s attribute field at one of the eight ids below.
| Attribute id | Base | What add_value does | Scale |
|---|---|---|---|
irons_spellbooks:max_mana | — | Flat add to mana capacity | Flat points (e.g. 100.0 = +100 max mana) |
irons_spellbooks:mana_regen | 1.0 | Mana regen multiplier | Fractional bonus (0.5 ≈ +50% regen) |
irons_spellbooks:spell_power | 1.0 | Overall spell power multiplier | Fractional bonus (0.25 ≈ +25%) |
irons_spellbooks:spell_resist | 1.0 | Incoming magic resistance | Fractional bonus (0.2 ≈ +20% resist) |
irons_spellbooks:cooldown_reduction | 0 | Spell cooldown reduction | Fraction 0–1 (0.15 = 15% shorter cooldowns) |
irons_spellbooks:cast_time_reduction | 0 | Cast-time reduction | Fraction 0–1 (0.15 = 15% faster casts) |
irons_spellbooks:casting_movespeed | — | Movement speed while casting | Movement-speed units |
irons_spellbooks:summon_damage | — | Summoned-mob damage | Damage units |
The operation and scale differ per attribute: match Iron’s own scaling. max_mana is a flat add; spell_power, mana_regen, and spell_resist sit on a base of 1.0, so an add_value amount is a fractional bonus (0.5 ≈ +50%); cooldown_reduction and cast_time_reduction are 0-based fractions in the range 0–1. There are no separate per-school (fire/ice/…) spell-power attributes in 3.14.0; schools are handled by school-types layered over the single spell_power / spell_resist attributes, so those eight are the complete list.
Referencing an irons_spellbooks:* attribute on a server without Iron’s installed logs one warning per grant and applies nothing; the power still loads. Gate the origin with "required_mods": ["irons_spellbooks"] if it should only exist when Iron’s is present.
Example (+100 flat max mana):
{
"type": "neoorigins:attribute_modifier",
"attribute": "irons_spellbooks:max_mana",
"amount": 100.0,
"operation": "add_value",
"name": "Deep Well",
"description": "A larger mana pool."
}
Example (+25% spell power, fractional, base 1.0):
{
"type": "neoorigins:attribute_modifier",
"attribute": "irons_spellbooks:spell_power",
"amount": 0.25,
"operation": "add_value",
"name": "Arcane Focus",
"description": "Spells hit 25% harder."
}
Both examples belong in an origin gated with "required_mods": ["irons_spellbooks"] so they only apply where the attributes exist.
Cold Sweat
cold_sweat is a compile-only soft dependency; it is never bundled, and nothing here is required. Every Cold-Sweat-typed reference is isolated in a single bridge class that is only loaded once Cold Sweat is confirmed present, so a pack that uses these surfaces runs fine without it installed: the action degrades to a logged no-op, the condition reads false, and the built-in resistances simply don’t load. Where a power only makes sense with Cold Sweat present, gate it with "required_mods": ["cold_sweat"] so it neither loads nor shows up in the picker when the mod is absent.
Three integration surfaces are available.
1. Write a temperature: neoorigins:modify_temperature action
Changes one of the player’s Cold Sweat temperature traits from an origin power: pick the trait, an amount, and an operation (add the delta, default, or set an absolute value). core is the player’s body temperature on a roughly −100 (freezing death) … +100 (burning death) scale, 0 being neutral; positive amounts warm, negative amounts cool. Without Cold Sweat installed the action is a logged no-op. See Core effect verbs for the full field list.
2. Read a temperature: neoorigins:body_temperature condition
Reads a Cold Sweat temperature trait and compares it against compare_to with a comparison operator, so a power can react to the player getting dangerously hot or cold (e.g. trait: core, compare_to: 50, comparison: ">=" fires once the body is overheating; compare_to: -50, comparison: "<=" catches dangerous cold). It is named body_temperature rather than temperature because neoorigins:temperature is already the biome base-temperature condition. Without Cold Sweat installed the condition fails closed, always false, with one logged warning. See Entity conditions for the full field list.
Both surfaces share the same trait vocabulary: core, base, and world are temperature readings (core is the body, base/world the ambient scale); heat_resistance, cold_resistance, heat_dampening, and cold_dampening are the resistance traits (roughly 0..1); freezing_point/burning_point are the body-temperature thresholds; rate scales how fast body temp changes.
3. Modify Cold Sweat attributes: neoorigins:attribute_modifier
neoorigins:attribute_modifier resolves any registered attribute id, so it can target Cold Sweat’s resistance attributes directly. Point the power’s attribute field at one of the four ids below.
| Attribute id | What add_value does | Scale |
|---|---|---|
cold_sweat:cold_resistance | Insulates against cold ambient temperature | ~0..1 (1.0 ≈ immune to cold) |
cold_sweat:heat_resistance | Insulates against hot ambient temperature | ~0..1 (1.0 ≈ immune to heat) |
cold_sweat:cold_dampening | Scales how strongly cold moves body temp | ~−1..1 (negative = more vulnerable to cold) |
cold_sweat:heat_dampening | Scales how strongly heat moves body temp | ~−1..1 (negative = more vulnerable to heat) |
A positive resistance protects; a negative dampening value makes the origin more affected by that temperature; the built-in package below uses both to give each origin a home climate and a weak one.
Built-in resistance package. Eighteen origins ship hidden, Cold-Sweat-gated attribute_modifier powers so they feel adapted to their element when Cold Sweat is installed (and are unaffected when it isn’t):
- Heat-adapted: Blazeling and Strider (
+1.0heat resist,−0.5cold dampening), Piglin (+0.75heat resist,−0.25cold dampening), Cinderborn and Fire Mage (+0.5heat resist,−0.25cold dampening), Cave Dragon (+0.5heat resist). - Cold-adapted: Frostborn (
+1.0cold resist,−0.5heat dampening), Sea Dragon (+0.5cold resist,−0.25heat dampening), Abyssal, Kraken, and Merling (+0.5cold resist), Enderian, Enderite, Avian, Windwalker, Sculkborn, Warden, and Siren (+0.25cold resist).
These powers are hidden and gated with "required_mods": ["cold_sweat"], so they never appear in the power list and never load on a server without Cold Sweat.
Dragon Survival
The neoorigins:become_dragon power drives DS’s own dragon state, so an origin can make its holder a DS dragon of a configured species and stage. Three built-in origins (Cave / Forest / Sea Dragon) ship gated behind "required_mods": ["dragonsurvival"]. The bridge is reflective and there is no hard dependency; see the caveat at the end of this page.
Sharing the join screen
Both mods want a screen the moment you join a world. NeoOrigins shows the origin picker because the server told the client to; Dragon Survival shows its species-choice screen when its start_with_dragon_choice config is on. Whichever one opens second replaces the first, and the usual casualty is the origin picker.
NeoOrigins resolves this in the picker’s favour without discarding DS’s screen. The species choice is held back and reopened as soon as the picker closes, whether you confirmed it, escaped it or abandoned it. The interception is symmetric, so it works whichever mod wins the race.
Only DS’s species screens are ever involved, and under the default behaviour only while the origin picker is actually on screen: opening a species screen yourself, from an altar block, the dragon inventory button or a command, behaves exactly as it does without NeoOrigins installed. DS’s appearance editor, skins, abilities and dragon inventory are never touched under any setting.
The client config compat.dragon_species_screens picks the behaviour: DEFER (the default, described above), SUPPRESS (cancel every DS species screen, picker on screen or not, so the origin picker is the only way to choose a species), or ALLOW (never interfere). See CLIENT_CONFIG.md. It is a per-client setting, so it needs no change on the server or in DS’s own config.
FTB Quests
What a quest author can use differs by Minecraft version:
| Feature | 1.21.1 | 26.1 | 26.2 | 26.3 |
|---|---|---|---|---|
“NeoOrigins: Grant Loot Pool” reward type (neoorigins:loot_pool) | Yes | Yes | No | No |
neoorigins_loot_pool_grant:<table_id> quest tag | Yes | Yes | No | No |
- 1.21.1 registers the reward type at common setup and listens for quest completion through FTB Quests’
ObjectCompletedEvent. Both are wired only whenftbquestsis loaded. - 26.1 registers the same reward type at common setup, against FTB Quests 26.1’s reward API. Completion for the tag marker is read from FTB Quests 26.1’s
FTBQuestsEvent.QuestProgress(completed quests only). - 26.2 and 26.3 have no working FTB Quests support. Neither build compiles against FTB Quests, since none exists for either, and each keeps only a reflection hook for the older
ObjectCompletedEvent, which FTB Quests’ 26.x line no longer has. If FTB Quests is installed the hook finds nothing, logs that tag-marker rewards are inert, and no reward type exists.
The neoorigins:loot_pool_grant power is unaffected by any of this and works on every version.
Availability by Minecraft version
Not every integration is compiled into every build. “Yes” means the build contains the integration’s code; the other mod still has to exist for that Minecraft version.
| Integration | 1.21.1 | 26.1 | 26.2 | 26.3 |
|---|---|---|---|---|
| Accessories | Yes | No | No | No |
| EMI | Yes | No | No | No |
| Sable | Yes | No | No | No |
| FTB Quests | Reward type and tag marker | Reward type and tag marker | No (see above) | No (see above) |
| FTB Ultimine | Yes | Yes | No: the ultimine power loads but is an inert marker, and vein-mining is left ungated | No: the ultimine power loads but is an inert marker, and vein-mining is left ungated |
| KubeJS | Yes | Yes | No: see KUBEJS.md | No: see KUBEJS.md |
| Everything else on this page | Yes | Yes | Yes | Yes |
Scripting
| Mod | Mod id | What it adds |
|---|---|---|
| KubeJS | kubejs | A scripting plugin exposing NeoOrigins to KubeJS: register custom powers, actions, and conditions, and hook origin lifecycle events from JS. Not available on the Minecraft 26.2 or 26.3 builds: KubeJS publishes no artifact for either, so the integration is not compiled in there. See KUBEJS.md. |
| KeybindJS | keybindjs | Client-side: when KeybindJS is loaded, a key mapping registered outside NeoOrigins under an active power’s declared key name is used for that power instead of one of NeoOrigins’ numbered hotkey slots, so the key is not bound twice. |
1.21.1 vs 26.x: the KubeJS plugin ships on 1.21.1 and 26.1; 26.2 and 26.3 have none, because KubeJS publishes no build for either.
Recipe viewers
| Mod | Mod id | What it adds |
|---|---|---|
| JEI | jei | Adds an information panel for the Orb of Origin item. |
| REI | roughlyenoughitems | Adds the Orb of Origin to the item list. |
1.21.1 vs 26.x: the EMI information panel ships on 1.21.1 only; the 26.x builds contain no EMI plugin, since EMI publishes no 26.x NeoForge build.
Tooltips / probes
| Mod | Mod id | What it adds |
|---|---|---|
| Jade | jade | Meant to show the mob origin (from the Mob Origin System) of a looked-at living entity. Player origins are not shown. See the caveat below: the line does not currently appear. |
| The One Probe | theoneprobe | Shows the mob origin (from the Mob Origin System) of a looked-at living entity in the probe overlay. Player origins are not shown. |
| AppleSkin | appleskin | Makes the food tooltip and the held-food HUD preview show what a modify_food_nutrition power will actually give, rather than the item’s vanilla value. |
AppleSkin, in more detail. neoorigins:modify_food_nutrition never rewrites the item’s food data. It lets vanilla eat the item and then corrects the player’s hunger and saturation server-side, so the numbers only become right at the moment of eating. AppleSkin builds its preview by reading the food data off the stack on the client, where the override does not exist, so without this bridge every diet origin was previewed at vanilla values. The bridge answers AppleSkin’s own FoodValuesEvent with the origin-adjusted figures and leaves the vanilla figure in place, so AppleSkin still draws its usual struck-through comparison next to ours. Because that event fires on the client, the configured overrides are synced down alongside the existing active-power sync. Nothing here classloads when AppleSkin is absent.
Caveats and known gaps
- Pehkui’s scale and origin scale are separate. With Pehkui installed, NeoOrigins never touches Pehkui’s scale: origin size powers use the vanilla
minecraft:scaleattribute and Pehkui’s own/scaleis the real command, so the two stack however Pehkui combines its scale with the vanilla attribute. Without Pehkui, the/scalestand-in adds its own non-saved modifier tominecraft:scaleon top of the origin’s, so it is lost on relog. - FTB Quests grants loot pools, not origins. The
neoorigins_loot_pool_granttag rolls a loot table and deposits the items; it does not assign an origin directly. Use a loot table that yields the relevant items, or pair the grant with an origin-granting power. - GeckoLib covers morph animations only. Custom projectiles still render as items; NeoOrigins ships no GeckoLib projectile renderer.
- The Jade origin line does not currently appear. The Jade provider runs on the client and reads the mob origin from the entity’s own data, but that data is only kept on the server (clients receive mob origins through a separate cache). The One Probe reads it on the server and is unaffected.
- Dragon Survival binds reflectively. DS exposes no public addon API, so the bridge resolves its internal classes and methods by name at runtime. If a future DS release renames them,
become_dragonlogs one warning and stops transforming players (everything else keeps working). Report the DS version and the bridge gets re-pointed. - Lossy datapack translation. Some Origins/Apoli modifier types translate with reduced fidelity, and a handful of types are unsupported. These are logged at reload. Check the log if an imported pack behaves unexpectedly.