From dcf3b7e9c3deb501a2648c8dc4ee1e1d081532a7 Mon Sep 17 00:00:00 2001 From: The_miro Date: Fri, 14 Aug 2026 11:39:02 +0200 Subject: [PATCH] Let scales and bones build armour, and add sea serpent fang Every scale material was in the "scute" group, and nothing in Truly Modular accepts it - not Armory's armour, not Arsenal's or Archery's parts. MIAPI's own turtle and armadillo scutes are stuck the same way. So the 22 scale materials now carry "bone" as a hidden group: matched when a module decides what it will accept, ignored when the workbench decides what heading to file the material under, which is how Armory hands its own gem slots vanilla materials. That is every piece of armour except the scuba set, which takes fabric/metal/glass, plus tool and bow parts. Dragon bone gains "gem_armor" the same way, so it can be set into an armour socket rather than only shaped into the armour; it already built grips and handles as a bone. Sea serpent fang is new - Ice and Fire has no sea serpent bone, and the fang is what a serpent leaves besides its scales. It grants water breathing, which is what Ice and Fire's own Tide Guardian armour does and what nothing in MIAPI can express: WaterBreathing.java registers an attribute and answers LivingBreatheEvent, exactly as FireImmunity and VacuumSeal do, but only with the bearer's eyes in water so a fang is not half a spacesuit. Co-Authored-By: Claude Opus 5 --- README.md | 23 ++++++- gradle.properties | 2 +- .../eu/abdelbaki/cmmodular/CMModular.java | 1 + .../abdelbaki/cmmodular/WaterBreathing.java | 62 +++++++++++++++++ .../assets/cmmodular/lang/en_us.json | 1 + .../miapi/materials/bone/dragonbone.json | 3 + .../materials/bone/sea_serpent_fang.json | 64 ++++++++++++++++++ .../materials/scute/deathworm_chitin_red.json | 3 + .../scute/deathworm_chitin_white.json | 3 + .../scute/deathworm_chitin_yellow.json | 3 + .../scute/dragonscales_amethyst.json | 3 + .../materials/scute/dragonscales_black.json | 3 + .../materials/scute/dragonscales_blue.json | 3 + .../materials/scute/dragonscales_bronze.json | 3 + .../materials/scute/dragonscales_copper.json | 3 + .../scute/dragonscales_electric.json | 3 + .../materials/scute/dragonscales_gray.json | 3 + .../materials/scute/dragonscales_green.json | 3 + .../materials/scute/dragonscales_red.json | 3 + .../scute/dragonscales_sapphire.json | 3 + .../materials/scute/dragonscales_silver.json | 3 + .../materials/scute/dragonscales_white.json | 3 + .../scute/sea_serpent_scales_blue.json | 3 + .../scute/sea_serpent_scales_bronze.json | 3 + .../scute/sea_serpent_scales_deepblue.json | 3 + .../scute/sea_serpent_scales_green.json | 3 + .../scute/sea_serpent_scales_purple.json | 3 + .../scute/sea_serpent_scales_red.json | 3 + .../scute/sea_serpent_scales_teal.json | 3 + tools/generate_materials.py | 4 ++ tools/materials.py | 66 ++++++++++++++++--- 31 files changed, 282 insertions(+), 10 deletions(-) create mode 100644 src/main/java/eu/abdelbaki/cmmodular/WaterBreathing.java create mode 100644 src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/sea_serpent_fang.json diff --git a/README.md b/README.md index d807ac0..b7232db 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Create/Mekanism Modular A [Truly Modular](https://modrinth.com/mod/modular-item-api) addon for Minecraft -1.21.1 / NeoForge. It adds 126 materials drawn from 22 mods - Create, Mekanism, Ice +1.21.1 / NeoForge. It adds 127 materials drawn from 22 mods - Create, Mekanism, Ice and Fire, Immersive Engineering, Ender IO, Applied Energistics, Occultism, Ars Nouveau, Iron's Spells, Pastel, Crystal Chronicles, NauTec, Superb Warfare, Industrial Foregoing, RFTools, Create Deco, Steampunk Dimension and the Create @@ -58,6 +58,10 @@ watches for it. Neither side knows about the other. **Breathing in a vacuum.** The same trick, for the space set - see below. +**Breathing underwater.** And again, for sea serpent fang: `WaterBreathing.java` +answers the same `LivingBreatheEvent`, but only when the bearer's eyes are in +water, so a fang is a fang rather than half a spacesuit. + ## Modules Three of the packs hold modules rather than materials. They are hand-written @@ -213,6 +217,23 @@ folders, so the hand-written packs survive it. emissive, so it still reads as fire in game. - Dragon scales are one material per colour (12 dragon, 7 sea serpent, 3 death worm chitin). Colours within an element share stats and differ only in palette. +- Bones are the other half of that. Dragon bone already built grips, handles + and hafts - `bone` is on every tool and bow whitelist - and now carries + `gem_armor` as a hidden group as well, so a piece can be set into an armour + socket instead of only shaped into the armour. Sea serpent fang is new and + does both: Ice and Fire has no sea serpent bone, and the fang is what a + serpent leaves behind besides its scales. It grants water breathing, which is + what Ice and Fire's own Tide Guardian armour does, from slot `any` - so one + fang socketed, worn or held is enough, and a second neither adds nor dilutes. +- Scales are in the `scute` group, and no module in Truly Modular accepts that + group - not Armory's armour, not Arsenal's or Archery's parts, and MIAPI's own + turtle and armadillo scutes are stuck the same way. So each scale material + carries `bone` as a hidden group: matched when a module decides what it will + accept, ignored when the workbench decides what heading to file the material + under, which is how Armory hands its own gem slots vanilla materials. Bone is + on every armour whitelist except the scuba set - that one takes + fabric/metal/glass, being a sealed suit rather than a plated one - so a scale + builds every other piece of armour, and tool and bow parts besides. - 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. diff --git a/gradle.properties b/gradle.properties index 12c446b..e8081b0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ neo_version=21.1.248 mod_id=cmmodular mod_name=Create/Mekanism Modular -mod_version=1.2.0 +mod_version=1.3.0 mod_group_id=eu.abdelbaki.cmmodular mod_authors=themiro mod_description=Materials from Create, Mekanism, Ice and Fire, Iron's Spells and the Create aerospace addons, for Truly Modular - plus a khopesh blade and a sealed space suit. diff --git a/src/main/java/eu/abdelbaki/cmmodular/CMModular.java b/src/main/java/eu/abdelbaki/cmmodular/CMModular.java index 4691cbe..ea29e0d 100644 --- a/src/main/java/eu/abdelbaki/cmmodular/CMModular.java +++ b/src/main/java/eu/abdelbaki/cmmodular/CMModular.java @@ -73,6 +73,7 @@ public class CMModular { public CMModular(IEventBus modBus) { FireImmunity.register(modBus); VacuumSeal.register(modBus); + WaterBreathing.register(modBus); modBus.addListener(this::addMaterialPacks); } diff --git a/src/main/java/eu/abdelbaki/cmmodular/WaterBreathing.java b/src/main/java/eu/abdelbaki/cmmodular/WaterBreathing.java new file mode 100644 index 0000000..c1b59ae --- /dev/null +++ b/src/main/java/eu/abdelbaki/cmmodular/WaterBreathing.java @@ -0,0 +1,62 @@ +package eu.abdelbaki.cmmodular; + +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.RangedAttribute; +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.entity.EntityAttributeModificationEvent; +import net.neoforged.neoforge.event.entity.living.LivingBreatheEvent; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +/** + * Sea serpent fang lets its bearer breathe underwater, which is what Ice and + * Fire's own Tide Guardian armour does and the only reason to hunt the thing. + * + *

There is no attribute for it and MIAPI has no property for it either - the + * closest data can get is a fake Respiration enchantment, which only postpones + * drowning. So this follows the pattern {@link FireImmunity} and + * {@link VacuumSeal} already set: an attribute of this mod's own that the + * material grants like any other, and a listener here that watches for it. + * + *

It answers the same event {@link VacuumSeal} does but only underwater, so + * a fang is a fang and not half a spacesuit. + */ +public final class WaterBreathing { + private static final DeferredRegister ATTRIBUTES = + DeferredRegister.create(Registries.ATTRIBUTE, CMModular.MOD_ID); + + /** At or above 1 the bearer never drowns; the fang grants a whole one. */ + public static final DeferredHolder WATER_BREATHING = + ATTRIBUTES.register("water_breathing", id -> new RangedAttribute( + "attribute.cmmodular.water_breathing", 0.0D, 0.0D, 1.0D).setSyncable(true)); + + private WaterBreathing() { + } + + static void register(IEventBus modBus) { + ATTRIBUTES.register(modBus); + modBus.addListener(WaterBreathing::attachToEntities); + // Last, so it answers after whatever said there was no air. + NeoForge.EVENT_BUS.addListener(EventPriority.LOWEST, WaterBreathing::onBreathe); + } + + /** Attributes only exist on an entity if they were added to its type. */ + private static void attachToEntities(EntityAttributeModificationEvent event) { + event.getTypes().forEach(type -> event.add(type, WATER_BREATHING)); + } + + private static void onBreathe(LivingBreatheEvent event) { + if (event.canBreathe() || !event.getEntity().isEyeInFluid(FluidTags.WATER)) { + return; + } + AttributeInstance instance = event.getEntity().getAttribute(WATER_BREATHING); + if (instance != null && instance.getValue() >= 1.0D) { + event.setCanBreathe(true); + } + } +} diff --git a/src/main/resources/assets/cmmodular/lang/en_us.json b/src/main/resources/assets/cmmodular/lang/en_us.json index 6f136e7..3e1a17d 100644 --- a/src/main/resources/assets/cmmodular/lang/en_us.json +++ b/src/main/resources/assets/cmmodular/lang/en_us.json @@ -1,6 +1,7 @@ { "attribute.cmmodular.fire_immunity": "Fire Immunity", "attribute.cmmodular.vacuum_seal": "Vacuum Seal", + "attribute.cmmodular.water_breathing": "Water Breathing", "miapi.module.cmmodular.blade.khopesh.name": "Khopesh Blade", "miapi.module.cmmodular.pommel.gem_socket.name": "Socketed Pommel", diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/dragonbone.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/dragonbone.json index a2aeae3..042da0f 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/dragonbone.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/dragonbone.json @@ -3,6 +3,9 @@ "groups": [ "bone" ], + "hidden_groups": [ + "gem_armor" + ], "icon": { "type": "item", "item": "iceandfire:dragonbone" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/sea_serpent_fang.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/sea_serpent_fang.json new file mode 100644 index 0000000..0359563 --- /dev/null +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/bone/sea_serpent_fang.json @@ -0,0 +1,64 @@ +{ + "translation": "Sea Serpent Fang ", + "groups": [ + "bone" + ], + "hidden_groups": [ + "gem_armor" + ], + "icon": { + "type": "item", + "item": "iceandfire:sea_serpent_fang" + }, + "hardness": 6.0, + "density": 3.0, + "flexibility": 4, + "durability": 760, + "enchantability": 16, + "toughness": 2, + "tier": 4, + "mining_speed": 7, + "mining_level": "minecraft:incorrect_for_diamond_tool", + "armor_durability": 26, + "color": "C8C8C9", + "color_palette": { + "type": "grayscale_map", + "colors": { + "24": "12131d", + "68": "222538", + "107": "525f68", + "150": "525f68", + "190": "8c8c8c", + "216": "c8c8c9", + "255": "e2fffa" + }, + "filler": "interpolate" + }, + "textures": [ + "rough", + "shiny" + ], + "properties": { + "default": { + "attributes": [ + { + "attribute": "cmmodular:water_breathing", + "value": "1", + "operation": "+", + "slot": "any" + } + ] + }, + "boot": { + "fake_enchants": { + "minecraft:depth_strider": 1 + } + } + }, + "items": [ + { + "item": "iceandfire:sea_serpent_fang", + "value": 1.0 + } + ] +} diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_red.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_red.json index 7c32a8a..13226d9 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_red.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_red.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:deathworm_chitin_red" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_white.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_white.json index c0e8ab1..4f894b6 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_white.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_white.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:deathworm_chitin_white" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_yellow.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_yellow.json index 377ca09..0221325 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_yellow.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/deathworm_chitin_yellow.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:deathworm_chitin_yellow" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_amethyst.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_amethyst.json index a833291..6b3da22 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_amethyst.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_amethyst.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_amethyst" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_black.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_black.json index c845e0a..7552590 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_black.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_black.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_black" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_blue.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_blue.json index 5aed92d..cf00d4f 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_blue.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_blue.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_blue" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_bronze.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_bronze.json index c853bea..86946b9 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_bronze.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_bronze.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_bronze" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_copper.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_copper.json index 1217a89..2b6feb0 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_copper.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_copper.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_copper" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_electric.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_electric.json index 1573902..931d4d4 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_electric.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_electric.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_electric" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_gray.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_gray.json index e9e970e..524792c 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_gray.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_gray.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_gray" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_green.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_green.json index bd88933..9ae7fc5 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_green.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_green.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_green" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_red.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_red.json index b2d1f3a..d31315a 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_red.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_red.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_red" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_sapphire.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_sapphire.json index ac64583..c8d8069 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_sapphire.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_sapphire.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_sapphire" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_silver.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_silver.json index 67e9305..a6929a4 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_silver.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_silver.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_silver" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_white.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_white.json index 4259544..7a6b25a 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_white.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/dragonscales_white.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:dragonscales_white" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_blue.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_blue.json index 504476b..e42b91d 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_blue.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_blue.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_blue" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_bronze.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_bronze.json index 2d8a3c6..bdba393 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_bronze.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_bronze.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_bronze" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_deepblue.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_deepblue.json index 0540c00..25f81c1 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_deepblue.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_deepblue.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_deepblue" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_green.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_green.json index 46d2a5c..c7b02ca 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_green.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_green.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_green" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_purple.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_purple.json index 6a7e5c0..c219c4b 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_purple.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_purple.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_purple" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_red.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_red.json index 3284898..423f998 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_red.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_red.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_red" diff --git a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_teal.json b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_teal.json index 47f250c..124927b 100644 --- a/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_teal.json +++ b/src/main/resources/packs/iceandfire/data/cmmodular/miapi/materials/scute/sea_serpent_scales_teal.json @@ -3,6 +3,9 @@ "groups": [ "scute" ], + "hidden_groups": [ + "bone" + ], "icon": { "type": "item", "item": "iceandfire:sea_serpent_scales_teal" diff --git a/tools/generate_materials.py b/tools/generate_materials.py index 211badc..390b39c 100644 --- a/tools/generate_materials.py +++ b/tools/generate_materials.py @@ -183,6 +183,10 @@ def build_material(spec, jars: Jars): out = { "translation": spec["translation"] + " ", # trailing space: "Steel Sword" "groups": spec["groups"], + # Counts for what a module will accept, but is not a heading the + # workbench files the material under. See SCALE_CRAFTING_GROUP. + **({"hidden_groups": spec["hidden_groups"]} + if spec.get("hidden_groups") else {}), "icon": {"type": "item", "item": spec["icon"]}, } out.update(spec["stats"]) diff --git a/tools/materials.py b/tools/materials.py index 5c40a64..dd0a414 100644 --- a/tools/materials.py +++ b/tools/materials.py @@ -80,9 +80,10 @@ PACKS = { "armory": {"mod": "tm_armory", "name": "Armory Modules"}, } -# Attribute this mod registers itself, so a material can grant something the -# game has no attribute for. See FireImmunity.java. +# Attributes this mod registers itself, so a material can grant something the +# game has no attribute for. See FireImmunity.java and WaterBreathing.java. FIRE_IMMUNITY = "cmmodular:fire_immunity" +WATER_BREATHING = "cmmodular:water_breathing" def attribute(attr, value, slot, operation="+"): @@ -91,7 +92,7 @@ def attribute(attr, value, slot, operation="+"): def M(name, pack, group, translation, palette_from, items, tier, hardness, density, flexibility, durability, enchantability, mining_speed, *, groups=None, - toughness=0, armor_durability=None, armor_toughness=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.""" @@ -104,6 +105,7 @@ def M(name, pack, group, translation, palette_from, items, tier, hardness, densi "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": { @@ -418,10 +420,36 @@ MATERIALS = [ {"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",), textures=("rough",), + groups=("bone",), hidden_groups=("gem_armor",), textures=("rough",), properties={"head": {"fracturing": "10"}}), # Vanilla bone with the numbers pushed to diamond tier; keeps the - # fracturing quirk MIAPI gives bone. + # 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"), + properties={ + "default": { + "attributes": [ + # Ice and Fire's own sea serpent armour grants water + # breathing, and that is the whole reason to hunt one. Slot + # `any`, capped at 1 and read as "at or above 1" by the + # handler, so one fang anywhere - socketed, worn or held - is + # enough and a second neither adds nor dilutes, exactly as + # cinder essence does for fire. + attribute(WATER_BREATHING, 1, "any"), + ], + }, + "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}, @@ -1042,6 +1070,25 @@ DRAGON_SCALE_PROPERTIES = { 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 = [] @@ -1057,7 +1104,8 @@ def _scales(): enchantability=15, mining_speed=7, toughness=4, armor_durability=44, armor_toughness=3.5, mining_level=MINING_LEVEL[4], - groups=("scute",), textures=("rough", "shiny"), + 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. @@ -1071,7 +1119,8 @@ def _scales(): 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",), textures=("rough", "shiny"), + groups=("scute",), hidden_groups=SCALE_CRAFTING_GROUP, + textures=("rough", "shiny"), properties={"armor": {"fake_enchants": {"minecraft:respiration": 1}}, "boot": {"fake_enchants": {"minecraft:depth_strider": 1}}})) for color, label in DEATHWORM_COLORS.items(): @@ -1082,7 +1131,8 @@ def _scales(): 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",), textures=("rough",), + groups=("scute",), hidden_groups=SCALE_CRAFTING_GROUP, + textures=("rough",), properties={"default": {"fire_proof": True}})) # Desert worms, so heat immunity comes with the shell. return out