diff --git a/README.md b/README.md index 4f4ffd2..a2cb4cf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Create/Mekanism Modular A [Truly Modular](https://modrinth.com/mod/modular-item-api) addon for Minecraft -1.21.1 / NeoForge. It adds 72 materials drawn from Create, Mekanism, Ice and -Fire, Iron's Spells 'n Spellbooks, Create: The Air War, Create: Cosmonautics and -Aeronautics: Interstellar Expansion, so those mods' metals, gems, scales and -essences can be used to build modular tools and armour. +1.21.1 / NeoForge. It adds 77 materials drawn from Create, Mekanism, Ice and +Fire, Immersive Engineering, Iron's Spells 'n Spellbooks, Create: The Air War, +Create: Cosmonautics and Aeronautics: Interstellar Expansion, so those mods' +metals, gems, scales and essences can be used to build modular tools and armour. Every source mod is optional. Install any subset - the materials for mods you do not have are never registered. @@ -22,11 +22,13 @@ and a material whose ingredient item is missing fails to parse. So each source mod's materials are a separate built-in datapack, registered in `CMModular.java` only when that mod is present. -Titanium is the exception: Air War and Cosmonautics both add a titanium ingot, -so one material covers both and draws its ingredients from `c:ingots/titanium` -rather than an item id. Cosmonautics already declares that tag; the tag files in -`data/c/` fill it in for Air War, which ships no common tags, using optional -entries so a missing mod is not an error. +**Overlapping metals.** Several metals come from more than one mod - steel, +lead and uranium from Mekanism and Immersive Engineering, silver from Ice and +Fire and Immersive Engineering, titanium from both aerospace addons. Each one +picks a single provider rather than accepting either, so the crafting screen +shows one entry per metal instead of two identical-looking ones. Providers are +Mekanism for steel/lead/uranium, Ice and Fire for silver, Cosmonautics for +titanium; swapping one is a one-line change in `tools/materials.py`. **Fire immunity.** Cinder essence grants immunity to fire, which is not an attribute the game has and not a property MIAPI offers. Instead of coupling to @@ -115,3 +117,9 @@ Requires `pillow` and `numpy`. - Interstellar Expansion is mostly machinery. Only three of its items are a material rather than a component; solid E-710 is left out because it is rocket fuel. +- Gem sockets do not check the `gem` group. Arsenal gates melee gems on + `gem_melee` and Armory gates armour gems on `gem_armor`, so every gem-like + material carries both and fits any gem slot. +- Immersive Engineering contributes aluminium, nickel, constantan, electrum and + graphite. Its steel, lead, uranium and silver are not separate materials - see + overlapping metals above. diff --git a/src/main/java/eu/abdelbaki/cmmodular/CMModular.java b/src/main/java/eu/abdelbaki/cmmodular/CMModular.java index cdefb4a..070e6bc 100644 --- a/src/main/java/eu/abdelbaki/cmmodular/CMModular.java +++ b/src/main/java/eu/abdelbaki/cmmodular/CMModular.java @@ -13,8 +13,8 @@ import net.neoforged.fml.common.Mod; import net.neoforged.neoforge.event.AddPackFindersEvent; /** - * Adds the materials of Create, Mekanism, Ice and Fire, Iron's Spells and the - * Create aerospace addons to Truly Modular. + * Adds the materials of Create, Mekanism, Ice and Fire, Immersive Engineering, + * Iron's Spells and the Create aerospace addons to Truly Modular. * *

Almost all of this mod is data. The one thing data cannot do is load * conditionally: MIAPI reads materials with its own loader, which honours @@ -22,28 +22,21 @@ import net.neoforged.neoforge.event.AddPackFindersEvent; * file off, and a material whose ingredient item does not exist fails to parse * outright. So each source mod's materials live in their own built-in datapack * and only get registered when that mod is actually installed. + * + *

Where two mods add the same metal - steel, lead and uranium are in both + * Mekanism and Immersive Engineering, silver in both Ice and Fire and Immersive + * Engineering, titanium in both aerospace addons - one of them is simply picked + * as the provider rather than the material accepting either. That keeps one + * entry per metal in the crafting screen. */ @Mod(CMModular.MOD_ID) public class CMModular { public static final String MOD_ID = "cmmodular"; - /** - * A set of materials, and the mods it needs in order to load. - * - * @param anyOf when true one of {@code requires} is enough, rather than all - * of them. Such a pack cannot name items directly - it has no - * way to know which mod turned up - so it sources ingredients - * from item tags instead. - */ - private record MaterialPack(String id, String name, List requires, boolean anyOf) { - MaterialPack(String id, String name, String... requires) { - this(id, name, List.of(requires), false); - } - + /** A set of materials, and the mod it needs in order to load. */ + private record MaterialPack(String id, String name, String requires) { boolean present() { - return anyOf - ? requires.stream().anyMatch(ModList.get()::isLoaded) - : requires.stream().allMatch(ModList.get()::isLoaded); + return ModList.get().isLoaded(requires); } } @@ -51,14 +44,12 @@ public class CMModular { new MaterialPack("mekanism", "Mekanism Materials", "mekanism"), new MaterialPack("create", "Create Materials", "create"), new MaterialPack("iceandfire", "Ice and Fire Materials", "iceandfire"), + new MaterialPack("immersiveengineering", "Immersive Engineering Materials", + "immersiveengineering"), new MaterialPack("irons_spellbooks", "Iron's Spells Materials", "irons_spellbooks"), new MaterialPack("interstellar", "Interstellar Expansion Materials", "vsie"), new MaterialPack("air_war", "Create: The Air War Materials", "create_the_air_wars"), - new MaterialPack("cosmonautics", "Create: Cosmonautics Materials", "rocketnautics"), - // Both aerospace addons add a titanium ingot. One material covers - // them both, fed by the c:ingots/titanium tag. - new MaterialPack("aerospace", "Aerospace Materials", - List.of("create_the_air_wars", "rocketnautics"), true)); + new MaterialPack("cosmonautics", "Create: Cosmonautics Materials", "rocketnautics")); public CMModular(IEventBus modBus) { FireImmunity.register(modBus); diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index 41705e4..f6c71ae 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -71,6 +71,13 @@ versionRange = "[0,)" ordering = "AFTER" side = "BOTH" +[[dependencies.${mod_id}]] +modId = "immersiveengineering" +type = "optional" +versionRange = "[0,)" +ordering = "AFTER" +side = "BOTH" + [[dependencies.${mod_id}]] modId = "vsie" type = "optional" diff --git a/src/main/resources/data/c/tags/item/ingots/titanium.json b/src/main/resources/data/c/tags/item/ingots/titanium.json deleted file mode 100644 index 8ed2dba..0000000 --- a/src/main/resources/data/c/tags/item/ingots/titanium.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "replace": false, - "values": [ - { - "id": "create_the_air_wars:titaniumingot", - "required": false - } - ] -} diff --git a/src/main/resources/data/c/tags/item/nuggets/titanium.json b/src/main/resources/data/c/tags/item/nuggets/titanium.json deleted file mode 100644 index 02cf2f7..0000000 --- a/src/main/resources/data/c/tags/item/nuggets/titanium.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "replace": false, - "values": [ - { - "id": "create_the_air_wars:titaniumnugget", - "required": false - } - ] -} diff --git a/src/main/resources/data/c/tags/item/plates/titanium.json b/src/main/resources/data/c/tags/item/plates/titanium.json deleted file mode 100644 index 0a9b381..0000000 --- a/src/main/resources/data/c/tags/item/plates/titanium.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "replace": false, - "values": [ - { - "id": "create_the_air_wars:titaniumsheet", - "required": false - } - ] -} diff --git a/src/main/resources/packs/aerospace/pack.mcmeta b/src/main/resources/packs/aerospace/pack.mcmeta deleted file mode 100644 index 13f0382..0000000 --- a/src/main/resources/packs/aerospace/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "Aerospace Materials for Truly Modular", - "pack_format": 48 - } -} diff --git a/src/main/resources/packs/air_war/data/cmmodular/miapi/materials/crystal/sulfur.json b/src/main/resources/packs/air_war/data/cmmodular/miapi/materials/crystal/sulfur.json index f6bc983..5c20d56 100644 --- a/src/main/resources/packs/air_war/data/cmmodular/miapi/materials/crystal/sulfur.json +++ b/src/main/resources/packs/air_war/data/cmmodular/miapi/materials/crystal/sulfur.json @@ -1,7 +1,9 @@ { "translation": "Sulfur ", "groups": [ - "crystal" + "crystal", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/aerospace/data/cmmodular/miapi/materials/metal/titanium.json b/src/main/resources/packs/cosmonautics/data/cmmodular/miapi/materials/metal/titanium.json similarity index 83% rename from src/main/resources/packs/aerospace/data/cmmodular/miapi/materials/metal/titanium.json rename to src/main/resources/packs/cosmonautics/data/cmmodular/miapi/materials/metal/titanium.json index 1ba36b8..69c7211 100644 --- a/src/main/resources/packs/aerospace/data/cmmodular/miapi/materials/metal/titanium.json +++ b/src/main/resources/packs/cosmonautics/data/cmmodular/miapi/materials/metal/titanium.json @@ -52,16 +52,20 @@ }, "items": [ { - "tag": "c:ingots/titanium", + "item": "rocketnautics:titanium_ingot", "value": 1.0 }, { - "tag": "c:nuggets/titanium", + "item": "rocketnautics:titanium_nugget", "value": 0.11112 }, { - "tag": "c:plates/titanium", + "item": "rocketnautics:titanium_sheet", "value": 1.0 + }, + { + "item": "rocketnautics:titanium_block", + "value": 9.0 } ] } diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/dread_shard.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/dread_shard.json index 262151b..59ff06c 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/dread_shard.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/dread_shard.json @@ -2,7 +2,9 @@ "translation": "Dread ", "groups": [ "crystal", - "metal" + "metal", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/pixie_dust.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/pixie_dust.json index 8c250c1..c481514 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/pixie_dust.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/pixie_dust.json @@ -1,7 +1,9 @@ { "translation": "Pixie Dust ", "groups": [ - "crystal" + "crystal", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/sapphire.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/sapphire.json index 52d4868..cb5fd56 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/sapphire.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/crystal/sapphire.json @@ -2,7 +2,9 @@ "translation": "Sapphire ", "groups": [ "crystal", - "gem" + "gem", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/aluminum.json b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/aluminum.json new file mode 100644 index 0000000..7494f48 --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/aluminum.json @@ -0,0 +1,64 @@ +{ + "translation": "Aluminium ", + "groups": [ + "metal" + ], + "icon": { + "type": "item", + "item": "immersiveengineering:ingot_aluminum" + }, + "hardness": 4.0, + "density": 1.2, + "flexibility": 3, + "durability": 260, + "enchantability": 17, + "toughness": 0, + "tier": 3, + "mining_speed": 6, + "mining_level": "minecraft:incorrect_for_iron_tool", + "armor_durability": 14, + "color": "B9C0C3", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "3c3d3e", + "68": "737677", + "107": "7a7e7f", + "150": "818587", + "190": "93989a", + "216": "b9c0c3", + "255": "c5cdd0" + }, + "filler": "interpolate" + }, + "textures": [ + "metallic", + "bright" + ], + "properties": { + "handheld": { + "attributes": [ + { + "attribute": "generic.attack_speed", + "value": "0.1", + "operation": "+", + "slot": "mainhand" + } + ] + } + }, + "items": [ + { + "item": "immersiveengineering:ingot_aluminum", + "value": 1.0 + }, + { + "item": "immersiveengineering:nugget_aluminum", + "value": 0.11112 + }, + { + "item": "immersiveengineering:plate_aluminum", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/constantan.json b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/constantan.json new file mode 100644 index 0000000..9505657 --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/constantan.json @@ -0,0 +1,51 @@ +{ + "translation": "Constantan ", + "groups": [ + "metal" + ], + "icon": { + "type": "item", + "item": "immersiveengineering:ingot_constantan" + }, + "hardness": 5.6, + "density": 4.0, + "flexibility": 2, + "durability": 640, + "enchantability": 14, + "toughness": 2, + "tier": 4, + "mining_speed": 7, + "mining_level": "minecraft:incorrect_for_diamond_tool", + "armor_durability": 24, + "color": "FE8E70", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "321c16", + "68": "60352a", + "107": "733e32", + "150": "7f4537", + "190": "aa5c4a", + "216": "fe8e70", + "255": "ff9f7e" + }, + "filler": "interpolate" + }, + "textures": [ + "metallic" + ], + "items": [ + { + "item": "immersiveengineering:ingot_constantan", + "value": 1.0 + }, + { + "item": "immersiveengineering:nugget_constantan", + "value": 0.11112 + }, + { + "item": "immersiveengineering:plate_constantan", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/electrum.json b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/electrum.json new file mode 100644 index 0000000..ad58f88 --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/electrum.json @@ -0,0 +1,57 @@ +{ + "translation": "Electrum ", + "groups": [ + "metal" + ], + "icon": { + "type": "item", + "item": "immersiveengineering:ingot_electrum" + }, + "hardness": 4.4, + "density": 3.6, + "flexibility": 2, + "durability": 260, + "enchantability": 26, + "toughness": 0, + "tier": 3, + "mining_speed": 9, + "mining_level": "minecraft:incorrect_for_iron_tool", + "armor_durability": 14, + "color": "FFBC4C", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "362a17", + "68": "67512c", + "107": "785c30", + "150": "7d5f31", + "190": "b0833b", + "216": "ffbc4c", + "255": "ffd051" + }, + "filler": "interpolate" + }, + "textures": [ + "metallic", + "bright" + ], + "properties": { + "tool": { + "luminious_learning": "0.5" + } + }, + "items": [ + { + "item": "immersiveengineering:ingot_electrum", + "value": 1.0 + }, + { + "item": "immersiveengineering:nugget_electrum", + "value": 0.11112 + }, + { + "item": "immersiveengineering:plate_electrum", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/hop_graphite.json b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/hop_graphite.json new file mode 100644 index 0000000..bb944a6 --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/hop_graphite.json @@ -0,0 +1,63 @@ +{ + "translation": "Graphite ", + "groups": [ + "metal" + ], + "icon": { + "type": "item", + "item": "immersiveengineering:ingot_hop_graphite" + }, + "hardness": 4.2, + "density": 2.0, + "flexibility": 1, + "durability": 520, + "enchantability": 12, + "toughness": 2, + "tier": 4, + "mining_speed": 10, + "mining_level": "minecraft:incorrect_for_diamond_tool", + "armor_durability": 18, + "color": "373737", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "080808", + "68": "101010", + "107": "121212", + "150": "171717", + "190": "212121", + "216": "373737", + "255": "3f3f3f" + }, + "filler": "interpolate" + }, + "textures": [ + "rough", + "metallic" + ], + "properties": { + "default": { + "fire_proof": true + }, + "handheld": { + "attributes": [ + { + "attribute": "generic.attack_speed", + "value": "0.08", + "operation": "+", + "slot": "mainhand" + } + ] + } + }, + "items": [ + { + "item": "immersiveengineering:ingot_hop_graphite", + "value": 1.0 + }, + { + "item": "immersiveengineering:plate_hop_graphite", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/nickel.json b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/nickel.json new file mode 100644 index 0000000..586d6d9 --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/data/cmmodular/miapi/materials/metal/nickel.json @@ -0,0 +1,52 @@ +{ + "translation": "Nickel ", + "groups": [ + "metal" + ], + "icon": { + "type": "item", + "item": "immersiveengineering:ingot_nickel" + }, + "hardness": 5.4, + "density": 4.4, + "flexibility": 1, + "durability": 480, + "enchantability": 10, + "toughness": 1, + "tier": 3, + "mining_speed": 6, + "mining_level": "minecraft:incorrect_for_iron_tool", + "armor_durability": 20, + "armor_toughness": 0.5, + "color": "C8CEBD", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "2b2c28", + "68": "52544d", + "107": "60635a", + "150": "686c62", + "190": "878c80", + "216": "c8cebd", + "255": "dfe5d2" + }, + "filler": "interpolate" + }, + "textures": [ + "metallic" + ], + "items": [ + { + "item": "immersiveengineering:ingot_nickel", + "value": 1.0 + }, + { + "item": "immersiveengineering:nugget_nickel", + "value": 0.11112 + }, + { + "item": "immersiveengineering:plate_nickel", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/immersiveengineering/pack.mcmeta b/src/main/resources/packs/immersiveengineering/pack.mcmeta new file mode 100644 index 0000000..306c99a --- /dev/null +++ b/src/main/resources/packs/immersiveengineering/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Immersive Engineering Materials for Truly Modular", + "pack_format": 48 + } +} diff --git a/src/main/resources/packs/interstellar/data/cmmodular/miapi/materials/crystal/silicon_carbide.json b/src/main/resources/packs/interstellar/data/cmmodular/miapi/materials/crystal/silicon_carbide.json index b53d69c..082eca0 100644 --- a/src/main/resources/packs/interstellar/data/cmmodular/miapi/materials/crystal/silicon_carbide.json +++ b/src/main/resources/packs/interstellar/data/cmmodular/miapi/materials/crystal/silicon_carbide.json @@ -1,7 +1,9 @@ { "translation": "Silicon Carbide ", "groups": [ - "crystal" + "crystal", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/arcane_essence.json b/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/arcane_essence.json index b45fd24..7e2777b 100644 --- a/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/arcane_essence.json +++ b/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/arcane_essence.json @@ -2,7 +2,9 @@ "translation": "Arcane ", "groups": [ "crystal", - "gem" + "gem", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/cinder_essence.json b/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/cinder_essence.json index 898734a..458dc4d 100644 --- a/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/cinder_essence.json +++ b/src/main/resources/packs/irons_spellbooks/data/cmmodular/miapi/materials/crystal/cinder_essence.json @@ -2,7 +2,9 @@ "translation": "Cinder ", "groups": [ "crystal", - "gem" + "gem", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/src/main/resources/packs/mekanism/data/cmmodular/miapi/materials/crystal/fluorite.json b/src/main/resources/packs/mekanism/data/cmmodular/miapi/materials/crystal/fluorite.json index 5192bd9..b1e2c35 100644 --- a/src/main/resources/packs/mekanism/data/cmmodular/miapi/materials/crystal/fluorite.json +++ b/src/main/resources/packs/mekanism/data/cmmodular/miapi/materials/crystal/fluorite.json @@ -2,7 +2,9 @@ "translation": "Fluorite ", "groups": [ "crystal", - "gem" + "gem", + "gem_melee", + "gem_armor" ], "icon": { "type": "item", diff --git a/tools/generate_materials.py b/tools/generate_materials.py index 9208e51..71a5c0d 100644 --- a/tools/generate_materials.py +++ b/tools/generate_materials.py @@ -18,6 +18,7 @@ rather than shipping a material that silently refuses to load. import argparse import json import re +import shutil import sys import zipfile @@ -185,18 +186,13 @@ def build_material(spec, jars: Jars): return out -def check_items(spec, jars: Jars, any_of_pack: bool): - """Item ids must exist; tags are allowed to be missing at build time.""" +def check_items(spec, jars: Jars): + """Every item a material names has to exist in the jar that provides it.""" problems = [] for entry in spec["items"]: if "item" not in entry: continue - if any_of_pack: - problems.append( - f"{spec['name']}: pack '{spec['pack']}' loads when any one of its " - f"mods is present, so it must use tags, not the item id {entry['item']}" - ) - elif not jars.has_item(entry["item"]): + if not jars.has_item(entry["item"]): problems.append(f"{spec['name']}: no such item {entry['item']}") if not jars.has_item(spec["icon"]): problems.append(f"{spec['name']}: icon item {spec['icon']} does not exist") @@ -218,14 +214,19 @@ def main(): problems = [] for spec in MATERIALS: - pack = PACKS[spec["pack"]] - problems += check_items(spec, jars, pack.get("any_of", False)) + problems += check_items(spec, jars) if problems: print("aborting, item ids do not check out:", file=sys.stderr) for p in problems: print(" " + p, file=sys.stderr) return 1 + # Wipe first. A material that moves between packs would otherwise leave a + # stale copy behind, and two files claiming the same material id is a silent + # mess to debug. + if args.out.exists(): + shutil.rmtree(args.out) + written = 0 for pack_id, pack in PACKS.items(): root = args.out / pack_id diff --git a/tools/materials.py b/tools/materials.py index 6261555..92627a8 100644 --- a/tools/materials.py +++ b/tools/materials.py @@ -39,22 +39,19 @@ 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 `mods` are present, so a material never references a missing item. -# `any_of` packs load when at least one listed mod is installed; those materials -# therefore have to source their ingredients from tags, not item ids. +# 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": {"mods": ["mekanism"], "name": "Mekanism Materials"}, - "create": {"mods": ["create"], "name": "Create Materials"}, - "iceandfire": {"mods": ["iceandfire"], "name": "Ice and Fire Materials"}, - "air_war": {"mods": ["create_the_air_wars"], "name": "Create: The Air War Materials"}, - "cosmonautics": {"mods": ["rocketnautics"], "name": "Create: Cosmonautics Materials"}, - "irons_spellbooks": {"mods": ["irons_spellbooks"], "name": "Iron's Spells Materials"}, - "interstellar": {"mods": ["vsie"], "name": "Interstellar Expansion Materials"}, - "aerospace": { - "mods": ["create_the_air_wars", "rocketnautics"], - "any_of": True, - "name": "Aerospace Materials", - }, + "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"}, } # Attribute this mod registers itself, so a material can grant something the @@ -110,6 +107,7 @@ def ingots(mod, ingot, nugget=None, block=None, extra=()): return out + def speed(value): """Attack speed tweak on held modules: positive is faster.""" return {"attributes": [{"attribute": "generic.attack_speed", "value": str(value), @@ -295,10 +293,11 @@ MATERIALS = [ # ----------------------------------------------------------------- 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", "aerospace", "metal", "Titanium", "rocketnautics:titanium_ingot", - [{"tag": "c:ingots/titanium", "value": 1.0}, - {"tag": "c:nuggets/titanium", "value": NUGGET}, - {"tag": "c:plates/titanium", "value": 1.0}], + 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, durability=1150, enchantability=11, mining_speed=9, toughness=2, armor_durability=32, armor_toughness=1.5, @@ -552,6 +551,60 @@ MATERIALS = [ properties={"handheld": {"attributes": [ 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. + # --------------------------------- 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 @@ -671,6 +724,20 @@ def _scales(): 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 add data to a material that already exists rather than replacing it. # Ice and Fire's amethyst is the same stone MIAPI already ships, so it just # becomes another way to craft it.