create-mekanism-modular/tools/materials.py

1471 lines
79 KiB
Python

"""Material definitions for the Truly Modular addon.
One entry per material. `generate_materials.py` turns these into MIAPI material
JSON, pulling the colour palette out of the source mod's own item texture.
Stat calibration follows Tinkers' Construct 3 (1.20.1) in spirit, re-scaled onto
MIAPI's vanilla-derived numbers:
material hardness density durability ench tier mining
copper 4.2 3.6 200 13 2 5
iron 5.0 3.8 235 14 3 6
diamond 6.0 2.0 1546 10 4 8
netherite 7.0 2.0 2016 15 5 9
Tinkers' character mapping used below:
cobalt -> titanium light, fast, durable, unremarkable damage
steel -> steel balanced workhorse, no frills
hepatizon -> brass/bronze copper alloys, damage and enchantability
manyullyn -> dragonsteel top damage, endgame gate
rose gold -> refined glowstone / pixie dust fragile, huge enchantability
ancient hide -> dragon scales, chitin armour-first, high toughness
Tiers 6 and 7 sit above netherite by request: 6 = refined obsidian, shadow
steel, refined radiance, atomic alloy; 7 = dragonsteel and antimatter.
"""
# Mining level tags, indexed by tier.
MINING_LEVEL = {
1: "minecraft:incorrect_for_wooden_tool",
2: "minecraft:incorrect_for_stone_tool",
3: "minecraft:incorrect_for_iron_tool",
4: "minecraft:incorrect_for_diamond_tool",
5: "minecraft:incorrect_for_netherite_tool",
6: "minecraft:incorrect_for_netherite_tool",
7: "minecraft:incorrect_for_netherite_tool",
}
NUGGET = 0.11112 # 1/9, matching MIAPI's own nugget values
BLOCK = 9.0
# Sub-packs. Each becomes a NeoForge built-in datapack that is only registered
# when its mod is present, so a material never references a missing item.
# Where two mods add the same metal, one is picked as the provider and the
# material lives in that mod's pack - see the Immersive Engineering section.
PACKS = {
"mekanism": {"mod": "mekanism", "name": "Mekanism Materials"},
"create": {"mod": "create", "name": "Create Materials"},
"iceandfire": {"mod": "iceandfire", "name": "Ice and Fire Materials"},
"air_war": {"mod": "create_the_air_wars", "name": "Create: The Air War Materials"},
"cosmonautics": {"mod": "rocketnautics", "name": "Create: Cosmonautics Materials"},
"irons_spellbooks": {"mod": "irons_spellbooks", "name": "Iron's Spells Materials"},
"interstellar": {"mod": "vsie", "name": "Interstellar Expansion Materials"},
"immersiveengineering": {"mod": "immersiveengineering",
"name": "Immersive Engineering Materials"},
"enderio": {"mod": "enderio", "name": "Ender IO Materials"},
"ae2": {"mod": "ae2", "name": "Applied Energistics Materials"},
"ars_nouveau": {"mod": "ars_nouveau", "name": "Ars Nouveau Materials"},
"occultism": {"mod": "occultism", "name": "Occultism Materials"},
"industrialforegoing": {"mod": "industrialforegoing",
"name": "Industrial Foregoing Materials"},
"nautec": {"mod": "nautec", "name": "NauTec Materials"},
"superbwarfare": {"mod": "superbwarfare", "name": "Superb Warfare Materials"},
"steampunkdimension": {"mod": "steampunkdimension",
"name": "Steampunk Dimension Materials"},
"rftoolsbase": {"mod": "rftoolsbase", "name": "RFTools Materials"},
"createdeco": {"mod": "createdeco", "name": "Create Deco Materials"},
"crystal_chronicles": {"mod": "crystal_chronicles",
"name": "Crystal Chronicles Materials"},
"pastel": {"mod": "pastel", "name": "Pastel Materials"},
"createpropulsion": {"mod": "createpropulsion",
"name": "Create Propulsion Materials"},
"aeroengineering": {"mod": "aeroengineering", "name": "AeroEngine Materials"},
"create_wizardry": {"mod": "create_wizardry", "name": "Create Wizardry Materials"},
# Modules rather than materials, but the same problem: a module that names
# Arsenal's or Armory's slots - or inherits one of their modules - is only
# useful when that mod is installed. Nothing is generated into these two;
# they hold the hand-written module JSON under packs/arsenal and
# packs/armory, and are listed here so their pack.mcmeta is written.
"arsenal": {"mod": "tm_arsenal", "name": "Arsenal Modules"},
"armory": {"mod": "tm_armory", "name": "Armory Modules"},
# Same again, for the one module that needs a mod outside Truly Modular:
# the gem case wants Armory's slot and Apotheosis' component both, so
# CMModular.java gates it on the pair.
"apotheosis": {"mod": "apotheosis", "name": "Apothic Gem Cases"},
}
# Attributes this mod registers itself, so a material can grant something the
# game has no attribute for. See FireImmunity.java, WaterBreathing.java and
# WaterCombat.java.
FIRE_IMMUNITY = "cmmodular:fire_immunity"
WATER_BREATHING = "cmmodular:water_breathing"
SAND_PHASING = "cmmodular:sand_phasing"
WATER_COMBAT = "cmmodular:water_combat"
# Vanilla's own underwater mining multiplier, base 0.2 - the 5x penalty for
# swinging a pick with your eyes under water, and what Aqua Affinity undoes.
SUBMERGED_MINING_SPEED = "minecraft:player.submerged_mining_speed"
def attribute(attr, value, slot, operation="+"):
return {"attribute": attr, "value": str(value), "operation": operation, "slot": slot}
def M(name, pack, group, translation, palette_from, items, tier, hardness, density,
flexibility, durability, enchantability, mining_speed, *, groups=None,
hidden_groups=None, toughness=0, armor_durability=None, armor_toughness=None,
knockback_resistance=None, textures=("metallic",), properties=None,
icon=None, mining_level=None):
"""One material. `palette_from` is the item whose texture seeds the palette."""
return {
"name": name,
"pack": pack,
"group": group,
"translation": translation,
"palette_from": palette_from,
"icon": icon or palette_from,
"items": items,
"groups": list(groups) if groups else [group],
"hidden_groups": list(hidden_groups) if hidden_groups else [],
"textures": list(textures),
"properties": properties or {},
"stats": {
"hardness": hardness,
"density": density,
"flexibility": flexibility,
"durability": durability,
"enchantability": enchantability,
"toughness": toughness,
"tier": tier,
"mining_speed": mining_speed,
"mining_level": mining_level or MINING_LEVEL[tier],
**({"armor_durability": armor_durability} if armor_durability is not None else {}),
**({"armor_toughness": armor_toughness} if armor_toughness is not None else {}),
**({"knockback_resistance": knockback_resistance} if knockback_resistance is not None else {}),
},
}
def ingots(mod, ingot, nugget=None, block=None, extra=()):
out = [{"item": f"{mod}:{ingot}", "value": 1.0}]
if nugget:
out.append({"item": f"{mod}:{nugget}", "value": NUGGET})
if block:
out.append({"item": f"{mod}:{block}", "value": BLOCK})
out.extend(extra)
return out
def speed(value):
"""Attack speed tweak on held modules: positive is faster."""
return {"attributes": [{"attribute": "generic.attack_speed", "value": str(value),
"operation": "+", "slot": "mainhand"}]}
MATERIALS = [
# ------------------------------------------------------------------ Mekanism
M("tin", "mekanism", "metal", "Tin", "mekanism:ingot_tin",
ingots("mekanism", "ingot_tin", "nugget_tin", "block_tin"),
tier=2, hardness=3.4, density=2.6, flexibility=2.5, durability=150,
enchantability=16, mining_speed=5, armor_durability=9,
textures=("metallic", "bright")),
# Soft, light and cheap: the tier-2 filler metal. Tinkers has no tin, so
# this reads off real tin - low hardness, corrosion-proof, easy to work.
M("lead", "mekanism", "metal", "Lead", "mekanism:ingot_lead",
ingots("mekanism", "ingot_lead", "nugget_lead", "block_lead"),
tier=3, hardness=4.2, density=6.0, flexibility=0.5, durability=300,
enchantability=8, mining_speed=4, toughness=1, armor_durability=16,
knockback_resistance=0.05,
properties={"handheld": speed(-0.12)}),
# The heaviest thing here. Slow swing, poor enchanting, but it plants you.
M("osmium", "mekanism", "metal", "Osmium", "mekanism:ingot_osmium",
ingots("mekanism", "ingot_osmium", "nugget_osmium", "block_osmium"),
tier=4, hardness=5.6, density=5.6, flexibility=0.5, durability=620,
enchantability=10, mining_speed=6, toughness=2, armor_durability=22,
armor_toughness=1.0, properties={"handheld": speed(-0.08)}),
# Densest metal that exists. Heavy-weapon material: big density offset,
# real toughness, sluggish in hand.
M("bronze", "mekanism", "metal", "Bronze", "mekanism:ingot_bronze",
ingots("mekanism", "ingot_bronze", "nugget_bronze", "block_bronze"),
tier=3, hardness=4.9, density=4.0, flexibility=1, durability=420,
enchantability=12, mining_speed=6, toughness=1, armor_durability=19),
# Tinkers' amethyst bronze slot: a solid step past iron, nothing exotic.
M("steel", "mekanism", "metal", "Steel", "mekanism:ingot_steel",
ingots("mekanism", "ingot_steel", "nugget_steel", "block_steel"),
tier=4, hardness=6.0, density=4.2, flexibility=1.5, durability=720,
enchantability=9, mining_speed=7, toughness=2, armor_durability=26,
armor_toughness=1.0),
# Tinkers' steel almost verbatim: diamond harvest tier, balanced, boring
# in the way a workhorse should be. Poor enchantability is the cost.
M("uranium", "mekanism", "metal", "Uranium", "mekanism:ingot_uranium",
ingots("mekanism", "ingot_uranium", "nugget_uranium", "block_uranium"),
tier=4, hardness=6.2, density=5.8, flexibility=0.5, durability=900,
enchantability=6, mining_speed=6, toughness=2, armor_durability=24,
properties={"default": {"emissive": {"sky": 3, "block": 3}},
"handheld": {"leeching": "0.5", **speed(-0.06)}}),
# Dense, faintly glowing, actively bad for you - leeching stands in for
# radiation, and enchantability is the worst on the list.
M("refined_obsidian", "mekanism", "metal", "Refined Obsidian",
"mekanism:ingot_refined_obsidian",
ingots("mekanism", "ingot_refined_obsidian", "nugget_refined_obsidian",
"block_refined_obsidian"),
tier=6, hardness=8.0, density=4.6, flexibility=2, durability=2600,
enchantability=12, mining_speed=12, toughness=4, armor_durability=42,
armor_toughness=4.0,
properties={"default": {"fire_proof": True}, "handheld": speed(-0.05)}),
M("refined_glowstone", "mekanism", "metal", "Refined Glowstone",
"mekanism:ingot_refined_glowstone",
ingots("mekanism", "ingot_refined_glowstone", "nugget_refined_glowstone",
"block_refined_glowstone"),
tier=5, hardness=5.0, density=2.4, flexibility=4, durability=700,
enchantability=30, mining_speed=11, toughness=1, armor_durability=22,
textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 15, "block": 15}},
"tool": {"luminious_learning": "1"}}),
# Tinkers' rose gold role: fragile for its tier, best-in-slot enchanting.
M("infused_alloy", "mekanism", "metal", "Infused Alloy", "mekanism:alloy_infused",
[{"item": "mekanism:alloy_infused", "value": 1.0}],
tier=4, hardness=5.8, density=3.6, flexibility=2, durability=800,
enchantability=16, mining_speed=8, toughness=2, armor_durability=26),
M("reinforced_alloy", "mekanism", "metal", "Reinforced Alloy",
"mekanism:alloy_reinforced",
[{"item": "mekanism:alloy_reinforced", "value": 1.0}],
tier=5, hardness=6.6, density=4.0, flexibility=2, durability=1600,
enchantability=14, mining_speed=9, toughness=3, armor_durability=34,
armor_toughness=2.0),
M("atomic_alloy", "mekanism", "metal", "Atomic Alloy", "mekanism:alloy_atomic",
[{"item": "mekanism:alloy_atomic", "value": 1.0}],
tier=6, hardness=7.8, density=3.8, flexibility=3, durability=2800,
enchantability=18, mining_speed=11, toughness=4, armor_durability=44,
armor_toughness=3.5, properties={"default": {"fire_proof": True}}),
# Mekanism's alloy ladder ends here, so it tops out the tier-6 band.
M("fluorite", "mekanism", "crystal", "Fluorite", "mekanism:fluorite_gem",
[{"item": "mekanism:fluorite_gem", "value": 1.0},
{"item": "mekanism:block_fluorite", "value": 4.0}],
tier=4, hardness=5.6, density=2.2, flexibility=0, durability=600,
enchantability=18, mining_speed=8, toughness=1, armor_durability=20,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 4, "block": 4}}}),
# Real fluorite fluoresces, hence the faint glow; brittle, so no flex.
M("hdpe", "mekanism", "metal", "HDPE", "mekanism:hdpe_sheet",
[{"item": "mekanism:hdpe_sheet", "value": 1.0},
{"item": "mekanism:hdpe_pellet", "value": 0.25},
{"item": "mekanism:hdpe_rod", "value": 0.5}],
tier=3, hardness=3.2, density=0.9, flexibility=6, durability=450,
enchantability=20, mining_speed=3, toughness=1, armor_durability=18,
textures=("rough",), properties={"handheld": speed(0.1)}),
# Plastic: nearly weightless, very flexible, hopeless at cutting rock.
M("plutonium", "mekanism", "metal", "Plutonium", "mekanism:pellet_plutonium",
[{"item": "mekanism:pellet_plutonium", "value": 1.0}],
tier=5, hardness=6.8, density=5.6, flexibility=0.5, durability=1500,
enchantability=8, mining_speed=8, toughness=3, armor_durability=30,
properties={"default": {"emissive": {"sky": 5, "block": 5}},
"handheld": {"leeching": "0.7"}}),
M("polonium", "mekanism", "metal", "Polonium", "mekanism:pellet_polonium",
[{"item": "mekanism:pellet_polonium", "value": 1.0}],
tier=5, hardness=6.6, density=5.0, flexibility=1, durability=1400,
enchantability=9, mining_speed=8, toughness=3, armor_durability=30,
properties={"default": {"emissive": {"sky": 6, "block": 6}},
"handheld": {"leeching": "0.7"}}),
M("antimatter", "mekanism", "metal", "Antimatter", "mekanism:pellet_antimatter",
[{"item": "mekanism:pellet_antimatter", "value": 1.0}],
tier=7, hardness=9.5, density=2.0, flexibility=3, durability=4000,
enchantability=22, mining_speed=15, toughness=5, armor_durability=52,
armor_toughness=5.0, textures=("emissive", "metallic"),
properties={"default": {"fire_proof": True,
"emissive": {"sky": 12, "block": 12}},
"handheld": {"immolate": "5"}}),
# The single most expensive item in Mekanism, so it shares the ceiling
# with dragonsteel.
# -------------------------------------------------------------------- Create
M("zinc", "create", "metal", "Zinc", "create:zinc_ingot",
ingots("create", "zinc_ingot", "zinc_nugget", "zinc_block"),
tier=2, hardness=3.8, density=3.0, flexibility=1.5, durability=180,
enchantability=15, mining_speed=5, armor_durability=10,
textures=("metallic", "bright")),
# Brittle in reality, so it stays a tier-2 stepping stone to brass.
M("brass", "create", "metal", "Brass", "create:brass_ingot",
ingots("create", "brass_ingot", "brass_nugget", "brass_block",
extra=[{"item": "create:brass_sheet", "value": 1.0}]),
tier=3, hardness=5.0, density=3.4, flexibility=2, durability=380,
enchantability=18, mining_speed=8, toughness=1, armor_durability=18,
textures=("metallic", "bright")),
# Create's precision metal, and Tinkers' hepatizon slot: quick and
# enchantable rather than durable.
M("andesite_alloy", "create", "metal", "Andesite Alloy", "create:andesite_alloy",
[{"item": "create:andesite_alloy", "value": 1.0},
{"item": "create:andesite_alloy_block", "value": BLOCK}],
tier=2, hardness=4.4, density=4.2, flexibility=1, durability=210,
enchantability=8, mining_speed=4, toughness=1, armor_durability=12,
groups=("metal", "stone"), textures=("rough", "metallic")),
# Half rock, half metal - grouped as both so stone and metal modules take it.
M("refined_radiance", "create", "metal", "Refined Radiance", "create:refined_radiance",
[{"item": "create:refined_radiance", "value": 1.0}],
tier=6, hardness=7.4, density=2.0, flexibility=4, durability=2500,
enchantability=28, mining_speed=12, toughness=4, armor_durability=40,
armor_toughness=3.0, textures=("emissive", "metallic"),
properties={"default": {"fire_proof": True,
"emissive": {"sky": 15, "block": 15}},
"tool": {"luminious_learning": "1"},
"handheld": {"illager_bane": "1"}}),
M("shadow_steel", "create", "metal", "Shadow Steel", "create:shadow_steel",
[{"item": "create:shadow_steel", "value": 1.0}],
tier=6, hardness=8.2, density=4.8, flexibility=2, durability=2700,
enchantability=14, mining_speed=10, toughness=4, armor_durability=42,
armor_toughness=3.5,
properties={"default": {"fire_proof": True},
"handheld": {"leeching": "1"}}),
# Create's two chapter-end materials are deliberately a matched pair:
# radiance enchants and glows, shadow steel hits and drains.
# ----------------------------------------------------------------- Aerospace
# Both Air War and Cosmonautics add titanium. This is one material fed by
# tags so either mod (or both) supplies it; see the c: tag files.
M("titanium", "cosmonautics", "metal", "Titanium", "rocketnautics:titanium_ingot",
[{"item": "rocketnautics:titanium_ingot", "value": 1.0},
{"item": "rocketnautics:titanium_nugget", "value": NUGGET},
{"item": "rocketnautics:titanium_sheet", "value": 1.0},
{"item": "rocketnautics:titanium_block", "value": BLOCK}],
tier=4, hardness=5.8, density=1.6, flexibility=3.5, durability=1150,
enchantability=11, mining_speed=9, toughness=2, armor_durability=32,
armor_toughness=1.5,
properties={"default": {
"fire_proof": True,
"attributes": [
# The aerospace metal, so it glides. Heavy armour subtracts
# "-30 - density*2" from glide efficiency; this hands a little
# back rather than cancelling it, and only on the chest, where
# elytra flight is decided.
attribute("miapi:generic.elytra_glide_efficiency", 10, "chest"),
{"attribute": "generic.attack_speed", "value": "0.06",
"operation": "+", "slot": "mainhand"},
],
}}),
# Tinkers' cobalt: light, fast, very durable, damage only average. Heat
# resistance is what separates it from steel.
M("titanium_alloy", "cosmonautics", "metal", "Titanium Alloy",
"rocketnautics:titanium_alloy",
[{"item": "rocketnautics:titanium_alloy", "value": 1.0},
{"item": "rocketnautics:titanium_alloy_nugget", "value": NUGGET},
{"item": "rocketnautics:titanium_alloy_sheet", "value": 1.0},
{"item": "rocketnautics:titanium_alloy_block", "value": BLOCK}],
tier=5, hardness=6.8, density=2.2, flexibility=3, durability=1900,
enchantability=12, mining_speed=10, toughness=3, armor_durability=36,
armor_toughness=2.0, properties={"default": {"fire_proof": True}}),
# Create Propulsion: Simulated's own ore, and the only platinum in the pack.
M("platinum", "createpropulsion", "metal", "Platinum",
"createpropulsion:platinum_ingot",
[{"item": "createpropulsion:platinum_ingot", "value": 1.0},
{"item": "createpropulsion:platinum_nugget", "value": NUGGET},
{"item": "createpropulsion:platinum_sheet", "value": 1.0},
{"item": "createpropulsion:platinum_block", "value": BLOCK}],
tier=4, hardness=5.0, density=5.7, flexibility=3, durability=680,
enchantability=24, mining_speed=7, toughness=2, armor_durability=24,
armor_toughness=1.0, textures=("metallic", "shiny"),
properties={"default": {"fire_proof": True},
"handheld": speed(-0.08)}),
# Real platinum: nearly as dense as osmium, but soft, so it swings slow
# and hits no harder than steel. What it is actually for is the precious
# metal's bargain - gold-grade enchantability without gold's fragility -
# and it melts at 1768C, hence the heat proofing.
# -------------------------------------------------------------- AeroEngine
M("aviation_alloy", "aeroengineering", "metal", "Aviation Alloy",
"aeroengineering:aviation_alloy_ingot",
[{"item": "aeroengineering:aviation_alloy_ingot", "value": 1.0},
{"item": "aeroengineering:aviation_alloy_sheet", "value": 1.0}],
tier=5, hardness=6.6, density=2.4, flexibility=4, durability=1650,
enchantability=14, mining_speed=10, toughness=3, armor_durability=35,
armor_toughness=2.0, textures=("metallic", "bright"),
properties={"default": {"fire_proof": True},
"handheld": speed(0.08)}),
# Iron superheated with netherite powder: a turbine superalloy. Light and
# heat-proof like titanium, harder and more flexible, worse to enchant -
# it sits between titanium and titanium alloy, which is where its recipe
# sits too.
# ------------------------------------------------------- Create: The Air War
M("sulfur", "air_war", "crystal", "Sulfur", "create_the_air_wars:raw_sulfur",
[{"item": "create_the_air_wars:raw_sulfur", "value": 1.0},
{"item": "create_the_air_wars:crashedsulfur", "value": 1.0}],
tier=2, hardness=3.0, density=2.0, flexibility=1, durability=140,
enchantability=14, mining_speed=4, armor_durability=6,
groups=("crystal",), textures=("crystal", "rough"),
properties={"default": {"immolate": "2"}}),
# Barely a tool material - it is here because it burns.
M("amalgam", "air_war", "metal", "Amalgam", "create_the_air_wars:rough_amalgam",
[{"item": "create_the_air_wars:rough_amalgam", "value": 1.0},
{"item": "create_the_air_wars:crushed_amalgam", "value": 1.0}],
tier=3, hardness=4.4, density=5.5, flexibility=3, durability=320,
enchantability=21, mining_speed=7, armor_durability=15,
textures=("metallic", "shiny"),
properties={"handheld": {"leeching": "0.3", **speed(-0.08)}}),
# Mercury alloy: heavy, quick to enchant, quietly poisonous.
# -------------------------------------------------------------- Ice and Fire
M("silver", "iceandfire", "metal", "Silver", "iceandfire:silver_ingot",
ingots("iceandfire", "silver_ingot", "silver_nugget", "silver_block"),
tier=3, hardness=4.6, density=3.4, flexibility=2, durability=220,
enchantability=20, mining_speed=7, armor_durability=13,
textures=("metallic", "bright"),
properties={"handheld": {"fake_enchants": {"minecraft:smite": 2}}}),
# Folklore does the design work: soft metal, great for enchanting,
# murder on the undead.
M("dragonbone", "iceandfire", "bone", "Dragonbone", "iceandfire:dragonbone",
[{"item": "iceandfire:dragonbone", "value": 1.0},
{"item": "iceandfire:dragon_bone_block", "value": 4.0}],
tier=4, hardness=6.2, density=4.4, flexibility=3, durability=700,
enchantability=12, mining_speed=7, toughness=2, armor_durability=24,
groups=("bone",), hidden_groups=("gem_armor",), textures=("rough",),
properties={"head": {"fracturing": "10"},
# Fire on the strike, the way Ice and Fire's own flamed
# dragonbone sword burns what it hits. Fire Aspect rather
# than MIAPI's `immolate`, which despite the name is bonus
# damage against something already burning and is marked
# unimplemented in MIAPI's own wiki. Ice and Fire ships one
# dragon bone item for all three kinds of dragon, so this
# cannot be the fire dragon's alone; the fire dragonscales
# are the only element-specific dragon material there is.
"handheld": {"fake_enchants": {"minecraft:fire_aspect": 1}}}),
# Vanilla bone with the numbers pushed to diamond tier; keeps the
# fracturing quirk MIAPI gives bone. The `bone` group already builds
# grips, handles and hafts wherever Arsenal and Archery take bone;
# `gem_armor` on top of it lets a piece sit in an armour socket too, so a
# dragon's bones can be set into a suit rather than only shaped into one.
M("sea_serpent_fang", "iceandfire", "bone", "Sea Serpent Fang",
"iceandfire:sea_serpent_fang",
[{"item": "iceandfire:sea_serpent_fang", "value": 1.0}],
tier=4, hardness=6.0, density=3.0, flexibility=4, durability=760,
enchantability=16, mining_speed=7, toughness=2, armor_durability=26,
groups=("bone",), hidden_groups=("gem_armor",), textures=("rough", "shiny"),
# All of it under `default`, so a fang set into an armour socket counts
# as much as one shaped into the piece - a gem module is not tagged
# `armor` or `handheld` and would never see anything filed there. What
# the fang is worth is decided by the slot instead: worn, it breathes;
# held, it fights and mines.
properties={
"default": {
"attributes": [
# Ice and Fire's own sea serpent armour grants water
# breathing, and that is the whole reason to hunt one. Half a
# lung per module and capped at 1, the trade the space set
# makes: two fangs worn - two sockets, two pieces, or a
# socketed piece built of it - and not one held.
*(attribute(WATER_BREATHING, 0.5, slot)
for slot in ("head", "chest", "legs", "feet")),
# Held rather than worn, and only under water. Vanilla mines
# at a fifth of the usual speed with your eyes submerged;
# 0.6 on a base of 0.2 is four times better than that off a
# single fang module and past dry-land speed off two.
attribute(SUBMERGED_MINING_SPEED, 0.6, "mainhand"),
# And the same water makes a serpent's tooth bite: a tenth
# more damage and a tenth faster a module, capped at half
# again - see WaterCombat.java.
attribute(WATER_COMBAT, 0.10, "mainhand"),
],
},
"boot": {"fake_enchants": {"minecraft:depth_strider": 1}},
}),
# Lighter and springier than dragon bone and quicker to enchant, but
# softer: a serpent's tooth, not a wyrm's femur.
M("witherbone", "iceandfire", "bone", "Witherbone", "iceandfire:witherbone",
[{"item": "iceandfire:witherbone", "value": 1.0},
{"item": "iceandfire:wither_shard", "value": 0.25}],
tier=3, hardness=5.8, density=4.6, flexibility=3, durability=520,
enchantability=10, mining_speed=6, toughness=1, armor_durability=20,
groups=("bone",), textures=("rough",),
properties={"head": {"fracturing": "15"}, "handheld": {"leeching": "0.5"}}),
M("hippogryph_talon", "iceandfire", "bone", "Talon", "iceandfire:hippogryph_talon",
[{"item": "iceandfire:hippogryph_talon", "value": 1.0}],
tier=3, hardness=6.6, density=2.4, flexibility=2, durability=300,
enchantability=14, mining_speed=6, armor_durability=14,
groups=("bone",), textures=("rough",),
properties={"handheld": speed(0.08)}),
# Sharp and light: high hardness, low durability, fast in hand.
M("sapphire", "iceandfire", "crystal", "Sapphire", "iceandfire:sapphire_gem",
[{"item": "iceandfire:sapphire_gem", "value": 1.0},
{"item": "iceandfire:sapphire_block", "value": BLOCK}],
tier=4, hardness=6.2, density=2.2, flexibility=0, durability=1200,
enchantability=14, mining_speed=8, toughness=2, armor_durability=30,
groups=("crystal", "gem"), textures=("crystal", "bright")),
M("pixie_dust", "iceandfire", "crystal", "Pixie Dust", "iceandfire:pixie_dust",
[{"item": "iceandfire:pixie_dust", "value": 1.0}],
tier=3, hardness=4.0, density=0.5, flexibility=6, durability=220,
enchantability=34, mining_speed=9, armor_durability=10,
groups=("crystal",), textures=("emissive", "crystal"),
properties={"default": {"emissive": {"sky": 7, "block": 7},
"luminious_learning": "1"}}),
# Highest enchantability in the set and almost no durability to go with
# it - the rose gold extreme.
M("dread_shard", "iceandfire", "crystal", "Dread", "iceandfire:dread_shard",
[{"item": "iceandfire:dread_shard", "value": 1.0}],
tier=5, hardness=6.4, density=3.0, flexibility=2, durability=1100,
enchantability=16, mining_speed=8, toughness=2, armor_durability=28,
groups=("crystal", "metal"), textures=("crystal", "rough"),
properties={"default": {"leeching": "1"}}),
M("ghost_ingot", "iceandfire", "metal", "Phantasmal", "iceandfire:ghost_ingot",
[{"item": "iceandfire:ghost_ingot", "value": 1.0}],
tier=5, hardness=6.0, density=0.6, flexibility=5, durability=1300,
enchantability=26, mining_speed=10, toughness=2, armor_durability=28,
textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 6, "block": 6}},
"handheld": speed(0.12)}),
# Almost no density: the fastest-swinging material here.
M("dragonsteel_fire", "iceandfire", "metal", "Fire Dragonsteel",
"iceandfire:dragonsteel_fire_ingot",
[{"item": "iceandfire:dragonsteel_fire_ingot", "value": 1.0},
{"item": "iceandfire:dragonsteel_fire_block", "value": BLOCK}],
tier=7, hardness=9.0, density=4.0, flexibility=3, durability=3600,
enchantability=18, mining_speed=13, toughness=5, armor_durability=50,
armor_toughness=5.0, textures=("emissive", "metallic"),
properties={"default": {"fire_proof": True,
"emissive": {"sky": 6, "block": 6}},
"handheld": {"immolate": "3"}}),
M("dragonsteel_ice", "iceandfire", "metal", "Ice Dragonsteel",
"iceandfire:dragonsteel_ice_ingot",
[{"item": "iceandfire:dragonsteel_ice_ingot", "value": 1.0},
{"item": "iceandfire:dragonsteel_ice_block", "value": BLOCK}],
tier=7, hardness=8.8, density=4.2, flexibility=3, durability=3600,
enchantability=18, mining_speed=13, toughness=5, armor_durability=50,
armor_toughness=5.0, textures=("metallic", "bright"),
properties={"armor": {"fake_item_tag": ["minecraft:freeze_immune_wearables"]},
"boot": {"can_walk_on_snow": True}}),
M("dragonsteel_lightning", "iceandfire", "metal", "Lightning Dragonsteel",
"iceandfire:dragonsteel_lightning_ingot",
[{"item": "iceandfire:dragonsteel_lightning_ingot", "value": 1.0},
{"item": "iceandfire:dragonsteel_lightning_block", "value": BLOCK}],
tier=7, hardness=8.8, density=3.4, flexibility=4, durability=3600,
enchantability=20, mining_speed=14, toughness=5, armor_durability=50,
armor_toughness=5.0, textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 8, "block": 8}},
"handheld": speed(0.15)}),
# The three dragonsteels share a stat line and differ only in behaviour,
# exactly how Ice and Fire treats them.
M("troll_leather_forest", "iceandfire", "fabric", "Forest Troll Leather",
"iceandfire:troll_leather_forest",
[{"item": "iceandfire:troll_leather_forest", "value": 1.0}],
tier=3, hardness=3.6, density=1.8, flexibility=5, durability=400,
enchantability=12, mining_speed=0, toughness=2, armor_durability=22,
groups=("fabric", "leather"), textures=("fabric",),
mining_level=MINING_LEVEL[1],
properties={"armor": {"fake_enchants": {"minecraft:projectile_protection": 2}}}),
M("troll_leather_frost", "iceandfire", "fabric", "Frost Troll Leather",
"iceandfire:troll_leather_frost",
[{"item": "iceandfire:troll_leather_frost", "value": 1.0}],
tier=3, hardness=3.6, density=1.8, flexibility=5, durability=400,
enchantability=12, mining_speed=0, toughness=2, armor_durability=22,
groups=("fabric", "leather"), textures=("fabric",),
mining_level=MINING_LEVEL[1],
properties={"armor": {"fake_enchants": {"minecraft:projectile_protection": 2},
"fake_item_tag": ["minecraft:freeze_immune_wearables"]},
"boot": {"can_walk_on_snow": True}}),
M("troll_leather_mountain", "iceandfire", "fabric", "Mountain Troll Leather",
"iceandfire:troll_leather_mountain",
[{"item": "iceandfire:troll_leather_mountain", "value": 1.0}],
tier=3, hardness=3.6, density=1.8, flexibility=5, durability=400,
enchantability=12, mining_speed=0, toughness=2, armor_durability=22,
groups=("fabric", "leather"), textures=("fabric",),
mining_level=MINING_LEVEL[1],
properties={"armor": {"fake_enchants": {"minecraft:projectile_protection": 2}}}),
# Ice and Fire's troll armour cuts projectile damage; projectile
# protection is the closest MIAPI-native equivalent.
M("stymphalian_feather", "iceandfire", "fletching", "Stymphalian",
"iceandfire:stymphalian_bird_feather",
[{"item": "iceandfire:stymphalian_bird_feather", "value": 1.0},
{"item": "iceandfire:stymphalian_feather_bundle", "value": 4.0}],
tier=3, hardness=3.4, density=0.4, flexibility=6, durability=140,
enchantability=15, mining_speed=0, armor_durability=8,
groups=("fletching", "feather"), textures=("feather",),
mining_level=MINING_LEVEL[1]),
# Metal feathers - sharper than a normal fletching, hence the hardness.
M("amphithere_feather", "iceandfire", "fletching", "Amphithere",
"iceandfire:amphithere_feather",
[{"item": "iceandfire:amphithere_feather", "value": 1.0}],
tier=3, hardness=2.6, density=0.3, flexibility=7, durability=120,
enchantability=18, mining_speed=0, armor_durability=8,
groups=("fletching", "feather"), textures=("feather",),
mining_level=MINING_LEVEL[1]),
# -------------------------------------------------- Iron's Spells 'n Spellbooks
# The two essences are gems and deliberately strong: they are worth using
# over a tier-6 metal only because of what they grant, since their raw
# numbers are no better and their durability is worse.
M("arcane_essence", "irons_spellbooks", "crystal", "Arcane",
"irons_spellbooks:arcane_essence",
[{"item": "irons_spellbooks:arcane_essence", "value": 1.0}],
tier=6, hardness=6.8, density=1.4, flexibility=5, durability=2400,
enchantability=32, mining_speed=11, toughness=3, armor_durability=38,
armor_toughness=2.5, groups=("crystal", "gem"), textures=("crystal", "bright"),
# Everything hangs off `default`. A gem socketed into armour is not
# tagged `armor` or `handheld` - the gem modules declare which material
# properties they accept and both list only `default` plus their own gem
# tags - so anything filed elsewhere silently never applied.
#
# Each slot gets its own modifier rather than one `armor`-wide one. That
# is what lets a helmet be worth more than boots, and it stops a sword
# from advertising a bonus "when worn", which is what a slot of `armor`
# on a weapon reads as.
properties={
"default": {
"emissive": {"sky": 6, "block": 6},
"attributes": [
attribute("irons_spellbooks:max_mana", 1300, "head"),
attribute("irons_spellbooks:max_mana", 900, "chest"),
attribute("irons_spellbooks:max_mana", 800, "legs"),
attribute("irons_spellbooks:max_mana", 700, "feet"),
# Held, not worn.
attribute("irons_spellbooks:max_mana", 900, "mainhand"),
attribute("irons_spellbooks:max_mana", 400, "offhand"),
attribute("irons_spellbooks:mana_regen", 0.15, "any", "*"),
attribute("irons_spellbooks:spell_power", 0.10, "mainhand", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.05, "mainhand", "*"),
],
},
}),
# These stack per module: a piece built out of arcane essence that also
# carries an arcane gem counts twice.
M("cinder_essence", "irons_spellbooks", "crystal", "Cinder",
"irons_spellbooks:cinder_essence",
[{"item": "irons_spellbooks:cinder_essence", "value": 1.0}],
tier=6, hardness=7.4, density=2.6, flexibility=3, durability=2400,
enchantability=20, mining_speed=11, toughness=4, armor_durability=40,
armor_toughness=3.0, groups=("crystal", "gem"), textures=("emissive", "crystal"),
# As with arcane essence, all of this is under `default` so it survives
# being socketed as a gem rather than used as the armour plate itself.
properties={
"default": {
"fire_proof": True,
"emissive": {"sky": 8, "block": 8},
"immolate": "3",
# One armour piece is enough: the handler treats anything at or
# above 1 as immune, so this is genuine immunity rather than a
# resistance that stacks up to it.
"attributes": [
# Slot `any`, so a single gem grants immunity wherever it
# sits - worn or held. The handler treats anything at or
# above 1 as immune, and the attribute is capped at 1, so
# extra pieces add nothing and nothing can dilute it.
attribute(FIRE_IMMUNITY, 1, "any"),
attribute("irons_spellbooks:fire_magic_resist", 0.20, "any", "*"),
attribute("irons_spellbooks:fire_spell_power", 0.20, "mainhand", "*"),
],
},
}),
# The one material made of an item this mod adds itself. It lives in the
# Iron's Spells pack even though its ingredient always exists, because
# everything it grants is an Iron's Spells attribute: without that mod
# there is nothing for the material to say.
M("arcana_core", "irons_spellbooks", "crystal", "Arcana Core",
"cmmodular:arcana_core",
[{"item": "cmmodular:arcana_core", "value": 1.0}],
tier=7, hardness=7.6, density=1.2, flexibility=5, durability=3400,
enchantability=40, mining_speed=12, toughness=4, armor_durability=48,
armor_toughness=3.0, groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={
"default": {
"emissive": {"sky": 10, "block": 10},
# Iron's Spells limits a caster three ways - a mana pool, a
# cooldown per spell and a cast time - and this is meant to end
# all three, so all three are here.
"attributes": [
# Mana: a pool nothing can empty, refilled a hundred times
# over. There is no "infinite" to ask for, so this is it.
attribute("irons_spellbooks:max_mana", 1000000, "any"),
attribute("irons_spellbooks:mana_regen", 100, "any", "*"),
# Cooldown and cast time are read as a factor on a base of 1
# and spent as `time * (2 - value)`, so `*` with 1 puts the
# value at 2 and the time at nothing. Iron's Spells floors
# both at zero, so a second core cannot push them negative.
attribute("irons_spellbooks:cooldown_reduction", 1.0, "any", "*"),
attribute("irons_spellbooks:cast_time_reduction", 1.0, "any", "*"),
# Ten times the power, by the same reading: 1 + 9.
attribute("irons_spellbooks:spell_power", 9.0, "any", "*"),
],
},
}),
# Deliberately absurd, and priced that way: four arcane essence, four
# cinder essence and a nether star, all of which are already endgame.
# The mod's three craftable metals, for completeness - ordinary materials
# that happen to sit late in its progression.
M("mithril", "irons_spellbooks", "metal", "Mithril",
"irons_spellbooks:mithril_ingot",
[{"item": "irons_spellbooks:mithril_ingot", "value": 1.0}],
tier=5, hardness=6.4, density=1.2, flexibility=4, durability=1800,
enchantability=24, mining_speed=11, toughness=3, armor_durability=36,
armor_toughness=2.0, textures=("metallic", "bright"),
properties={"handheld": speed(0.12)}),
# Light enough to swing fast and enchant well, in the Tolkien sense.
# "Arcane Metal" rather than plain Arcane, which is what Iron's Spells calls
# this material itself: the item is an Arcane Ingot, and a material is named
# for the substance rather than the shape it is traded in. Plain Arcane is
# taken here by the essence above, and the metal is the one of the two that
# can afford the longer name.
M("arcane_metal", "irons_spellbooks", "metal", "Arcane Metal",
"irons_spellbooks:arcane_ingot",
[{"item": "irons_spellbooks:arcane_ingot", "value": 1.0}],
tier=5, hardness=6.2, density=2.8, flexibility=3, durability=1700,
enchantability=26, mining_speed=9, toughness=3, armor_durability=34,
armor_toughness=2.0,
# The one thing arcane metal is for: spells come back faster. Cooldown
# reduction is the whole reason to build out of it rather than out of
# mithril, so it is deliberately the strongest effect on any metal here.
#
# Under `default`, not `handheld`, so armour plated in it counts too - a
# caster wants the set, not just the sword. Per-slot rather than one
# `armor`-wide modifier, for the same reasons as arcane essence: a helmet
# can be worth more than boots, and a weapon reads as a held bonus
# instead of claiming something "when worn".
#
# Iron's Spells treats the attribute as a factor on a base of 1, hence the
# `*` operation - a flat `+` would be added to a base of zero and do
# nothing - and spends it as `cooldown * (2 - value)`. So +0.10 is 10% off
# the wait, and +1.00 in total would be instant casting.
#
# These stack per module, and that is what sets the numbers. A weapon is
# about four modules, so one built entirely of arcane metal is 40% - well
# past the 25% of Iron's Spells' own best staff, which is the point. The
# armour values are smaller because a full set is a dozen modules: all of
# it in arcane metal lands near 45%, so even a player wearing the set and
# holding the staff stays under the 100% the formula bottoms out at.
properties={"default": {"attributes": [
attribute("irons_spellbooks:cooldown_reduction", 0.10, "mainhand", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.05, "head", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.04, "chest", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.03, "legs", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.03, "feet", "*"),
attribute("irons_spellbooks:cooldown_reduction", 0.03, "offhand", "*"),
attribute("irons_spellbooks:spell_power", 0.05, "mainhand", "*"),
]}}),
# ------------------------------------------------- Immersive Engineering
# Steel, lead, uranium and silver are not here - Immersive Engineering adds
# those too, so they live in the tag-fed shared packs above and accept
# either mod's ingots.
M("aluminum", "immersiveengineering", "metal", "Aluminium",
"immersiveengineering:ingot_aluminum",
ingots("immersiveengineering", "ingot_aluminum", "nugget_aluminum",
extra=[{"item": "immersiveengineering:plate_aluminum", "value": 1.0}]),
tier=3, hardness=4.0, density=1.2, flexibility=3, durability=260,
enchantability=17, mining_speed=6, armor_durability=14,
textures=("metallic", "bright"), properties={"handheld": speed(0.10)}),
# Light and corrosion-proof but soft - the cheap way to a fast tool, at
# the cost of everything else.
M("nickel", "immersiveengineering", "metal", "Nickel",
"immersiveengineering:ingot_nickel",
ingots("immersiveengineering", "ingot_nickel", "nugget_nickel",
extra=[{"item": "immersiveengineering:plate_nickel", "value": 1.0}]),
tier=3, hardness=5.4, density=4.4, flexibility=1, durability=480,
enchantability=10, mining_speed=6, toughness=1, armor_durability=20,
armor_toughness=0.5),
# Hard, tough and stubbornly corrosion resistant; dull to enchant.
M("constantan", "immersiveengineering", "metal", "Constantan",
"immersiveengineering:ingot_constantan",
ingots("immersiveengineering", "ingot_constantan", "nugget_constantan",
extra=[{"item": "immersiveengineering:plate_constantan", "value": 1.0}]),
tier=4, hardness=5.6, density=4.0, flexibility=2, durability=640,
enchantability=14, mining_speed=7, toughness=2, armor_durability=24),
# A copper-nickel alloy prized for not changing under heat or strain,
# so it is the steady middle option: no weakness, no standout.
M("electrum", "immersiveengineering", "metal", "Electrum",
"immersiveengineering:ingot_electrum",
ingots("immersiveengineering", "ingot_electrum", "nugget_electrum",
extra=[{"item": "immersiveengineering:plate_electrum", "value": 1.0}]),
tier=3, hardness=4.4, density=3.6, flexibility=2, durability=260,
enchantability=26, mining_speed=9, armor_durability=14,
textures=("metallic", "bright"),
properties={"tool": {"luminious_learning": "0.5"}}),
# Gold-silver alloy, so it inherits gold's bargain: superb to enchant,
# falls apart quickly.
M("hop_graphite", "immersiveengineering", "metal", "Graphite",
"immersiveengineering:ingot_hop_graphite",
ingots("immersiveengineering", "ingot_hop_graphite", None,
extra=[{"item": "immersiveengineering:plate_hop_graphite", "value": 1.0}]),
tier=4, hardness=4.2, density=2.0, flexibility=1, durability=520,
enchantability=12, mining_speed=10, toughness=2, armor_durability=18,
textures=("rough", "metallic"),
properties={"default": {"fire_proof": True}, "handheld": speed(0.08)}),
# Graphite is a dry lubricant and shrugs off heat, hence the quick swing,
# high mining speed and fireproofing - but it is soft, so it hits weakly.
# ------------------------------------------------------------------ Ender IO
# A whole alloy ladder, each alloy named after what was smelted into it.
M("redstone_alloy", "enderio", "metal", "Redstone Alloy",
"enderio:redstone_alloy_ingot",
ingots("enderio", "redstone_alloy_ingot", "redstone_alloy_nugget"),
tier=3, hardness=4.4, density=3.2, flexibility=3, durability=320,
enchantability=20, mining_speed=7, armor_durability=16,
properties={"default": {"emissive": {"sky": 3, "block": 3}}}),
M("conductive_alloy", "enderio", "metal", "Conductive Alloy",
"enderio:conductive_alloy_ingot",
ingots("enderio", "conductive_alloy_ingot", "conductive_alloy_nugget"),
tier=3, hardness=5.0, density=3.8, flexibility=2, durability=400,
enchantability=15, mining_speed=7, armor_durability=18),
M("pulsating_alloy", "enderio", "metal", "Pulsating Alloy",
"enderio:pulsating_alloy_ingot",
ingots("enderio", "pulsating_alloy_ingot", "pulsating_alloy_nugget"),
tier=4, hardness=5.6, density=3.4, flexibility=4, durability=800,
enchantability=18, mining_speed=9, toughness=2, armor_durability=24,
properties={"default": {"emissive": {"sky": 4, "block": 4}}}),
# Ender-infused, so it is quick and light for its tier.
M("energetic_alloy", "enderio", "metal", "Energetic Alloy",
"enderio:energetic_alloy_ingot",
ingots("enderio", "energetic_alloy_ingot", "energetic_alloy_nugget"),
tier=4, hardness=5.4, density=3.0, flexibility=3, durability=700,
enchantability=24, mining_speed=9, toughness=1, armor_durability=22,
textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 8, "block": 8},
"luminious_learning": "0.5"}}),
# Glowstone and gold: bright and very enchantable, not very sturdy.
M("vibrant_alloy", "enderio", "metal", "Vibrant Alloy",
"enderio:vibrant_alloy_ingot",
ingots("enderio", "vibrant_alloy_ingot", "vibrant_alloy_nugget"),
tier=5, hardness=6.4, density=3.0, flexibility=4, durability=1700,
enchantability=22, mining_speed=10, toughness=3, armor_durability=34,
armor_toughness=2.0, textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 8, "block": 8}}}),
M("soularium", "enderio", "metal", "Soularium", "enderio:soularium_ingot",
ingots("enderio", "soularium_ingot", "soularium_nugget"),
tier=4, hardness=5.2, density=4.0, flexibility=2, durability=650,
enchantability=20, mining_speed=8, toughness=1, armor_durability=22,
properties={"default": {"leeching": "0.5"}}),
# Gold soaked in soul sand, so it takes a little life with each hit.
M("dark_steel", "enderio", "metal", "Dark Steel", "enderio:dark_steel_ingot",
ingots("enderio", "dark_steel_ingot", "dark_steel_nugget"),
tier=5, hardness=6.8, density=4.6, flexibility=1.5, durability=1800,
enchantability=12, mining_speed=9, toughness=3, armor_durability=34,
armor_toughness=2.0, properties={"default": {"fire_proof": True}}),
# Steel taken through obsidian: the durable, unexciting tier-5 option.
M("end_steel", "enderio", "metal", "End Steel", "enderio:end_steel_ingot",
ingots("enderio", "end_steel_ingot", "end_steel_nugget"),
tier=6, hardness=7.6, density=4.4, flexibility=2, durability=2600,
enchantability=14, mining_speed=11, toughness=4, armor_durability=42,
armor_toughness=3.5, properties={"default": {"fire_proof": True}}),
M("ender_crystal", "enderio", "crystal", "Ender Crystal", "enderio:ender_crystal",
[{"item": "enderio:ender_crystal", "value": 1.0}],
tier=5, hardness=6.0, density=1.6, flexibility=4, durability=1200,
enchantability=24, mining_speed=9, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 6, "block": 6}}}),
M("vibrant_crystal", "enderio", "crystal", "Vibrant Crystal",
"enderio:vibrant_crystal",
[{"item": "enderio:vibrant_crystal", "value": 1.0}],
tier=5, hardness=6.4, density=1.6, flexibility=4, durability=1400,
enchantability=26, mining_speed=10, toughness=2, armor_durability=30,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 9, "block": 9}}}),
M("pulsating_crystal", "enderio", "crystal", "Pulsating Crystal",
"enderio:pulsating_crystal",
[{"item": "enderio:pulsating_crystal", "value": 1.0}],
tier=5, hardness=5.8, density=1.5, flexibility=5, durability=1200,
enchantability=25, mining_speed=10, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 5, "block": 5}}}),
M("prescient_crystal", "enderio", "crystal", "Prescient Crystal",
"enderio:prescient_crystal",
[{"item": "enderio:prescient_crystal", "value": 1.0}],
tier=5, hardness=5.6, density=1.5, flexibility=4, durability=1150,
enchantability=30, mining_speed=9, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"luminious_learning": "1"}}),
# The one you pick for enchanting rather than for stats.
M("enticing_crystal", "enderio", "crystal", "Enticing Crystal",
"enderio:enticing_crystal",
[{"item": "enderio:enticing_crystal", "value": 1.0}],
tier=5, hardness=5.8, density=1.6, flexibility=4, durability=1200,
enchantability=24, mining_speed=9, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"attributes": [
attribute("minecraft:generic.luck", 1, "any")]}}),
M("weather_crystal", "enderio", "crystal", "Weather Crystal",
"enderio:weather_crystal",
[{"item": "enderio:weather_crystal", "value": 1.0}],
tier=5, hardness=6.0, density=1.6, flexibility=4, durability=1250,
enchantability=24, mining_speed=9, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 6, "block": 6}}}),
# ------------------------------------------------------- Applied Energistics
M("certus_quartz", "ae2", "crystal", "Certus Quartz",
"ae2:certus_quartz_crystal",
[{"item": "ae2:certus_quartz_crystal", "value": 1.0}],
tier=3, hardness=5.0, density=2.2, flexibility=0, durability=420,
enchantability=16, mining_speed=7, toughness=1, armor_durability=16,
groups=("crystal", "gem"), textures=("crystal", "bright")),
# Quartz with a charge to it - brittle, like all quartz.
M("charged_certus_quartz", "ae2", "crystal", "Charged Certus",
"ae2:charged_certus_quartz_crystal",
[{"item": "ae2:charged_certus_quartz_crystal", "value": 1.0}],
tier=4, hardness=5.4, density=2.2, flexibility=0, durability=700,
enchantability=22, mining_speed=9, toughness=1, armor_durability=22,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 5, "block": 5}}}),
M("fluix", "ae2", "crystal", "Fluix", "ae2:fluix_crystal",
[{"item": "ae2:fluix_crystal", "value": 1.0}],
tier=5, hardness=6.2, density=2.0, flexibility=2, durability=1300,
enchantability=24, mining_speed=10, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 6, "block": 6}}}),
# -------------------------------------------------------------- Ars Nouveau
M("source_gem", "ars_nouveau", "crystal", "Source", "ars_nouveau:source_gem",
[{"item": "ars_nouveau:source_gem", "value": 1.0}],
tier=4, hardness=5.2, density=1.4, flexibility=5, durability=600,
enchantability=30, mining_speed=9, toughness=1, armor_durability=20,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 7, "block": 7},
"luminious_learning": "1"}}),
# Condensed magic: superb to enchant, not much use as a blade.
# ---------------------------------------------------------------- Occultism
M("iesnium", "occultism", "metal", "Iesnium", "occultism:iesnium_ingot",
ingots("occultism", "iesnium_ingot", "iesnium_nugget"),
tier=5, hardness=6.6, density=4.2, flexibility=2, durability=1600,
enchantability=16, mining_speed=9, toughness=3, armor_durability=32,
armor_toughness=2.0, properties={"default": {"fire_proof": True}}),
# Only found in the Nether, so it comes fireproof.
M("spirit_attuned_gem", "occultism", "crystal", "Spirit Attuned",
"occultism:spirit_attuned_gem",
[{"item": "occultism:spirit_attuned_gem", "value": 1.0}],
tier=5, hardness=5.8, density=1.8, flexibility=4, durability=1100,
enchantability=28, mining_speed=9, toughness=2, armor_durability=26,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"leeching": "0.5"}}),
# ------------------------------------------------------- Industrial Foregoing
M("pink_slime", "industrialforegoing", "metal", "Pink Slime",
"industrialforegoing:pink_slime_ingot",
[{"item": "industrialforegoing:pink_slime_ingot", "value": 1.0}],
tier=3, hardness=3.8, density=1.0, flexibility=8, durability=460,
enchantability=22, mining_speed=6, toughness=1, armor_durability=20,
textures=("rough",), properties={"handheld": speed(0.12)}),
# Tinkers' slime materials in spirit: floppy, springy, absurdly flexible.
# ------------------------------------------------------------------- NauTec
M("cast_iron", "nautec", "metal", "Cast Iron", "nautec:cast_iron_ingot",
ingots("nautec", "cast_iron_ingot", "cast_iron_nugget"),
tier=3, hardness=5.2, density=4.8, flexibility=0.5, durability=380,
enchantability=9, mining_speed=5, toughness=1, armor_durability=18),
# Hard and heavy but brittle - real cast iron cracks rather than bends.
M("atlantic_gold", "nautec", "metal", "Atlantic Gold",
"nautec:atlantic_gold_ingot",
ingots("nautec", "atlantic_gold_ingot", "atlantic_gold_nugget"),
tier=4, hardness=4.8, density=3.4, flexibility=3, durability=520,
enchantability=28, mining_speed=10, armor_durability=20,
textures=("metallic", "bright"),
properties={"default": {"luminious_learning": "0.5"}}),
M("aquarine_steel", "nautec", "metal", "Aquarine Steel",
"nautec:aquarine_steel_ingot",
[{"item": "nautec:aquarine_steel_ingot", "value": 1.0},
{"item": "nautec:aquarine_steel_compound", "value": 1.0}],
tier=5, hardness=6.4, density=3.6, flexibility=3, durability=1650,
enchantability=18, mining_speed=9, toughness=3, armor_durability=34,
armor_toughness=2.0,
properties={"default": {"fake_enchants": {"minecraft:respiration": 1}}}),
# ----------------------------------------------------------- Superb Warfare
M("tungsten", "superbwarfare", "metal", "Tungsten",
"superbwarfare:tungsten_ingot",
[{"item": "superbwarfare:tungsten_ingot", "value": 1.0}],
tier=5, hardness=7.2, density=5.9, flexibility=0.5, durability=1750,
enchantability=8, mining_speed=8, toughness=3, armor_durability=34,
armor_toughness=2.5, properties={"default": {"fire_proof": True},
"handheld": speed(-0.12)}),
# Highest melting point of any metal and nearly as dense as osmium: it
# hits like a truck and swings like one too.
M("cemented_carbide", "superbwarfare", "metal", "Cemented Carbide",
"superbwarfare:cemented_carbide_ingot",
[{"item": "superbwarfare:cemented_carbide_ingot", "value": 1.0}],
tier=6, hardness=8.4, density=5.2, flexibility=0.5, durability=2500,
enchantability=10, mining_speed=13, toughness=4, armor_durability=40,
armor_toughness=3.0, properties={"default": {"fire_proof": True},
"handheld": speed(-0.08)}),
# What real cutting tools are tipped with - the best miner in the set,
# brittle and graceless everywhere else.
# ------------------------------------------------------ Steampunk Dimension
M("ferdonzor", "steampunkdimension", "metal", "Ferdonzor",
"steampunkdimension:ferdonzor_ingot",
[{"item": "steampunkdimension:ferdonzor_ingot", "value": 1.0}],
tier=5, hardness=6.4, density=4.0, flexibility=2, durability=1550,
enchantability=15, mining_speed=9, toughness=3, armor_durability=32,
armor_toughness=1.5),
M("glow_shard", "steampunkdimension", "crystal", "Glowshard",
"steampunkdimension:glow_shard",
[{"item": "steampunkdimension:glow_shard", "value": 1.0}],
tier=3, hardness=4.6, density=1.6, flexibility=3, durability=380,
enchantability=24, mining_speed=8, armor_durability=16,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 10, "block": 10}}}),
# ----------------------------------------------------------------- RFTools
M("dimensional_shard", "rftoolsbase", "crystal", "Dimensional",
"rftoolsbase:dimensionalshard",
[{"item": "rftoolsbase:dimensionalshard", "value": 1.0}],
tier=5, hardness=6.0, density=1.8, flexibility=3, durability=1250,
enchantability=26, mining_speed=10, toughness=2, armor_durability=28,
groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": {"emissive": {"sky": 7, "block": 7}}}),
# -------------------------------------------------------------- Create Deco
M("industrial_iron", "createdeco", "metal", "Industrial Iron",
"createdeco:industrial_iron_ingot",
ingots("createdeco", "industrial_iron_ingot", "industrial_iron_nugget"),
tier=3, hardness=5.2, density=4.0, flexibility=1, durability=340,
enchantability=11, mining_speed=6, toughness=1, armor_durability=18),
# Iron that has been through a factory: a little tougher, no more.
# --------------------------------- Aeronautics: Interstellar Expansion (vsie)
# Mostly a machinery mod; these are the three items that are a material
# rather than a component. Solid E-710 is deliberately left out - it is
# rocket fuel, not something to build a tool out of.
M("microlattice", "interstellar", "metal", "Microlattice",
"vsie:metalic_microlattice",
[{"item": "vsie:metalic_microlattice", "value": 1.0}],
tier=5, hardness=5.2, density=0.3, flexibility=7, durability=1400,
enchantability=20, mining_speed=9, toughness=2, armor_durability=34,
armor_toughness=1.5, textures=("metallic", "bright"),
properties={"handheld": speed(0.18)}),
# Real metallic microlattice is 99.99% air and lighter than styrofoam.
# Lowest density and fastest swing of any metal here, which is the whole
# reason to pick it - it will never out-hit osmium.
M("silicon_carbide", "interstellar", "crystal", "Silicon Carbide",
"vsie:silicon_carbide",
[{"item": "vsie:silicon_carbide", "value": 1.0}],
tier=5, hardness=7.6, density=2.4, flexibility=0, durability=1300,
enchantability=12, mining_speed=13, toughness=3, armor_durability=34,
armor_toughness=3.0, groups=("crystal",), textures=("crystal", "rough"),
properties={"default": {"fire_proof": True}}),
# A ceramic: nearly as hard as diamond and the industrial abrasive of
# choice, hence the mining speed - but brittle, so no flex and less
# durability than its tier would suggest.
M("computronic_substrate", "interstellar", "metal", "Computronic",
"vsie:computronic_substrate",
[{"item": "vsie:computronic_substrate", "value": 1.0}],
tier=5, hardness=4.6, density=1.8, flexibility=3, durability=1100,
enchantability=28, mining_speed=9, toughness=2, armor_durability=28,
textures=("emissive", "metallic"),
properties={"default": {"emissive": {"sky": 4, "block": 4}},
"tool": {"luminious_learning": "1"}}),
# Soft and unimpressive as a weapon; it is here for enchantability.
M("pyrium", "irons_spellbooks", "metal", "Pyrium",
"irons_spellbooks:pyrium_ingot",
[{"item": "irons_spellbooks:pyrium_ingot", "value": 1.0}],
tier=5, hardness=6.8, density=3.4, flexibility=2, durability=1750,
enchantability=18, mining_speed=9, toughness=3, armor_durability=36,
armor_toughness=2.0, textures=("emissive", "metallic"),
properties={"default": {"fire_proof": True,
"emissive": {"sky": 5, "block": 5}},
"handheld": {"immolate": "2"}}),
]
# --------------------------------------------------------------------- scales
# Generated rather than written out: colours differ only in palette, which is
# read from each colour's own texture. Stats and behaviour follow the element.
DRAGON_SCALE_ELEMENTS = {
"fire": ["red", "bronze", "green", "gray"],
"ice": ["blue", "white", "sapphire", "silver"],
"lightning": ["electric", "amethyst", "copper", "black"],
}
DRAGON_SCALE_PROPERTIES = {
"fire": {"default": {"fire_proof": True},
"armor": {"fake_enchants": {"minecraft:fire_protection": 2}}},
"ice": {"armor": {"fake_item_tag": ["minecraft:freeze_immune_wearables"]},
"boot": {"can_walk_on_snow": True}},
"lightning": {"default": {"emissive": {"sky": 5, "block": 5}},
"handheld": speed(0.08)},
}
SEA_SERPENT_COLORS = ["blue", "bronze", "deepblue", "green", "purple", "red", "teal"]
DEATHWORM_COLORS = {"red": "Red", "white": "White", "yellow": "Tan"}
# No module anywhere accepts the "scute" group. Armory's armour whitelists
# wood/fabric/metal/flint/bone/stone/crystal/glass, Arsenal's and Archery's
# parts much the same, and none of the four lists "scute" - so a scale material
# was a material you could look at and never build with, the same trap the
# gem groups below were in. MIAPI's own turtle and armadillo scutes are stuck
# there too, so this is not something the scales were doing wrong.
#
# Bone is the group they join: it is on every armour whitelist except the scuba
# set (fabric/metal/glass - a sealed suit, not a plated one), it is what a hard
# organic plate is nearest to, and it carries them into tool and bow parts as
# well, which suits stats that were always meant to be usable and unremarkable
# in hand rather than unusable.
#
# It goes in `hidden_groups` rather than `groups`: MIAPI matches a module's
# whitelist against both, but only `groups` decides where the material is filed
# in the workbench, so a dragonscale still lists as a scale rather than as a
# bone. Armory itself does this to hand its gem slots vanilla materials.
SCALE_CRAFTING_GROUP = ("bone",)
def _scales():
out = []
for element, colors in DRAGON_SCALE_ELEMENTS.items():
for color in colors:
out.append(M(
f"dragonscales_{color}", "iceandfire", "scute",
f"{color.replace('_', ' ').title()} Dragonscale",
f"iceandfire:dragonscales_{color}",
[{"item": f"iceandfire:dragonscales_{color}", "value": 1.0},
{"item": f"iceandfire:dragonscale_{color}", "value": BLOCK}],
tier=5, hardness=6.0, density=2.6, flexibility=4, durability=1500,
enchantability=15, mining_speed=7, toughness=4,
armor_durability=44, armor_toughness=3.5,
mining_level=MINING_LEVEL[4],
groups=("scute",), hidden_groups=SCALE_CRAFTING_GROUP,
textures=("rough", "shiny"),
properties=DRAGON_SCALE_PROPERTIES[element]))
# Armour-first, like Tinkers' ancient hide: high toughness and
# armour durability, unremarkable as a cutting edge.
for color in SEA_SERPENT_COLORS:
out.append(M(
f"sea_serpent_scales_{color}", "iceandfire", "scute",
f"{color.replace('deepblue', 'deep blue').title()} Serpent Scale",
f"iceandfire:sea_serpent_scales_{color}",
[{"item": f"iceandfire:sea_serpent_scales_{color}", "value": 1.0},
{"item": f"iceandfire:sea_serpent_scale_block_{color}", "value": BLOCK}],
tier=4, hardness=5.4, density=2.4, flexibility=5, durability=950,
enchantability=16, mining_speed=6, toughness=3,
armor_durability=32, armor_toughness=2.5,
groups=("scute",), hidden_groups=SCALE_CRAFTING_GROUP,
textures=("rough", "shiny"),
properties={
"armor": {
"fake_enchants": {"minecraft:respiration": 1},
# A serpent's own speed in water. Per worn slot rather than
# one `armor`-wide modifier, so each piece counts once
# where it sits; it stacks per module, so a full suit of
# scales lands near +1 - about what Armory's own scuba set
# is worth, which is the company this belongs in.
"attributes": [
attribute("miapi:generic.swim_speed", 0.10, slot)
for slot in ("head", "chest", "legs", "feet")
],
},
"boot": {"fake_enchants": {"minecraft:depth_strider": 1}}}))
for color, label in DEATHWORM_COLORS.items():
out.append(M(
f"deathworm_chitin_{color}", "iceandfire", "scute",
f"{label} Chitin", f"iceandfire:deathworm_chitin_{color}",
[{"item": f"iceandfire:deathworm_chitin_{color}", "value": 1.0}],
tier=4, hardness=5.6, density=2.2, flexibility=4, durability=880,
enchantability=13, mining_speed=6, toughness=3,
armor_durability=30, armor_toughness=2.0,
groups=("scute",), hidden_groups=SCALE_CRAFTING_GROUP,
textures=("rough",),
properties={"default": {
"fire_proof": True,
# A deathworm swims through dune the way a fish does water, so
# its shell lets its bearer do the same: sand, gravel and the
# rest of `cmmodular:sand_like` stop being something to walk
# into. Slot `any` and capped at 1, as with cinder essence, so
# one piece of chitin anywhere is the whole ability. What holds
# you up is untouched - see SandPhasing.java.
"attributes": [attribute(SAND_PHASING, 1, "any")],
}}))
# Desert worms, so heat immunity comes with the shell.
return out
# --------------------------------------------------------------- gem-set mods
# Crystal Chronicles and Pastel each add a family of gems that differ in colour
# and lore rather than in kind. They are generated rather than written out one
# by one: within a family the stats follow the tier, and the palette - which is
# what actually distinguishes them in game - comes from each gem's own texture.
# name -> (tier, flavour property)
CRYSTAL_CHRONICLES = {
"hemalite_shard": (5, {"leeching": "0.7"}),
"volcanite_shard": (5, {"fire_proof": True, "immolate": "2",
"emissive": {"sky": 6, "block": 6}}),
"voltite_shard": (5, {"emissive": {"sky": 7, "block": 7}}),
"ice_shard": (4, {"can_walk_on_snow": True,
"fake_item_tag": ["minecraft:freeze_immune_wearables"]}),
"floralite_shard": (4, {}),
"divinite_shard": (5, {"luminious_learning": "1"}),
"voidstone_shard": (5, {"leeching": "0.5"}),
"avaricite_shard": (5, {"attributes": [
{"attribute": "minecraft:generic.luck", "value": "1",
"operation": "+", "slot": "any"}]}),
}
PASTEL_GEMS = {
"topaz_shard": (4, {}),
"citrine_shard": (4, {}),
"onyx_shard": (5, {"leeching": "0.5"}),
"moonstone_shard": (5, {"emissive": {"sky": 8, "block": 8}}),
"bismuth_crystal": (4, {}),
"blazing_crystal": (5, {"fire_proof": True, "immolate": "2",
"emissive": {"sky": 7, "block": 7}}),
"frostbite_crystal": (5, {"can_walk_on_snow": True,
"fake_item_tag": ["minecraft:freeze_immune_wearables"]}),
"shimmerstone_gem": (5, {"emissive": {"sky": 12, "block": 12},
"luminious_learning": "1"}),
"paltaeria_gem": (5, {}),
"stratine_gem": (5, {}),
}
# Gem stat bands, so a family stays internally consistent.
_GEM_BAND = {
4: dict(hardness=5.6, density=2.0, flexibility=1, durability=700,
enchantability=20, mining_speed=8, toughness=1, armor_durability=22),
5: dict(hardness=6.2, density=1.9, flexibility=2, durability=1250,
enchantability=24, mining_speed=9, toughness=2, armor_durability=28,
armor_toughness=1.5),
}
# Nuggets, in effect: Pastel's two float-gems break into eight fragments on an
# anvil and nine come back out of a floatblock, so a fragment is an eighth of a
# gem and worth accepting as one.
GEM_FRAGMENTS = {
"paltaeria_gem": ("pastel:paltaeria_fragments", 0.125),
"stratine_gem": ("pastel:stratine_fragments", 0.125),
}
def _gem_family(pack, namespace, table):
out = []
for item, (tier, props) in table.items():
label = item.replace("_shard", "").replace("_crystal", "").replace("_gem", "")
items = [{"item": f"{namespace}:{item}", "value": 1.0}]
if item in GEM_FRAGMENTS:
fragment, value = GEM_FRAGMENTS[item]
items.append({"item": fragment, "value": value})
out.append(M(
item, pack, "crystal", label.replace("_", " ").title(),
f"{namespace}:{item}", items,
tier=tier, groups=("crystal", "gem"), textures=("crystal", "bright"),
properties={"default": props} if props else None,
**_GEM_BAND[tier]))
return out
MATERIALS.extend(_gem_family("crystal_chronicles", "crystal_chronicles",
CRYSTAL_CHRONICLES))
MATERIALS.extend(_gem_family("pastel", "pastel", PASTEL_GEMS))
MATERIALS.extend(_scales())
# Gem sockets do not look for the "gem" group. Truly Modular: Arsenal gates its
# melee gem modules on `gem_melee` and Armory gates its armour ones on
# `gem_armor`, so a material tagged only "crystal"/"gem" is rejected by every
# socket - which is exactly what happened to the two essences. Anything gem-like
# gets both, so it fits any gem slot regardless of size or whether the item is
# a weapon or a piece of armour.
GEM_SOCKET_GROUPS = ("gem_melee", "gem_armor")
for _material in MATERIALS:
if {"gem", "crystal"} & set(_material["groups"]):
_material["groups"] = list(_material["groups"]) + [
g for g in GEM_SOCKET_GROUPS if g not in _material["groups"]]
# Extensions edit a material that already exists instead of adding a new one.
# The file goes in the materials folder like any other and is told apart by its
# shape: `parent` names the material it edits and `data` is merged onto a copy
# of it - the same form MIAPI's own stained glass uses to vary plain glass.
#
# The merge overwrites whole fields rather than appending to them, so an
# extension that adds an ingredient has to repeat the ones it wants to keep.
EXTENSIONS = [
# Ice and Fire's amethyst is the same stone MIAPI already ships, so it just
# becomes another way to craft it. The item id really is spelled
# "amythest_gem" - that typo is in Ice and Fire itself.
{
"pack": "iceandfire",
"path": "crystal/amethyst",
"data": {
"parent": "miapi:crystal/amethyst",
"data": {
"items": [
{"item": "minecraft:amethyst_shard", "value": 0.25},
{"item": "minecraft:amethyst_cluster", "value": 0.25},
{"item": "minecraft:amethyst_block", "value": 1.0},
{"item": "iceandfire:amythest_gem", "value": 0.25},
],
},
},
},
]
# Forms of a material that a *different* mod adds. Create: Wizardry presses
# Iron's Spells' arcane ingots into sheets and stacks them into blocks, and adds
# the mithril nugget the base mod never had, so all of those are the same metal.
#
# They cannot simply be listed on the material: it lives in the Iron's Spells
# pack, and an item id belonging to a mod that is not installed stops the whole
# material from loading. An extension in Create: Wizardry's own pack is only
# read when that mod is there.
EXTRA_ITEM_FORMS = {
"arcane_metal": [("create_wizardry:arcane_sheet", 1.0),
("create_wizardry:arcane_block", BLOCK)],
"mithril": [("create_wizardry:mithril_nugget", NUGGET)],
}
# ------------------------------------------------- identical materials, one entry
# Several of these metals and gems are added by more than one mod. Every
# variant should behave as the same material rather than as a near-duplicate,
# so on top of the primary provider's own items each material also accepts the
# `c:` common tag, which every provider registers into. Any mod's silver ingot
# is therefore just silver.
#
# Nothing records where a stack came from - MIAPI stores only the material id on
# the item - so a tool built from Immersive Engineering silver is indistinguish-
# able from one built with Ice and Fire silver. The primary provider's item stays
# first in the list, so anything that reads a single representative item back out
# (repair and deconstruct previews) resolves to the default rather than to
# whichever variant happened to be used.
COMMON_TAGS = {
# metals
"tin": "tin", "lead": "lead", "osmium": "osmium", "bronze": "bronze",
"steel": "steel", "uranium": "uranium", "silver": "silver",
"refined_obsidian": "refined_obsidian", "refined_glowstone": "refined_glowstone",
"brass": "brass", "zinc": "zinc", "andesite_alloy": "andesite_alloy",
"aluminum": "aluminum", "nickel": "nickel", "constantan": "constantan",
"electrum": "electrum", "hop_graphite": "hop_graphite",
"titanium": "titanium", "titanium_alloy": "titanium_alloy",
"industrial_iron": "industrial_iron", "iesnium": "iesnium",
"pink_slime": "pink_slime", "tungsten": "tungsten",
"dark_steel": "dark_steel", "end_steel": "end_steel",
"energetic_alloy": "energetic_alloy", "vibrant_alloy": "vibrant_alloy",
"conductive_alloy": "conductive_alloy", "pulsating_alloy": "pulsating_alloy",
"redstone_alloy": "redstone_alloy", "soularium": "soularium",
"mithril": "mithril", "platinum": "platinum",
}
COMMON_GEM_TAGS = {
"certus_quartz": "certus_quartz", "fluix": "fluix", "source_gem": "source",
"fluorite": "fluorite", "sapphire": "sapphire",
"ender_crystal": "ender_crystal", "vibrant_crystal": "vibrant_crystal",
"pulsating_crystal": "pulsating_crystal", "prescient_crystal": "prescient_crystal",
"enticing_crystal": "enticing_crystal", "weather_crystal": "weather_crystal",
}
def _accept_every_provider():
"""Append the common tag to each material that more than one mod can supply.
Tags are safe where item ids are not: an unknown tag resolves to nothing
instead of failing the material, so a tag naming a mod that is not installed
costs only an ingredient that matches no item.
"""
for material in MATERIALS:
name = material["name"]
if name in COMMON_TAGS:
tag = COMMON_TAGS[name]
material["items"] = material["items"] + [
{"tag": f"c:ingots/{tag}", "value": 1.0},
{"tag": f"c:nuggets/{tag}", "value": NUGGET},
{"tag": f"c:storage_blocks/{tag}", "value": BLOCK},
]
elif name in COMMON_GEM_TAGS:
material["items"] = material["items"] + [
{"tag": f"c:gems/{COMMON_GEM_TAGS[name]}", "value": 1.0},
]
_accept_every_provider()
def _extend_with_extra_forms(pack="create_wizardry"):
"""Turn EXTRA_ITEM_FORMS into material extensions.
Built after the common tags are appended, and out of the material's own item
list, because the merge replaces the ingredient list rather than adding to
it - everything the material already accepted has to be carried over.
"""
by_name = {material["name"]: material for material in MATERIALS}
for name, extras in EXTRA_ITEM_FORMS.items():
base = by_name[name]
path = f"{base['group']}/{name}"
EXTENSIONS.append({
"pack": pack,
# The extension is filed under its own name, not the material's. A
# datapack file is identified by its path, so writing it to the
# material's path in a second pack does not add an extension - it
# replaces the material with one, whichever pack loads last. The
# extension then names itself as its own parent, MIAPI reads that as
# a cycle, and the material is gone for anyone with both mods.
"path": f"{path}_from_{pack}",
"data": {
"parent": f"cmmodular:{path}",
"data": {
"items": base["items"] + [{"item": item, "value": value}
for item, value in extras],
},
},
})
_extend_with_extra_forms()