diff --git a/.gitignore b/.gitignore index 413ebaa9..7419408c 100644 --- a/.gitignore +++ b/.gitignore @@ -120,3 +120,6 @@ runs/ **/.cache/ .kotlin/ + +# Extracted dependency sources used for local API lookup +reference/ diff --git a/AGENTS.md b/AGENTS.md index d0fdabe0..dbdbbb62 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,3 +13,20 @@ ## Tool Preference For Other Work For tasks other than searching or reading project files, prefer IDEA MCP tools and the `workspace-agent-bridge` skill when they provide the relevant operation, such as diagnostics, formatting, refactoring, or other IDE-aware actions. + +## Language File Generation + +1. English language files (`en_us.json` / `en_ud.json`) are generated by datagen from `src/main/java/dev/anvilcraft/pigsplus/data/lang/`. +2. Simplified Chinese is manually maintained at `src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json`. Do not generate `zh_cn.json` with datagen, otherwise it will overwrite or conflict with the manual file. +3. When adding an English key to a datagen provider, add the corresponding Chinese key to the manual `zh_cn.json` so the two key sets stay unified. +4. Do not manually edit files under `src/generated/resources/`; `runData` will overwrite them. +5. If a new UI, JEI, Jade, Ageratum, recipe, Modify, or Requirement text is added, add its English key in `LangHandler` / `JeiLang` / `RecipeLang` and its Chinese key in the manual `zh_cn.json`. + +## Nullability + +1. Code defaults to non-null via `package-info.java` (`@ParametersAreNonnullByDefault` / `@MethodsReturnNonnullByDefault`). +2. Any parameter, field, or return that can be null must be annotated with `@Nullable` (`org.jetbrains.annotations.Nullable`), and callers must handle the nullable result. + +## Code Style + +1. Prefix accesses to the current instance's own fields and calls to its own methods with `this.` (e.g. `this.progress`, `this.syncState(be)`). diff --git a/gradle.properties b/gradle.properties index 029f75b8..719ce6c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,10 +21,10 @@ curseforge_id=1380275 mod_id=anvilcraft_pigsplus mod_name=AnvilCraft-PigsPlus mod_license=LGPL-3.0 license -mod_version=2.6.0 +mod_version=2.7.0 maven_group=dev.anvilcraft.pigsplus mod_authors=TB_pig -mod_description=tools made by TB_pig +mod_description=tools made by TB_pig & draw by LuanHongKeZhen systemProp.file.encoding=UTF-8 systemProp.sun.jnu.encoding=UTF-8 diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json index 2a39172c..9987ab03 100644 --- a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json @@ -24,6 +24,8 @@ "anvilcraft_pigsplus.configuration.enchanted_generator.tooltip": "ɹoʇɐɹǝuǝ⅁ pǝʇuɐɥɔuƎ", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion": "uoᴉsɹǝʌuoƆ ʎᵷɹǝuƎ ɹǝᵷɹɐɥƆ ssǝꞁǝɹᴉM ǝꞁqɐʇɹoԀ", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion.tooltip": "(Mʞ) ɹǝᵷɹɐɥɔ ssǝꞁǝɹᴉʍ ǝꞁqɐʇɹod ɟo ʎʇᴉʇuɐnb uoᴉsɹǝʌuoɔ ʎᵷɹǝuƎ", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown": "uʍopꞁooƆ uoᴉʇdɹosqⱯ ɹǝɯɹoɟǝᴚ", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown.tooltip": "(sʞɔᴉʇ uᴉ) ɹǝɯɹoɟǝɹ ɹɐʇs/ʎɹɐʇǝuɐꞁd ɟo ꞁɐʌɹǝʇuᴉ uoᴉʇdɹosqⱯ", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "uoᴉʇɐɹnᵷᴉɟuoƆ ɹǝʌɹǝS snꞁdsᵷᴉԀ ʇɟɐɹɔꞁᴉʌuⱯ", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "uoᴉʇɐɹnᵷᴉɟuoƆ ɹǝʌɹǝS snꞁdsᵷᴉԀ ʇɟɐɹɔꞁᴉʌuⱯ", "anvilcraft_pigsplus.configuration.title": "uoᴉʇɐɹnᵷᴉɟuoƆ snꞁdsᵷᴉԀ ʇɟɐɹɔꞁᴉʌuⱯ", @@ -55,13 +57,34 @@ "block.anvilcraft_pigsplus.void_acid_cauldron": "uoɹpꞁnɐƆ pᴉɔⱯ pᴉoɅ", "block.anvilcraft_pigsplus.void_catalyst": "ʇsʎꞁɐʇɐƆ pᴉoɅ", "block.anvilcraft_pigsplus.weak_resin_block": "uᴉsǝᴚ ʞɐǝM ɟo ʞɔoꞁᗺ", + "concept.anvilcraft_pigsplus.atmosphere": "ǝɹǝɥdsoɯʇⱯ", + "concept.anvilcraft_pigsplus.biologic": "sǝɔɹnosǝᴚ ꞁɐɔᴉᵷoꞁoᴉᗺ", + "concept.anvilcraft_pigsplus.civilization": "uoᴉʇɐzᴉꞁᴉʌᴉƆ", + "concept.anvilcraft_pigsplus.default": "ʇdǝɔuoƆ uʍouʞu∩", + "concept.anvilcraft_pigsplus.laser": "ɹǝsɐꞀ", + "concept.anvilcraft_pigsplus.magnetic_field": "pꞁǝᴉℲ ɔᴉʇǝuᵷɐW", + "concept.anvilcraft_pigsplus.plante_type": "ǝdʎ⟘ ʇǝuɐꞁԀ", + "concept.anvilcraft_pigsplus.reformer": "ɹǝɯɹoɟǝᴚ", + "concept.anvilcraft_pigsplus.rotation_speed": "pǝǝdS uoᴉʇɐʇoᴚ", + "concept.anvilcraft_pigsplus.sea": "ǝᵷɐɹǝʌoƆ pᴉnbᴉꞀ", + "concept.anvilcraft_pigsplus.temperature": "ǝɹnʇɐɹǝdɯǝ⟘", + "config.jade.plugin_anvilcraft_pigsplus.celestial_reformer": "ɹǝɯɹoɟǝᴚ ꞁɐᴉʇsǝꞁǝƆ", "config.jade.plugin_anvilcraft_pigsplus.electric_enchanting_table": "ǝꞁqɐ⟘ ᵷuᴉʇuɐɥɔuƎ ɔᴉɹʇɔǝꞁƎ", "config.jade.plugin_anvilcraft_pigsplus.enchanted_generator": "ɹoʇɐɹǝuǝ⅁ pǝʇuɐɥɔuƎ", "config.jade.plugin_anvilcraft_pigsplus.precision_magnetic_pivot": "ʇoʌᴉԀ ɔᴉʇǝuᵷɐW uoᴉsᴉɔǝɹԀ", + "enchantment.anvilcraft_pigsplus.endurance": "ǝɔuɐɹnpuƎ", + "gui.anvilcraft_pigsplus.category.celestial_reformer": "ɹǝɯɹoɟǝᴚ ꞁɐᴉʇsǝꞁǝƆ", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing": "ᵷuᴉssǝɔoɹԀ ɔᴉʇǝuᵷɐɯoɹʇɔǝꞁƎ uoᴉsᴉɔǝɹԀ", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.consume_fluid": "%2$s ɟo ᗺɯ %1$d :ǝɯnsuoƆ", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.need_activated": "pǝʇɐʌᴉʇɔɐ ǝq oʇ spǝǝN", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.produce_fluid": "%2$s ɟo ᗺɯ %1$d :ǝɔnpoɹԀ", + "gui.anvilcraft_pigsplus.jei.fluid": "ᗺɯ %s :%s :pᴉnꞁℲ", + "gui.anvilcraft_pigsplus.jei.laser": "(%s) %s ꞁǝʌǝꞁ :ɹǝsɐꞀ", + "gui.anvilcraft_pigsplus.jei.modification": "%s :uoᴉʇɐɔᴉɟᴉpoW", + "gui.anvilcraft_pigsplus.laser.type.any": "ɹǝsɐꞁ ʎuⱯ", + "gui.anvilcraft_pigsplus.laser.type.gamma": "ɹǝsɐꞁ ɐɯɯɐ⅁", + "gui.anvilcraft_pigsplus.laser.type.normal": "ɹǝsɐꞁ ꞁɐɯɹoN", + "item.anvilcraft_pigsplus.celestial_reformer_component": "ʇuǝuodɯoƆ ɹǝɯɹoɟǝᴚ ꞁɐᴉʇsǝꞁǝƆ", "item.anvilcraft_pigsplus.chaotic_raw_ore": "ǝɹO ʍɐᴚ ɔᴉʇoɐɥƆ", "item.anvilcraft_pigsplus.echo_geode": "ǝpoǝ⅁ oɥɔƎ", "item.anvilcraft_pigsplus.ender_component": "ʇuǝuodɯoƆ ɹǝpuƎ", @@ -75,6 +98,52 @@ "itemGroup.anvilcraft_pigsplus.addon_items": "snꞁԀ sᵷᴉԀ :ʇɟɐɹƆꞁᴉʌuⱯ", "jei.anvilcraft.pigsplus.info.ender_component": "˙ʇuǝuodɯoƆ ɹǝpuƎ ɐ uᴉɐʇqo oʇ ǝɔuɐɥɔ %%%.0f ɐ sᴉ ǝɹǝɥʇ 'ꞁɐʇɹod puƎ ǝɥʇ oʇuᴉ ʇuǝuodɯoƆ ᴉɹnʞɐɹɐꞰ ɐ ʍoɹɥ⟘", "jei.anvilcraft.pigsplus.info.spiritual_component": "˙ʇuǝuodɯoƆ ɯnᴉpǝW ǝuo ʇsoɯ ʇɐ ǝʇɐɹǝuǝᵷ oʇ ǝɔuɐɥɔ %%%.0f ɐ sǝpᴉʌoɹd ʇuǝɯʇuɐɥɔuǝ ɥɔɐǝ 'pǝʎoɹʇsǝp sᴉ ʇuǝuodɯoƆ ᴉɹnʞɐɹɐꞰ ɐ uǝɥM", + "modification.anvilcraft_pigsplus.add_atmosphere": "ǝɹǝɥdsoɯʇⱯ ppⱯ", + "modification.anvilcraft_pigsplus.add_biological_resources": "sǝɔɹnosǝᴚ ꞁɐɔᴉᵷoꞁoᴉᗺ ppⱯ", + "modification.anvilcraft_pigsplus.add_civilization": "uoᴉʇɐzᴉꞁᴉʌᴉƆ ʍoꞀ ppⱯ", + "modification.anvilcraft_pigsplus.decrease_liquid_coverage": "ǝᵷɐɹǝʌoƆ uɐǝɔO ǝsɐǝɹɔǝᗡ", + "modification.anvilcraft_pigsplus.decrease_temperature": "ǝɹnʇɐɹǝdɯǝ⟘ ǝsɐǝɹɔǝᗡ", + "modification.anvilcraft_pigsplus.fast_rotation": "uoᴉʇɐʇoᴚ d∩ pǝǝdS", + "modification.anvilcraft_pigsplus.increase_liquid_coverage": "ǝᵷɐɹǝʌoƆ uɐǝɔO ǝsɐǝɹɔuI", + "modification.anvilcraft_pigsplus.increase_temperature": "ǝɹnʇɐɹǝdɯǝ⟘ ǝsɐǝɹɔuI", + "modification.anvilcraft_pigsplus.slow_rotation": "uoᴉʇɐʇoᴚ uʍoᗡ ʍoꞁS", + "modification.anvilcraft_pigsplus.strengthen_magnetic_field": "pꞁǝᴉℲ ɔᴉʇǝuᵷɐW uǝɥʇᵷuǝɹʇS", + "modification.anvilcraft_pigsplus.unknown": "uoᴉʇɐɔᴉɟᴉpoW uʍouʞu∩", + "modification.anvilcraft_pigsplus.void_wasteland": "puɐꞁǝʇsɐM pᴉoɅ oʇuI uɹn⟘", + "modification.anvilcraft_pigsplus.wasteland": "puɐꞁǝʇsɐM oʇuI uɹn⟘", + "modification.anvilcraft_pigsplus.weaken_magnetic_field": "pꞁǝᴉℲ ɔᴉʇǝuᵷɐW uǝʞɐǝM", + "requirement.anvilcraft_pigsplus.has_atmosphere": "ǝɹǝɥdsoɯʇⱯ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.has_biological_resources": "sǝɔɹnosǝᴚ ꞁɐɔᴉᵷoꞁoᴉᗺ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.has_civilization": "uoᴉʇɐzᴉꞁᴉʌᴉƆ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.has_liquid": "pᴉnbᴉꞀ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.has_other_megastructure": "ǝɹnʇɔnɹʇsɐᵷǝW ɹǝɥʇouⱯ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_least": "%s =< ǝᵷɐɹǝʌoƆ pᴉnbᴉꞀ", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_most": "%s => ǝᵷɐɹǝʌoƆ pᴉnbᴉꞀ", + "requirement.anvilcraft_pigsplus.liquid_coverage_between": "%s - %s ǝᵷɐɹǝʌoƆ pᴉnbᴉꞀ", + "requirement.anvilcraft_pigsplus.magnetic_field_at_least": "%s =< pꞁǝᴉℲ ɔᴉʇǝuᵷɐW", + "requirement.anvilcraft_pigsplus.magnetic_field_at_most": "%s => pꞁǝᴉℲ ɔᴉʇǝuᵷɐW", + "requirement.anvilcraft_pigsplus.magnetic_field_between": "%s => puɐ %s =< pꞁǝᴉℲ ɔᴉʇǝuᵷɐW", + "requirement.anvilcraft_pigsplus.no_atmosphere": "ǝɹǝɥdsoɯʇⱯ oN sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.no_liquid": "pᴉnbᴉꞀ oN sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.no_other_megastructure": "ǝɹnʇɔnɹʇsɐᵷǝW ɹǝɥʇO oN sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.planetary_reformer": "ɹǝɯɹoɟǝᴚ ʎɹɐʇǝuɐꞁԀ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.rocky_planet": "ʇǝuɐꞁԀ ʎʞɔoᴚ sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.rotation_speed_at_least": "%s =< pǝǝdS uoᴉʇɐʇoᴚ", + "requirement.anvilcraft_pigsplus.rotation_speed_at_most": "%s => pǝǝdS uoᴉʇɐʇoᴚ", + "requirement.anvilcraft_pigsplus.rotation_speed_between": "%s => puɐ %s =< pǝǝdS uoᴉʇɐʇoᴚ", + "requirement.anvilcraft_pigsplus.star_reformer": "ɹǝɯɹoɟǝᴚ ɹɐʇS sǝɹᴉnbǝᴚ", + "requirement.anvilcraft_pigsplus.temperature_at_least": "%s =< ǝɹnʇɐɹǝdɯǝ⟘", + "requirement.anvilcraft_pigsplus.temperature_at_most": "%s => ǝɹnʇɐɹǝdɯǝ⟘", + "requirement.anvilcraft_pigsplus.temperature_between": "%s - %s ǝɹnʇɐɹǝdɯǝ⟘", + "requirement.anvilcraft_pigsplus.unknown": "ʇuǝɯǝɹᴉnbǝᴚ uʍouʞu∩", + "requirement.anvilcraft_pigsplus.water_ocean": "ǝᵷɐɹǝʌoƆ ꞁꞁnℲ ʍoꞁǝᗺ uɐǝɔO ɹǝʇɐM ɹO pᴉnbᴉꞀ oN sǝɹᴉnbǝᴚ", + "screen.anvilcraft.cfa.megastructure.planetary_reformer": "ɹǝɯɹoɟǝᴚ ʎɹɐʇǝuɐꞁԀ", + "screen.anvilcraft.cfa.megastructure.planetary_reformer.usage": "˙ʎpoq ꞁɐᴉʇsǝꞁǝɔ ǝɥʇ ɯɹoɟǝɹ oʇ sǝɔɹnosǝɹ ǝɯnsuoƆ", + "screen.anvilcraft.cfa.megastructure.star_reformer": "ɹǝɯɹoɟǝᴚ ɹɐʇS", + "screen.anvilcraft.cfa.megastructure.star_reformer.usage": "˙ʎpoq ꞁɐᴉʇsǝꞁǝɔ ǝɥʇ ɯɹoɟǝɹ oʇ sǝɔɹnosǝɹ ǝɯnsuoƆ", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.fluid": "ᗺɯ %s / %s :%s", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.item": "%s / %s :%s", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser": "(%s) %s ꞁǝʌǝꞁ :ɹǝsɐꞀ", "tooltip.anvilcraft_pigsplus.enchanted_generator.decrease_rate": "%s :ǝʇɐɹ ǝsɐǝɹɔǝp ԀX", "tooltip.anvilcraft_pigsplus.menger_sponge_staff": "pᴉnbᴉꞁ ɟo ʇunoɯɐ ǝᵷɹɐꞁ ɐ ǝʌoɯǝᴚ", "tooltip.anvilcraft_pigsplus.portable_wireless_charger": "ʇ/ƎℲ %d sǝʇɐɹǝuǝᵷ puɐ Mʞ %d sǝɯnsuoɔ ʇᴉ 'ʞɔɐdʞɔɐq uǝɥM", @@ -87,6 +156,5 @@ "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.pre_direction.none": "ǝuoN", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time": "%s :snʇɐʇS", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.stopped": "pǝddoʇS", - "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "ᵷuᴉʞɹoM", - "enchantment.anvilcraft_pigsplus.endurance": "??u??npn?" -} + "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "ᵷuᴉʞɹoM" +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json index 4c2bd1e7..339cf6a5 100644 --- a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json @@ -24,6 +24,8 @@ "anvilcraft_pigsplus.configuration.enchanted_generator.tooltip": "Enchanted Generator", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion": "Portable Wireless Charger Energy Conversion", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion.tooltip": "Energy conversion quantity of portable wireless charger (kW)", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown": "Reformer Absorption Cooldown", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown.tooltip": "Absorption interval of planetary/star reformer (in ticks)", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "Anvilcraft Pigsplus Server Configuration", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "Anvilcraft Pigsplus Server Configuration", "anvilcraft_pigsplus.configuration.title": "Anvilcraft Pigsplus Configuration", @@ -55,13 +57,34 @@ "block.anvilcraft_pigsplus.void_acid_cauldron": "Void Acid Cauldron", "block.anvilcraft_pigsplus.void_catalyst": "Void Catalyst", "block.anvilcraft_pigsplus.weak_resin_block": "Block of Weak Resin", + "concept.anvilcraft_pigsplus.atmosphere": "Atmosphere", + "concept.anvilcraft_pigsplus.biologic": "Biological Resources", + "concept.anvilcraft_pigsplus.civilization": "Civilization", + "concept.anvilcraft_pigsplus.default": "Unknown Concept", + "concept.anvilcraft_pigsplus.laser": "Laser", + "concept.anvilcraft_pigsplus.magnetic_field": "Magnetic Field", + "concept.anvilcraft_pigsplus.plante_type": "Planet Type", + "concept.anvilcraft_pigsplus.reformer": "Reformer", + "concept.anvilcraft_pigsplus.rotation_speed": "Rotation Speed", + "concept.anvilcraft_pigsplus.sea": "Liquid Coverage", + "concept.anvilcraft_pigsplus.temperature": "Temperature", + "config.jade.plugin_anvilcraft_pigsplus.celestial_reformer": "Celestial Reformer", "config.jade.plugin_anvilcraft_pigsplus.electric_enchanting_table": "Electric Enchanting Table", "config.jade.plugin_anvilcraft_pigsplus.enchanted_generator": "Enchanted Generator", "config.jade.plugin_anvilcraft_pigsplus.precision_magnetic_pivot": "Precision Magnetic Pivot", + "enchantment.anvilcraft_pigsplus.endurance": "Endurance", + "gui.anvilcraft_pigsplus.category.celestial_reformer": "Celestial Reformer", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing": "Precision Electromagnetic Processing", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.consume_fluid": "Consume: %1$d mB of %2$s", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.need_activated": "Needs to be activated", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.produce_fluid": "Produce: %1$d mB of %2$s", + "gui.anvilcraft_pigsplus.jei.fluid": "Fluid: %s: %s mB", + "gui.anvilcraft_pigsplus.jei.laser": "Laser: level %s (%s)", + "gui.anvilcraft_pigsplus.jei.modification": "Modification: %s", + "gui.anvilcraft_pigsplus.laser.type.any": "Any laser", + "gui.anvilcraft_pigsplus.laser.type.gamma": "Gamma laser", + "gui.anvilcraft_pigsplus.laser.type.normal": "Normal laser", + "item.anvilcraft_pigsplus.celestial_reformer_component": "Celestial Reformer Component", "item.anvilcraft_pigsplus.chaotic_raw_ore": "Chaotic Raw Ore", "item.anvilcraft_pigsplus.echo_geode": "Echo Geode", "item.anvilcraft_pigsplus.ender_component": "Ender Component", @@ -75,6 +98,52 @@ "itemGroup.anvilcraft_pigsplus.addon_items": "AnvilCraft: Pigs Plus", "jei.anvilcraft.pigsplus.info.ender_component": "Throw a Karakuri Component into the End portal, there is a %.0f%% chance to obtain a Ender Component.", "jei.anvilcraft.pigsplus.info.spiritual_component": "When a Karakuri Component is destroyed, each enchantment provides a %.0f%% chance to generate at most one Medium Component.", + "modification.anvilcraft_pigsplus.add_atmosphere": "Add Atmosphere", + "modification.anvilcraft_pigsplus.add_biological_resources": "Add Biological Resources", + "modification.anvilcraft_pigsplus.add_civilization": "Add Low Civilization", + "modification.anvilcraft_pigsplus.decrease_liquid_coverage": "Decrease Ocean Coverage", + "modification.anvilcraft_pigsplus.decrease_temperature": "Decrease Temperature", + "modification.anvilcraft_pigsplus.fast_rotation": "Speed Up Rotation", + "modification.anvilcraft_pigsplus.increase_liquid_coverage": "Increase Ocean Coverage", + "modification.anvilcraft_pigsplus.increase_temperature": "Increase Temperature", + "modification.anvilcraft_pigsplus.slow_rotation": "Slow Down Rotation", + "modification.anvilcraft_pigsplus.strengthen_magnetic_field": "Strengthen Magnetic Field", + "modification.anvilcraft_pigsplus.unknown": "Unknown Modification", + "modification.anvilcraft_pigsplus.void_wasteland": "Turn Into Void Wasteland", + "modification.anvilcraft_pigsplus.wasteland": "Turn Into Wasteland", + "modification.anvilcraft_pigsplus.weaken_magnetic_field": "Weaken Magnetic Field", + "requirement.anvilcraft_pigsplus.has_atmosphere": "Requires Atmosphere", + "requirement.anvilcraft_pigsplus.has_biological_resources": "Requires Biological Resources", + "requirement.anvilcraft_pigsplus.has_civilization": "Requires Civilization", + "requirement.anvilcraft_pigsplus.has_liquid": "Requires Liquid", + "requirement.anvilcraft_pigsplus.has_other_megastructure": "Requires Another Megastructure", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_least": "Liquid Coverage >= %s", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_most": "Liquid Coverage <= %s", + "requirement.anvilcraft_pigsplus.liquid_coverage_between": "Liquid Coverage %s - %s", + "requirement.anvilcraft_pigsplus.magnetic_field_at_least": "Magnetic Field >= %s", + "requirement.anvilcraft_pigsplus.magnetic_field_at_most": "Magnetic Field <= %s", + "requirement.anvilcraft_pigsplus.magnetic_field_between": "Magnetic Field >= %s and <= %s", + "requirement.anvilcraft_pigsplus.no_atmosphere": "Requires No Atmosphere", + "requirement.anvilcraft_pigsplus.no_liquid": "Requires No Liquid", + "requirement.anvilcraft_pigsplus.no_other_megastructure": "Requires No Other Megastructure", + "requirement.anvilcraft_pigsplus.planetary_reformer": "Requires Planetary Reformer", + "requirement.anvilcraft_pigsplus.rocky_planet": "Requires Rocky Planet", + "requirement.anvilcraft_pigsplus.rotation_speed_at_least": "Rotation Speed >= %s", + "requirement.anvilcraft_pigsplus.rotation_speed_at_most": "Rotation Speed <= %s", + "requirement.anvilcraft_pigsplus.rotation_speed_between": "Rotation Speed >= %s and <= %s", + "requirement.anvilcraft_pigsplus.star_reformer": "Requires Star Reformer", + "requirement.anvilcraft_pigsplus.temperature_at_least": "Temperature >= %s", + "requirement.anvilcraft_pigsplus.temperature_at_most": "Temperature <= %s", + "requirement.anvilcraft_pigsplus.temperature_between": "Temperature %s - %s", + "requirement.anvilcraft_pigsplus.unknown": "Unknown Requirement", + "requirement.anvilcraft_pigsplus.water_ocean": "Requires No Liquid Or Water Ocean Below Full Coverage", + "screen.anvilcraft.cfa.megastructure.planetary_reformer": "Planetary Reformer", + "screen.anvilcraft.cfa.megastructure.planetary_reformer.usage": "Consume resources to reform the celestial body.", + "screen.anvilcraft.cfa.megastructure.star_reformer": "Star Reformer", + "screen.anvilcraft.cfa.megastructure.star_reformer.usage": "Consume resources to reform the celestial body.", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.fluid": "%s: %s / %s mB", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.item": "%s: %s / %s", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser": "Laser: level %s (%s)", "tooltip.anvilcraft_pigsplus.enchanted_generator.decrease_rate": "XP decrease rate: %s", "tooltip.anvilcraft_pigsplus.menger_sponge_staff": "Remove a large amount of liquid", "tooltip.anvilcraft_pigsplus.portable_wireless_charger": "When backpack, it consumes %d kW and generates %d FE/t", @@ -87,6 +156,5 @@ "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.pre_direction.none": "None", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time": "Status: %s", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.stopped": "Stopped", - "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "Working", - "enchantment.anvilcraft_pigsplus.endurance": "Endurance" -} + "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "Working" +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/models/item/celestial_reformer_component.json b/src/generated/resources/assets/anvilcraft_pigsplus/models/item/celestial_reformer_component.json new file mode 100644 index 00000000..6d98167b --- /dev/null +++ b/src/generated/resources/assets/anvilcraft_pigsplus/models/item/celestial_reformer_component.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "anvilcraft_pigsplus:item/celestial_reformer_component" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/tags/item/explosion_proof.json b/src/generated/resources/data/anvilcraft/tags/item/explosion_proof.json new file mode 100644 index 00000000..9acb37eb --- /dev/null +++ b/src/generated/resources/data/anvilcraft/tags/item/explosion_proof.json @@ -0,0 +1,6 @@ +{ + "values": [ + "anvilcraft_pigsplus:celestial_reformer_component", + "anvilcraft_pigsplus:menger_sponge_holy_staff" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_atmosphere.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_atmosphere.json new file mode 100644 index 00000000..294b8ee6 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_atmosphere.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/add_atmosphere" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/add_atmosphere" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_biological_resources.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_biological_resources.json new file mode 100644 index 00000000..42854b0c --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_biological_resources.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/add_biological_resources" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/add_biological_resources" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_civilization.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_civilization.json new file mode 100644 index 00000000..d376251a --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/add_civilization.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/add_civilization" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/add_civilization" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_liquid_coverage.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_liquid_coverage.json new file mode 100644 index 00000000..bf40ee20 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_liquid_coverage.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/decrease_liquid_coverage" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/decrease_liquid_coverage" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_temperature.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_temperature.json new file mode 100644 index 00000000..9612f974 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/decrease_temperature.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/decrease_temperature" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/decrease_temperature" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/fast_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/fast_rotation.json new file mode 100644 index 00000000..9a0d4efb --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/fast_rotation.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/fast_rotation" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/fast_rotation" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_liquid_coverage.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_liquid_coverage.json new file mode 100644 index 00000000..0110e1f7 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_liquid_coverage.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/increase_liquid_coverage" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/increase_liquid_coverage" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_temperature.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_temperature.json new file mode 100644 index 00000000..bd001697 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/increase_temperature.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/increase_temperature" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/increase_temperature" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/slow_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/slow_rotation.json new file mode 100644 index 00000000..3373a3c4 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/slow_rotation.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/slow_rotation" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/slow_rotation" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_fast_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_fast_rotation.json new file mode 100644 index 00000000..d0509723 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_fast_rotation.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/star_fast_rotation" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/star_fast_rotation" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_slow_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_slow_rotation.json new file mode 100644 index 00000000..e2e0111f --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_slow_rotation.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/star_slow_rotation" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/star_slow_rotation" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_strengthen_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_strengthen_magnetic_field.json new file mode 100644 index 00000000..2bc4f217 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_strengthen_magnetic_field.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/star_strengthen_magnetic_field" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/star_strengthen_magnetic_field" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_weaken_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_weaken_magnetic_field.json new file mode 100644 index 00000000..8c3c3986 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/star_weaken_magnetic_field.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/star_weaken_magnetic_field" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/star_weaken_magnetic_field" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/strengthen_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/strengthen_magnetic_field.json new file mode 100644 index 00000000..ce197026 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/strengthen_magnetic_field.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/strengthen_magnetic_field" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/strengthen_magnetic_field" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/void_wasteland.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/void_wasteland.json new file mode 100644 index 00000000..bd934207 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/void_wasteland.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/void_wasteland" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/void_wasteland" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/wasteland.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/wasteland.json new file mode 100644 index 00000000..10d065c4 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/wasteland.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/wasteland" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/wasteland" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/weaken_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/weaken_magnetic_field.json new file mode 100644 index 00000000..da56ed7e --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/celestial_reformer/weaken_magnetic_field.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer/weaken_magnetic_field" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer/weaken_magnetic_field" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/misc/celestial_reformer_component.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/misc/celestial_reformer_component.json new file mode 100644 index 00000000..fc6f6104 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/misc/celestial_reformer_component.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:celestial_reformer_component" + }, + "trigger": "minecraft:recipe_unlocked" + }, + "has_transcendium_ingot": { + "conditions": { + "items": [ + { + "items": "anvilcraft:transcendium_ingot" + } + ] + }, + "trigger": "minecraft:inventory_changed" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_transcendium_ingot" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:celestial_reformer_component" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_atmosphere.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_atmosphere.json new file mode 100644 index 00000000..e8e634b8 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_atmosphere.json @@ -0,0 +1,21 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "minecraft:glass_bottle" + } + ], + "modification": "anvilcraft_pigsplus:add_atmosphere", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:no_atmosphere" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_biological_resources.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_biological_resources.json new file mode 100644 index 00000000..397c42cd --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_biological_resources.json @@ -0,0 +1,42 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "minecraft:bone_block" + }, + { + "count": 320, + "item": "minecraft:moss_block" + }, + { + "count": 320, + "item": "minecraft:cod" + } + ], + "modification": "anvilcraft_pigsplus:add_biological_resources", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:has_atmosphere" + }, + { + "requirement": "anvilcraft_pigsplus:has_liquid" + }, + { + "max": "medium", + "min": "none", + "requirement": "anvilcraft_pigsplus:liquid_coverage_range" + }, + { + "max": "mild", + "min": "mild", + "requirement": "anvilcraft_pigsplus:temperature_range" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_civilization.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_civilization.json new file mode 100644 index 00000000..00d2274c --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/add_civilization.json @@ -0,0 +1,32 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "fluids": [ + { + "amount": 1280000, + "fluid": "anvilcraft:exp_fluid" + } + ], + "items": [ + { + "count": 1280, + "item": "minecraft:book" + } + ], + "modification": "anvilcraft_pigsplus:add_civilization", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:has_biological_resources" + }, + { + "max": "medium", + "min": "medium", + "requirement": "anvilcraft_pigsplus:liquid_coverage_range" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_liquid_coverage.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_liquid_coverage.json new file mode 100644 index 00000000..e308f9ac --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_liquid_coverage.json @@ -0,0 +1,21 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "minecraft:bucket" + } + ], + "modification": "anvilcraft_pigsplus:decrease_liquid_coverage", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:has_liquid" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_temperature.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_temperature.json new file mode 100644 index 00000000..f873f095 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/decrease_temperature.json @@ -0,0 +1,23 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "minecraft:blue_ice" + } + ], + "modification": "anvilcraft_pigsplus:decrease_temperature", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "max": "scorched", + "min": "cold", + "requirement": "anvilcraft_pigsplus:temperature_range" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/fast_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/fast_rotation.json new file mode 100644 index 00000000..b88060c2 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/fast_rotation.json @@ -0,0 +1,19 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 640, + "item": "anvilcraft:sugar_block" + } + ], + "modification": "anvilcraft_pigsplus:fast_rotation", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "max": 3, + "requirement": "anvilcraft_pigsplus:rotation_speed" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_liquid_coverage.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_liquid_coverage.json new file mode 100644 index 00000000..810b13ef --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_liquid_coverage.json @@ -0,0 +1,21 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "fluids": [ + { + "amount": 320000, + "fluid": "minecraft:water" + } + ], + "modification": "anvilcraft_pigsplus:increase_liquid_coverage", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:water_ocean" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_temperature.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_temperature.json new file mode 100644 index 00000000..2b16dc98 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/increase_temperature.json @@ -0,0 +1,23 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "anvilcraft:heated_tungsten_block" + } + ], + "modification": "anvilcraft_pigsplus:increase_temperature", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "max": "hot", + "min": "freezing", + "requirement": "anvilcraft_pigsplus:temperature_range" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/slow_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/slow_rotation.json new file mode 100644 index 00000000..8ad71826 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/slow_rotation.json @@ -0,0 +1,19 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 640, + "item": "anvilcraft:lead_block" + } + ], + "modification": "anvilcraft_pigsplus:slow_rotation", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "min": 1, + "requirement": "anvilcraft_pigsplus:rotation_speed" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_fast_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_fast_rotation.json new file mode 100644 index 00000000..7d4e72a1 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_fast_rotation.json @@ -0,0 +1,25 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 3200, + "item": "anvilcraft:sugar_block" + } + ], + "lasers": [ + { + "type": "any", + "level": 16 + } + ], + "modification": "anvilcraft_pigsplus:fast_rotation", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:star_reformer" + }, + { + "max": 3, + "requirement": "anvilcraft_pigsplus:rotation_speed" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_slow_rotation.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_slow_rotation.json new file mode 100644 index 00000000..874f7cd7 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_slow_rotation.json @@ -0,0 +1,25 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 3200, + "item": "anvilcraft:lead_block" + } + ], + "lasers": [ + { + "type": "any", + "level": 16 + } + ], + "modification": "anvilcraft_pigsplus:slow_rotation", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:star_reformer" + }, + { + "min": 1, + "requirement": "anvilcraft_pigsplus:rotation_speed" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_strengthen_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_strengthen_magnetic_field.json new file mode 100644 index 00000000..e8194902 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_strengthen_magnetic_field.json @@ -0,0 +1,25 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 3200, + "item": "anvilcraft:magnet_block" + } + ], + "lasers": [ + { + "type": "any", + "level": 16 + } + ], + "modification": "anvilcraft_pigsplus:strengthen_magnetic_field", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:star_reformer" + }, + { + "max": 3, + "requirement": "anvilcraft_pigsplus:magnetic_field" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_weaken_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_weaken_magnetic_field.json new file mode 100644 index 00000000..047bad02 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/star_weaken_magnetic_field.json @@ -0,0 +1,25 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 3200, + "item": "minecraft:heavy_weighted_pressure_plate" + } + ], + "lasers": [ + { + "type": "any", + "level": 16 + } + ], + "modification": "anvilcraft_pigsplus:weaken_magnetic_field", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:star_reformer" + }, + { + "min": 1, + "requirement": "anvilcraft_pigsplus:magnetic_field" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/strengthen_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/strengthen_magnetic_field.json new file mode 100644 index 00000000..b2ef2c7e --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/strengthen_magnetic_field.json @@ -0,0 +1,19 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 640, + "item": "anvilcraft:magnet_block" + } + ], + "modification": "anvilcraft_pigsplus:strengthen_magnetic_field", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "max": 3, + "requirement": "anvilcraft_pigsplus:magnetic_field" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/void_wasteland.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/void_wasteland.json new file mode 100644 index 00000000..b6b6c5ca --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/void_wasteland.json @@ -0,0 +1,21 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "fluids": [ + { + "amount": 320000, + "fluid": "anvilcraft_pigsplus:void_acid" + } + ], + "modification": "anvilcraft_pigsplus:void_wasteland", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:has_civilization" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/wasteland.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/wasteland.json new file mode 100644 index 00000000..cd76e3b0 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/wasteland.json @@ -0,0 +1,21 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 320, + "item": "anvilcraft:plutonium_block" + } + ], + "modification": "anvilcraft_pigsplus:wasteland", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "requirement": "anvilcraft_pigsplus:rocky_planet" + }, + { + "requirement": "anvilcraft_pigsplus:has_civilization" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/weaken_magnetic_field.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/weaken_magnetic_field.json new file mode 100644 index 00000000..9e2fdef4 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer/weaken_magnetic_field.json @@ -0,0 +1,19 @@ +{ + "type": "anvilcraft_pigsplus:celestial_reformer", + "items": [ + { + "count": 640, + "item": "minecraft:heavy_weighted_pressure_plate" + } + ], + "modification": "anvilcraft_pigsplus:weaken_magnetic_field", + "requirements": [ + { + "requirement": "anvilcraft_pigsplus:planetary_reformer" + }, + { + "min": 1, + "requirement": "anvilcraft_pigsplus:magnetic_field" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer_component.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer_component.json new file mode 100644 index 00000000..557b91b0 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/celestial_reformer_component.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "K": { + "item": "anvilcraft_pigsplus:karakuri_component" + }, + "T": { + "item": "anvilcraft:transcendium_ingot" + } + }, + "pattern": [ + "TKT", + "K K", + "TKT" + ], + "result": { + "count": 4, + "id": "anvilcraft_pigsplus:celestial_reformer_component" + } +} \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/AnvilCraftPigsPlus.java b/src/main/java/dev/anvilcraft/pigsplus/AnvilCraftPigsPlus.java index f1a6c899..69ad5757 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/AnvilCraftPigsPlus.java +++ b/src/main/java/dev/anvilcraft/pigsplus/AnvilCraftPigsPlus.java @@ -9,12 +9,14 @@ import dev.anvilcraft.pigsplus.event.CapabilitiesEventListener; import dev.anvilcraft.pigsplus.init.AddonBlockEntities; import dev.anvilcraft.pigsplus.init.AddonBlocks; +import dev.anvilcraft.pigsplus.init.PigsReformerRequirements; import dev.anvilcraft.pigsplus.init.AddonFluids; import dev.anvilcraft.pigsplus.init.AddonInteractionMaps; import dev.anvilcraft.pigsplus.init.AddonItemGroups; import dev.anvilcraft.pigsplus.init.AddonItems; import dev.anvilcraft.pigsplus.init.AddonMenuTypes; import dev.anvilcraft.pigsplus.init.AddonParticleTypes; +import dev.anvilcraft.pigsplus.init.PigsReformerModifications; import dev.anvilcraft.pigsplus.init.AddonRecipeTypes; import dev.anvilcraft.pigsplus.init.enchantment.AddonEnchantmentLevelBasedValueTypes; import net.minecraft.resources.ResourceLocation; @@ -43,6 +45,8 @@ public AnvilCraftPigsPlus(IEventBus modEventBus, ModContainer modContainer) { AddonBlockEntities.register(); modEventBus.addListener(CapabilitiesEventListener::registerCapabilities); AddonRecipeTypes.register(modEventBus); + PigsReformerRequirements.register(modEventBus); + PigsReformerModifications.register(modEventBus); AddonEnchantmentLevelBasedValueTypes.register(modEventBus); ModDatagen.init(); modEventBus.addListener(AnvilCraftPigsPlus::commonSetup); diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddAtmosphereModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddAtmosphereModification.java new file mode 100644 index 00000000..7c359d8b --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddAtmosphereModification.java @@ -0,0 +1,42 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 为岩石行星添加大气层。 + */ +public class AddAtmosphereModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.add_atmosphere"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("atmosphere"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (!(body instanceof RockyPlanetData rp) || rp.hasAtmosphere()) return; + be.setCelestialBodyData(new RockyPlanetData( + rp.bodyClass(), + true, + rp.liquidCoverage(), + rp.temperature(), + rp.ringType(), + rp.size(), + rp.paletteBaseRow(), + rp.paletteOverlayRow(), + rp.axialTilt(), + rp.rotationSpeed(), + rp.magneticFieldStrength() + )); + be.setChanged(); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddBiologicalResourcesModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddBiologicalResourcesModification.java new file mode 100644 index 00000000..5d6dc6ff --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddBiologicalResourcesModification.java @@ -0,0 +1,26 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 按本体生物资源生成逻辑为行星添加生物资源。 + */ +public class AddBiologicalResourcesModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.add_biological_resources"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("biologic"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialReformerPlanetUtil.addBiologicalResources(be); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddCivilizationModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddCivilizationModification.java new file mode 100644 index 00000000..de22f852 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/AddCivilizationModification.java @@ -0,0 +1,26 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 为行星添加低等文明,并停止生物资源产出。 + */ +public class AddCivilizationModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.add_civilization"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("civilization"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialReformerPlanetUtil.addCivilization(be); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseLiquidCoverageModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseLiquidCoverageModification.java new file mode 100644 index 00000000..fabdd085 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseLiquidCoverageModification.java @@ -0,0 +1,60 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyClass; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 降低一级流体覆盖率,并重新生成行星资源。 + */ +public class DecreaseLiquidCoverageModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.decrease_liquid_coverage"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("sea"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (!(body instanceof RockyPlanetData rp)) return; + + LiquidCoverage next = switch (rp.liquidCoverage()) { + case HIGH -> LiquidCoverage.MEDIUM; + case MEDIUM -> LiquidCoverage.LOW; + case LOW -> LiquidCoverage.NONE; + case NONE -> null; + }; + if (next == null) return; + + CelestialBodyClass nextClass = switch (next) { + case NONE -> CelestialBodyClass.ROCKY_NO_LIQUID; + case LOW -> CelestialBodyClass.ROCKY_LOW_LIQUID; + case MEDIUM -> CelestialBodyClass.ROCKY_MED_LIQUID; + default -> rp.bodyClass(); + }; + RockyPlanetData updated = new RockyPlanetData( + nextClass, + rp.hasAtmosphere(), + next, + rp.temperature(), + rp.ringType(), + rp.size(), + rp.paletteBaseRow(), + rp.paletteOverlayRow(), + rp.axialTilt(), + rp.rotationSpeed(), + rp.magneticFieldStrength() + ); + CelestialReformerPlanetUtil.regenerate(be, updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseTemperatureModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseTemperatureModification.java new file mode 100644 index 00000000..8b05211f --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/DecreaseTemperatureModification.java @@ -0,0 +1,51 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.Temperature; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 降低一级行星温度。 + */ +public class DecreaseTemperatureModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.decrease_temperature"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("temperature"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (!(body instanceof RockyPlanetData rp)) return; + Temperature next = switch (rp.temperature()) { + case FREEZING -> Temperature.FREEZING; + case COLD -> Temperature.FREEZING; + case MILD -> Temperature.COLD; + case HOT -> Temperature.MILD; + case SCORCHED -> Temperature.HOT; + }; + if (next == rp.temperature()) return; + be.setCelestialBodyData(new RockyPlanetData( + rp.bodyClass(), + rp.hasAtmosphere(), + rp.liquidCoverage(), + next, + rp.ringType(), + rp.size(), + rp.paletteBaseRow(), + rp.paletteOverlayRow(), + rp.axialTilt(), + rp.rotationSpeed(), + rp.magneticFieldStrength() + )); + be.setChanged(); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/FastRotationModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/FastRotationModification.java new file mode 100644 index 00000000..c0094891 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/FastRotationModification.java @@ -0,0 +1,56 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.GiantPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.StarData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +public class FastRotationModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.fast_rotation"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("rotation_speed"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body == null) return; + int newRotation = Mth.clamp(body.rotationSpeed() + 1, MIN_LEVEL, MAX_LEVEL); + CelestialBodyData updated = switch (body) { + case RockyPlanetData rp -> new RockyPlanetData( + rp.bodyClass(), rp.hasAtmosphere(), rp.liquidCoverage(), rp.temperature(), + rp.ringType(), rp.size(), rp.paletteBaseRow(), rp.paletteOverlayRow(), + rp.axialTilt(), newRotation, rp.magneticFieldStrength() + ); + case GiantPlanetData gp -> new GiantPlanetData( + gp.bodyClass(), gp.pressureType(), gp.windSpeed(), gp.ringType(), + gp.size(), gp.paletteBaseRow(), gp.paletteOverlayRow(), + gp.axialTilt(), newRotation, gp.magneticFieldStrength(), gp.brownDwarf() + ); + case SpecialCelestialBodyData sp -> new SpecialCelestialBodyData( + sp.recipeId(), sp.name(), sp.size(), sp.axialTilt(), + newRotation, sp.magneticFieldStrength(), + sp.temperature(), sp.hasAtmosphere(), sp.liquidCoverage(), + sp.isErrorPlanet(), sp.needsCustomModel(), sp.model(), sp.playerHeadProfile() + ); + case StarData star -> new StarData( + star.bodyClass(), star.size(), star.colorR(), star.colorG(), star.colorB(), + star.axialTilt(), newRotation, star.magneticFieldStrength(), + star.energy(), star.bodyUuid() + ); + default -> null; + }; + if (updated == null) return; + be.setCelestialBodyData(updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseLiquidCoverageModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseLiquidCoverageModification.java new file mode 100644 index 00000000..a359b8bf --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseLiquidCoverageModification.java @@ -0,0 +1,60 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyClass; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 提升一级液体覆盖度,并重新生成行星资源。 + */ +public class IncreaseLiquidCoverageModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.increase_liquid_coverage"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("sea"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (!(body instanceof RockyPlanetData rp)) return; + + LiquidCoverage next = switch (rp.liquidCoverage()) { + case NONE -> LiquidCoverage.LOW; + case LOW -> LiquidCoverage.MEDIUM; + case MEDIUM -> LiquidCoverage.HIGH; + case HIGH -> null; + }; + if (next == null) return; + + CelestialBodyClass nextClass = switch (next) { + case LOW -> CelestialBodyClass.ROCKY_LOW_LIQUID; + case MEDIUM -> CelestialBodyClass.ROCKY_MED_LIQUID; + case HIGH -> CelestialBodyClass.ROCKY_HIGH_LIQUID; + default -> rp.bodyClass(); + }; + RockyPlanetData updated = new RockyPlanetData( + nextClass, + rp.hasAtmosphere(), + next, + rp.temperature(), + rp.ringType(), + rp.size(), + rp.paletteBaseRow(), + rp.paletteOverlayRow(), + rp.axialTilt(), + rp.rotationSpeed(), + rp.magneticFieldStrength() + ); + CelestialReformerPlanetUtil.regenerate(be, updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseTemperatureModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseTemperatureModification.java new file mode 100644 index 00000000..e36fc516 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/IncreaseTemperatureModification.java @@ -0,0 +1,51 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.Temperature; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 提升一级行星温度。 + */ +public class IncreaseTemperatureModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.increase_temperature"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("temperature"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (!(body instanceof RockyPlanetData rp)) return; + Temperature next = switch (rp.temperature()) { + case FREEZING -> Temperature.COLD; + case COLD -> Temperature.MILD; + case MILD -> Temperature.HOT; + case HOT -> Temperature.SCORCHED; + case SCORCHED -> Temperature.SCORCHED; + }; + if (next == rp.temperature()) return; + be.setCelestialBodyData(new RockyPlanetData( + rp.bodyClass(), + rp.hasAtmosphere(), + rp.liquidCoverage(), + next, + rp.ringType(), + rp.size(), + rp.paletteBaseRow(), + rp.paletteOverlayRow(), + rp.axialTilt(), + rp.rotationSpeed(), + rp.magneticFieldStrength() + )); + be.setChanged(); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModification.java new file mode 100644 index 00000000..42769e6a --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModification.java @@ -0,0 +1,37 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +public abstract class ReformerModification { + public static final int MIN_LEVEL = 0; + public static final int MAX_LEVEL = 5; + + public abstract void apply(CelestialForgingAnvilBlockEntity be); + + /** + * 获取用于展示的描述组件,格式化方式由子类自行决定。 + */ + public abstract Component getDescription(); + + /** + * 获取用于 JEI/Jade/Ageratum 显示的图标。 + */ + public abstract ResourceLocation getIcon(); + + /** + * 根据图标文件名生成完整资源路径。 + */ + protected final ResourceLocation icon(String name) { + return AnvilCraftPigsPlus.of("textures/gui/reformer/" + name + ".png"); + } + + /** + * 生成翻译文本。 + */ + protected final Component text(String key, Object... args) { + return Component.translatable(key, args); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModifications.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModifications.java new file mode 100644 index 00000000..0766c9f4 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/ReformerModifications.java @@ -0,0 +1,27 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.NewRegistryEvent; +import net.neoforged.neoforge.registries.RegistryBuilder; + +@EventBusSubscriber(modid = AnvilCraftPigsPlus.MOD_ID) +public final class ReformerModifications { + public static final ResourceKey> KEY = + ResourceKey.createRegistryKey(AnvilCraftPigsPlus.of("celestial_reformer_modification")); + public static final Registry REGISTRY = new RegistryBuilder<>(KEY) + .sync(true) + .maxId(512) + .create(); + + private ReformerModifications() { + } + + @SubscribeEvent + public static void register(NewRegistryEvent event) { + event.register(REGISTRY); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/SlowRotationModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/SlowRotationModification.java new file mode 100644 index 00000000..6faa3d11 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/SlowRotationModification.java @@ -0,0 +1,56 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.GiantPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.StarData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +public class SlowRotationModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.slow_rotation"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("rotation_speed"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body == null) return; + int newRotation = Mth.clamp(body.rotationSpeed() - 1, MIN_LEVEL, MAX_LEVEL); + CelestialBodyData updated = switch (body) { + case RockyPlanetData rp -> new RockyPlanetData( + rp.bodyClass(), rp.hasAtmosphere(), rp.liquidCoverage(), rp.temperature(), + rp.ringType(), rp.size(), rp.paletteBaseRow(), rp.paletteOverlayRow(), + rp.axialTilt(), newRotation, rp.magneticFieldStrength() + ); + case GiantPlanetData gp -> new GiantPlanetData( + gp.bodyClass(), gp.pressureType(), gp.windSpeed(), gp.ringType(), + gp.size(), gp.paletteBaseRow(), gp.paletteOverlayRow(), + gp.axialTilt(), newRotation, gp.magneticFieldStrength(), gp.brownDwarf() + ); + case SpecialCelestialBodyData sp -> new SpecialCelestialBodyData( + sp.recipeId(), sp.name(), sp.size(), sp.axialTilt(), + newRotation, sp.magneticFieldStrength(), + sp.temperature(), sp.hasAtmosphere(), sp.liquidCoverage(), + sp.isErrorPlanet(), sp.needsCustomModel(), sp.model(), sp.playerHeadProfile() + ); + case StarData star -> new StarData( + star.bodyClass(), star.size(), star.colorR(), star.colorG(), star.colorB(), + star.axialTilt(), newRotation, star.magneticFieldStrength(), + star.energy(), star.bodyUuid() + ); + default -> null; + }; + if (updated == null) return; + be.setCelestialBodyData(updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/StrengthenMagneticFieldModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/StrengthenMagneticFieldModification.java new file mode 100644 index 00000000..fea4798d --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/StrengthenMagneticFieldModification.java @@ -0,0 +1,56 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.GiantPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.StarData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +public class StrengthenMagneticFieldModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.strengthen_magnetic_field"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("magnetic_field"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body == null) return; + int newMagnetic = Mth.clamp(body.magneticFieldStrength() + 1, MIN_LEVEL, MAX_LEVEL); + CelestialBodyData updated = switch (body) { + case RockyPlanetData rp -> new RockyPlanetData( + rp.bodyClass(), rp.hasAtmosphere(), rp.liquidCoverage(), rp.temperature(), + rp.ringType(), rp.size(), rp.paletteBaseRow(), rp.paletteOverlayRow(), + rp.axialTilt(), rp.rotationSpeed(), newMagnetic + ); + case GiantPlanetData gp -> new GiantPlanetData( + gp.bodyClass(), gp.pressureType(), gp.windSpeed(), gp.ringType(), + gp.size(), gp.paletteBaseRow(), gp.paletteOverlayRow(), + gp.axialTilt(), gp.rotationSpeed(), newMagnetic, gp.brownDwarf() + ); + case SpecialCelestialBodyData sp -> new SpecialCelestialBodyData( + sp.recipeId(), sp.name(), sp.size(), sp.axialTilt(), + sp.rotationSpeed(), newMagnetic, + sp.temperature(), sp.hasAtmosphere(), sp.liquidCoverage(), + sp.isErrorPlanet(), sp.needsCustomModel(), sp.model(), sp.playerHeadProfile() + ); + case StarData star -> new StarData( + star.bodyClass(), star.size(), star.colorR(), star.colorG(), star.colorB(), + star.axialTilt(), star.rotationSpeed(), newMagnetic, + star.energy(), star.bodyUuid() + ); + default -> null; + }; + if (updated == null) return; + be.setCelestialBodyData(updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/VoidWastelandModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/VoidWastelandModification.java new file mode 100644 index 00000000..64dfe6fd --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/VoidWastelandModification.java @@ -0,0 +1,26 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 将行星转换为虚空废土世界。 + */ +public class VoidWastelandModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.void_wasteland"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("plante_type"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialReformerPlanetUtil.setWasteland(be, true); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/WastelandModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/WastelandModification.java new file mode 100644 index 00000000..6acc516a --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/WastelandModification.java @@ -0,0 +1,26 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.anvilcraft.pigsplus.util.CelestialReformerPlanetUtil; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +/** + * 将行星转换为废土世界。 + */ +public class WastelandModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.wasteland"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("plante_type"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialReformerPlanetUtil.setWasteland(be, false); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/modification/WeakenMagneticFieldModification.java b/src/main/java/dev/anvilcraft/pigsplus/api/modification/WeakenMagneticFieldModification.java new file mode 100644 index 00000000..b221e883 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/modification/WeakenMagneticFieldModification.java @@ -0,0 +1,56 @@ +package dev.anvilcraft.pigsplus.api.modification; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.GiantPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.StarData; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; + +public class WeakenMagneticFieldModification extends ReformerModification { + @Override + public Component getDescription() { + return this.text("modification.anvilcraft_pigsplus.weaken_magnetic_field"); + } + + @Override + public ResourceLocation getIcon() { + return this.icon("magnetic_field"); + } + + @Override + public void apply(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body == null) return; + int newMagnetic = Mth.clamp(body.magneticFieldStrength() - 1, MIN_LEVEL, MAX_LEVEL); + CelestialBodyData updated = switch (body) { + case RockyPlanetData rp -> new RockyPlanetData( + rp.bodyClass(), rp.hasAtmosphere(), rp.liquidCoverage(), rp.temperature(), + rp.ringType(), rp.size(), rp.paletteBaseRow(), rp.paletteOverlayRow(), + rp.axialTilt(), rp.rotationSpeed(), newMagnetic + ); + case GiantPlanetData gp -> new GiantPlanetData( + gp.bodyClass(), gp.pressureType(), gp.windSpeed(), gp.ringType(), + gp.size(), gp.paletteBaseRow(), gp.paletteOverlayRow(), + gp.axialTilt(), gp.rotationSpeed(), newMagnetic, gp.brownDwarf() + ); + case SpecialCelestialBodyData sp -> new SpecialCelestialBodyData( + sp.recipeId(), sp.name(), sp.size(), sp.axialTilt(), + sp.rotationSpeed(), newMagnetic, + sp.temperature(), sp.hasAtmosphere(), sp.liquidCoverage(), + sp.isErrorPlanet(), sp.needsCustomModel(), sp.model(), sp.playerHeadProfile() + ); + case StarData star -> new StarData( + star.bodyClass(), star.size(), star.colorR(), star.colorG(), star.colorB(), + star.axialTilt(), star.rotationSpeed(), newMagnetic, + star.energy(), star.bodyUuid() + ); + default -> null; + }; + if (updated == null) return; + be.setCelestialBodyData(updated); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/CelestialReformerRequirements.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/CelestialReformerRequirements.java new file mode 100644 index 00000000..6620c32f --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/CelestialReformerRequirements.java @@ -0,0 +1,27 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.registries.NewRegistryEvent; +import net.neoforged.neoforge.registries.RegistryBuilder; + +@EventBusSubscriber(modid = AnvilCraftPigsPlus.MOD_ID) +public final class CelestialReformerRequirements { + public static final ResourceKey> KEY = + ResourceKey.createRegistryKey(AnvilCraftPigsPlus.of("celestial_reformer_requirement")); + public static final Registry REGISTRY = new RegistryBuilder<>(KEY) + .sync(true) + .maxId(512) + .create(); + + private CelestialReformerRequirements() { + } + + @SubscribeEvent + public static void register(NewRegistryEvent event) { + event.register(REGISTRY); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasAtmosphereRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasAtmosphereRequirement.java new file mode 100644 index 00000000..4d051ee7 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasAtmosphereRequirement.java @@ -0,0 +1,28 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import net.minecraft.network.chat.Component; + +public class HasAtmosphereRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.has_atmosphere"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body instanceof RockyPlanetData rp) return rp.hasAtmosphere(); + if (body instanceof SpecialCelestialBodyData sp) return sp.hasAtmosphere(); + return false; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasBiologicalResourcesRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasBiologicalResourcesRequirement.java new file mode 100644 index 00000000..59ebbd80 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasBiologicalResourcesRequirement.java @@ -0,0 +1,27 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +/** + * 要求行星资源集中已生成生物资源。 + */ +public class HasBiologicalResourcesRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.has_biological_resources"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + var resources = be.getPlanetaryResourceSet(); + return resources != null + && (!resources.getBiologicalItems().isEmpty() || !resources.getBiologicalFluids().isEmpty()); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasCivilizationRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasCivilizationRequirement.java new file mode 100644 index 00000000..68b27d15 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasCivilizationRequirement.java @@ -0,0 +1,25 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +/** + * 要求行星资源集已生成文明。 + */ +public class HasCivilizationRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.has_civilization"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getPlanetaryResourceSet() != null && be.getPlanetaryResourceSet().hasCivilization(); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasLiquidRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasLiquidRequirement.java new file mode 100644 index 00000000..8a9b42c9 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasLiquidRequirement.java @@ -0,0 +1,31 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import net.minecraft.network.chat.Component; + +public class HasLiquidRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.has_liquid"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body instanceof RockyPlanetData rp) return rp.liquidCoverage() != LiquidCoverage.NONE; + if (body instanceof SpecialCelestialBodyData sp) { + return sp.liquidCoverage() != null && sp.liquidCoverage() != LiquidCoverage.NONE; + } + return false; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasOtherMegastructureRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasOtherMegastructureRequirement.java new file mode 100644 index 00000000..32a56b66 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/HasOtherMegastructureRequirement.java @@ -0,0 +1,22 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class HasOtherMegastructureRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.has_other_megastructure"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getActiveMegastructureIndex() >= 0; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/LiquidCoverageRangeRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/LiquidCoverageRangeRequirement.java new file mode 100644 index 00000000..82c34454 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/LiquidCoverageRangeRequirement.java @@ -0,0 +1,81 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +/** + * 液体覆盖度区间需求,边界为可选的 {@link LiquidCoverage}。 + */ +public class LiquidCoverageRangeRequirement extends ReformerRequirement { + public static final MapCodec CODEC = + RecordCodecBuilder.mapCodec(instance -> instance.group( + coverageCodec().optionalFieldOf("min").forGetter(req -> Optional.ofNullable(req.min)), + coverageCodec().optionalFieldOf("max").forGetter(req -> Optional.ofNullable(req.max)) + ).apply(instance, (min, max) -> new LiquidCoverageRangeRequirement(min.orElse(null), max.orElse(null)))); + + private final @Nullable LiquidCoverage min; + private final @Nullable LiquidCoverage max; + + public LiquidCoverageRangeRequirement() { + this(null, null); + } + + public LiquidCoverageRangeRequirement(@Nullable LiquidCoverage min, @Nullable LiquidCoverage max) { + this.min = min; + this.max = max; + } + + private static Codec coverageCodec() { + return Codec.STRING.xmap(LiquidCoverage::fromName, LiquidCoverage::getSerializedName); + } + + @Override + public MapCodec codec() { + return CODEC; + } + + @Override + public Component getDescription() { + if (this.min != null && this.max != null) { + return this.text( + "requirement.anvilcraft_pigsplus.liquid_coverage_between", + this.min.getSerializedName(), + this.max.getSerializedName() + ); + } + if (this.min != null) { + return this.text("requirement.anvilcraft_pigsplus.liquid_coverage_at_least", this.min.getSerializedName()); + } + if (this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.liquid_coverage_at_most", this.max.getSerializedName()); + } + return this.text("requirement.anvilcraft_pigsplus.unknown"); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + LiquidCoverage coverage; + if (body instanceof RockyPlanetData rp) { + coverage = rp.liquidCoverage(); + } else if (body instanceof SpecialCelestialBodyData sp) { + coverage = sp.liquidCoverage() == null ? LiquidCoverage.NONE : sp.liquidCoverage(); + } else { + return false; + } + int value = coverage.ordinal(); + int min = this.min == null ? 0 : this.min.ordinal(); + int max = this.max == null ? LiquidCoverage.values().length - 1 : this.max.ordinal(); + return value >= min && value <= max; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/MagneticFieldRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/MagneticFieldRequirement.java new file mode 100644 index 00000000..ad0372c1 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/MagneticFieldRequirement.java @@ -0,0 +1,67 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +/** + * 磁场等级需求,支持可选的上下限;未填写的边界表示不限制。 + */ +public class MagneticFieldRequirement extends ReformerRequirement { + public static final MapCodec CODEC = + RecordCodecBuilder.mapCodec(instance -> instance.group( + Codec.INT.optionalFieldOf("min").forGetter(requirement -> Optional.ofNullable(requirement.min)), + Codec.INT.optionalFieldOf("max").forGetter(requirement -> Optional.ofNullable(requirement.max)) + ).apply(instance, (min, max) -> new MagneticFieldRequirement(min.orElse(null), max.orElse(null)))); + + private final @Nullable Integer min; + private final @Nullable Integer max; + + public MagneticFieldRequirement() { + this(null, null); + } + + public MagneticFieldRequirement(@Nullable Integer min, @Nullable Integer max) { + this.min = min; + this.max = max; + } + + public @Nullable Integer min() { + return this.min; + } + + public @Nullable Integer max() { + return this.max; + } + + @Override + public MapCodec codec() { + return CODEC; + } + + @Override + public Component getDescription() { + if (this.min != null && this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.magnetic_field_between", this.min, this.max); + } + if (this.min != null) { + return this.text("requirement.anvilcraft_pigsplus.magnetic_field_at_least", this.min); + } + if (this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.magnetic_field_at_most", this.max); + } + return this.text("requirement.anvilcraft_pigsplus.unknown"); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + if (be.getCelestialBodyData() == null) return false; + int value = be.getCelestialBodyData().magneticFieldStrength(); + return (this.min == null || value >= this.min) && (this.max == null || value <= this.max); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoAtmosphereRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoAtmosphereRequirement.java new file mode 100644 index 00000000..340a5133 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoAtmosphereRequirement.java @@ -0,0 +1,22 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class NoAtmosphereRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.no_atmosphere"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return !new HasAtmosphereRequirement().test(be); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoLiquidRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoLiquidRequirement.java new file mode 100644 index 00000000..ccf52c7c --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoLiquidRequirement.java @@ -0,0 +1,22 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class NoLiquidRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.no_liquid"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return !new HasLiquidRequirement().test(be); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoOtherMegastructureRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoOtherMegastructureRequirement.java new file mode 100644 index 00000000..3ab8fd3e --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/NoOtherMegastructureRequirement.java @@ -0,0 +1,22 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class NoOtherMegastructureRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.no_other_megastructure"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getActiveMegastructureIndex() < 0; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/PlanetaryReformerRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/PlanetaryReformerRequirement.java new file mode 100644 index 00000000..bc84e0e3 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/PlanetaryReformerRequirement.java @@ -0,0 +1,24 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.anvilcraft.pigsplus.block.entity.megastructure.PlanetaryReformerHandler; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class PlanetaryReformerRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.planetary_reformer"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getActiveMegastructureOption() != null + && PlanetaryReformerHandler.NAME.equals(be.getActiveMegastructureOption().megastructure()); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/ReformerRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/ReformerRequirement.java new file mode 100644 index 00000000..6c71c2a6 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/ReformerRequirement.java @@ -0,0 +1,33 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import net.minecraft.ChatFormatting; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public abstract class ReformerRequirement { + /** + * 校验需求是否成立。 + */ + public abstract boolean test(CelestialForgingAnvilBlockEntity be); + + /** + * 获取用于展示的描述组件,格式化方式由子类自行决定。 + */ + public abstract Component getDescription(); + + /** + * 返回该需求类型的编解码器。 + * + *

无参数类型返回 {@link MapCodec#unit(Object)};带参数的类型返回可重建实例的 + * {@code MapCodec},参数由配方 data.json 中的字段提供。

+ */ + public abstract MapCodec codec(); + + /** + * 生成默认红色样式的翻译文本。 + */ + protected final Component text(String key, Object... args) { + return Component.translatable(key, args).withStyle(ChatFormatting.RED); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RequirementEntry.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RequirementEntry.java new file mode 100644 index 00000000..da9e2390 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RequirementEntry.java @@ -0,0 +1,91 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.datafixers.util.Either; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; + +import java.util.function.Function; + +/** + * 配方中的一条需求:由需求 id 和反序列化出的需求实例组成。 + * + *

data.json 中既支持纯字符串 id(无参数需求),也支持对象形式 + * {@code {"requirement": "id", ...参数}};参数由对应需求的 {@link ReformerRequirement#codec()} 解码。

+ */ +public record RequirementEntry(ResourceLocation id, ReformerRequirement requirement) { + private static final Codec STRING_CODEC = ResourceLocation.CODEC.flatXmap( + RequirementEntry::fromId, + entry -> DataResult.success(entry.id()) + ); + + private static final Codec OBJECT_CODEC = Codec.STRING.dispatch( + "requirement", + (Function) entry -> entry.id().toString(), + (Function>) id -> RequirementEntry.codecFor(id) + ); + + public static final Codec CODEC = Codec.either(STRING_CODEC, OBJECT_CODEC) + .xmap(either -> either.map(Function.identity(), Function.identity()), RequirementEntry::toEither) + .validate(RequirementEntry::validate); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + ResourceLocation.STREAM_CODEC, + RequirementEntry::id, + ByteBufCodecs.COMPOUND_TAG, + RequirementEntry::writeTag, + RequirementEntry::readTag + ); + + private static DataResult fromId(ResourceLocation id) { + ReformerRequirement prototype = CelestialReformerRequirements.REGISTRY.get(id); + if (prototype == null) { + return DataResult.error(() -> "Unknown reformer requirement: " + id); + } + return DataResult.success(new RequirementEntry(id, prototype)); + } + + @SuppressWarnings("unchecked") + private static MapCodec codecFor(String id) { + ResourceLocation location = ResourceLocation.tryParse(id); + ReformerRequirement prototype = location == null + ? null + : CelestialReformerRequirements.REGISTRY.get(location); + if (prototype == null) { + return MapCodec.unit(() -> new RequirementEntry(location, null)); + } + MapCodec dataCodec = (MapCodec) prototype.codec(); + return dataCodec.xmap( + requirement -> new RequirementEntry(location, requirement), + RequirementEntry::requirement + ); + } + + private static Either toEither(RequirementEntry entry) { + return Either.right(entry); + } + + private static DataResult validate(RequirementEntry entry) { + return entry.requirement() == null + ? DataResult.error(() -> "Unknown reformer requirement: " + entry.id()) + : DataResult.success(entry); + } + + private static CompoundTag writeTag(RequirementEntry entry) { + return CODEC.encodeStart(NbtOps.INSTANCE, entry).result() + .map(tag -> tag instanceof CompoundTag compound ? compound : new CompoundTag()) + .orElseGet(CompoundTag::new); + } + + private static RequirementEntry readTag(ResourceLocation id, CompoundTag tag) { + RequirementEntry entry = CODEC.parse(NbtOps.INSTANCE, tag).result().orElse(null); + return entry == null ? new RequirementEntry(id, null) : entry; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RockyPlanetRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RockyPlanetRequirement.java new file mode 100644 index 00000000..d0f19039 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RockyPlanetRequirement.java @@ -0,0 +1,26 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import net.minecraft.network.chat.Component; + +/** + * 要求当前天体是普通岩石行星。 + */ +public class RockyPlanetRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.rocky_planet"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getCelestialBodyData() instanceof RockyPlanetData; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RotationSpeedRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RotationSpeedRequirement.java new file mode 100644 index 00000000..79bd2fd2 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/RotationSpeedRequirement.java @@ -0,0 +1,67 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +/** + * 转速等级需求,支持可选的上下限;未填写的边界表示不限制。 + */ +public class RotationSpeedRequirement extends ReformerRequirement { + public static final MapCodec CODEC = + RecordCodecBuilder.mapCodec(instance -> instance.group( + Codec.INT.optionalFieldOf("min").forGetter(requirement -> Optional.ofNullable(requirement.min)), + Codec.INT.optionalFieldOf("max").forGetter(requirement -> Optional.ofNullable(requirement.max)) + ).apply(instance, (min, max) -> new RotationSpeedRequirement(min.orElse(null), max.orElse(null)))); + + private final @Nullable Integer min; + private final @Nullable Integer max; + + public RotationSpeedRequirement() { + this(null, null); + } + + public RotationSpeedRequirement(@Nullable Integer min, @Nullable Integer max) { + this.min = min; + this.max = max; + } + + public @Nullable Integer min() { + return this.min; + } + + public @Nullable Integer max() { + return this.max; + } + + @Override + public MapCodec codec() { + return CODEC; + } + + @Override + public Component getDescription() { + if (this.min != null && this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.rotation_speed_between", this.min, this.max); + } + if (this.min != null) { + return this.text("requirement.anvilcraft_pigsplus.rotation_speed_at_least", this.min); + } + if (this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.rotation_speed_at_most", this.max); + } + return this.text("requirement.anvilcraft_pigsplus.unknown"); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + if (be.getCelestialBodyData() == null) return false; + int value = be.getCelestialBodyData().rotationSpeed(); + return (this.min == null || value >= this.min) && (this.max == null || value <= this.max); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/StarReformerRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/StarReformerRequirement.java new file mode 100644 index 00000000..a226c830 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/StarReformerRequirement.java @@ -0,0 +1,24 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.anvilcraft.pigsplus.block.entity.megastructure.StarReformerHandler; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import net.minecraft.network.chat.Component; + +public class StarReformerRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.star_reformer"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + return be.getActiveMegastructureOption() != null + && StarReformerHandler.NAME.equals(be.getActiveMegastructureOption().megastructure()); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/TemperatureRangeRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/TemperatureRangeRequirement.java new file mode 100644 index 00000000..6497feb7 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/TemperatureRangeRequirement.java @@ -0,0 +1,81 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.Temperature; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +/** + * 温度区间需求,边界为可选的 {@link Temperature}。 + */ +public class TemperatureRangeRequirement extends ReformerRequirement { + public static final MapCodec CODEC = + RecordCodecBuilder.mapCodec(instance -> instance.group( + temperatureCodec().optionalFieldOf("min").forGetter(req -> Optional.ofNullable(req.min)), + temperatureCodec().optionalFieldOf("max").forGetter(req -> Optional.ofNullable(req.max)) + ).apply(instance, (min, max) -> new TemperatureRangeRequirement(min.orElse(null), max.orElse(null)))); + + private final @Nullable Temperature min; + private final @Nullable Temperature max; + + public TemperatureRangeRequirement() { + this(null, null); + } + + public TemperatureRangeRequirement(@Nullable Temperature min, @Nullable Temperature max) { + this.min = min; + this.max = max; + } + + private static Codec temperatureCodec() { + return Codec.STRING.xmap(Temperature::fromName, Temperature::getSerializedName); + } + + @Override + public MapCodec codec() { + return CODEC; + } + + @Override + public Component getDescription() { + if (this.min != null && this.max != null) { + return this.text( + "requirement.anvilcraft_pigsplus.temperature_between", + this.min.getSerializedName(), + this.max.getSerializedName() + ); + } + if (this.min != null) { + return this.text("requirement.anvilcraft_pigsplus.temperature_at_least", this.min.getSerializedName()); + } + if (this.max != null) { + return this.text("requirement.anvilcraft_pigsplus.temperature_at_most", this.max.getSerializedName()); + } + return this.text("requirement.anvilcraft_pigsplus.unknown"); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + Temperature temperature; + if (body instanceof RockyPlanetData rp) { + temperature = rp.temperature(); + } else if (body instanceof SpecialCelestialBodyData sp) { + temperature = sp.temperature(); + } else { + return false; + } + int value = temperature.ordinal(); + int min = this.min == null ? 0 : this.min.ordinal(); + int max = this.max == null ? Temperature.values().length - 1 : this.max.ordinal(); + return value >= min && value <= max; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/api/requirement/WaterOceanRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/WaterOceanRequirement.java new file mode 100644 index 00000000..3995be7e --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/api/requirement/WaterOceanRequirement.java @@ -0,0 +1,35 @@ +package dev.anvilcraft.pigsplus.api.requirement; + +import com.mojang.serialization.MapCodec; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.material.Fluids; + +/** + * 要求无液体覆盖,或当前液体为水且覆盖度未满。 + */ +public class WaterOceanRequirement extends ReformerRequirement { + @Override + public Component getDescription() { + return this.text("requirement.anvilcraft_pigsplus.water_ocean"); + } + + @Override + public MapCodec codec() { + return MapCodec.unit(this); + } + + @Override + public boolean test(CelestialForgingAnvilBlockEntity be) { + if (!(be.getCelestialBodyData() instanceof RockyPlanetData rp)) return false; + if (rp.liquidCoverage() == LiquidCoverage.NONE) return true; + if (rp.liquidCoverage() == LiquidCoverage.HIGH) return false; + if (be.getPlanetaryResourceSet() == null) return false; + var water = BuiltInRegistries.FLUID.getKey(Fluids.WATER); + return be.getPlanetaryResourceSet().getFluids().stream() + .anyMatch(stack -> stack.fluidId().equals(water)); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputChannel.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputChannel.java new file mode 100644 index 00000000..d959bb02 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputChannel.java @@ -0,0 +1,7 @@ +package dev.anvilcraft.pigsplus.block.entity.megastructure; + +public enum CelestialReformerInputChannel { + LOGISTICS_ITEM, + FLUID_INTERFACE, + LASER_INTERFACE +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputRequirement.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputRequirement.java new file mode 100644 index 00000000..6870cbe8 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/CelestialReformerInputRequirement.java @@ -0,0 +1,46 @@ +package dev.anvilcraft.pigsplus.block.entity.megastructure; + +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe.LaserType; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +public record CelestialReformerInputRequirement( + CelestialReformerInputChannel channel, + ResourceLocation resource, + int amount, + @Nullable LaserType laserType +) { + public static CelestialReformerInputRequirement logisticsItem(ResourceLocation item, int amount) { + return new CelestialReformerInputRequirement( + CelestialReformerInputChannel.LOGISTICS_ITEM, item, amount, null + ); + } + + public static CelestialReformerInputRequirement fluid(ResourceLocation fluid, int amount) { + return new CelestialReformerInputRequirement( + CelestialReformerInputChannel.FLUID_INTERFACE, fluid, amount, null + ); + } + + public static CelestialReformerInputRequirement laser(int level) { + return new CelestialReformerInputRequirement( + CelestialReformerInputChannel.LASER_INTERFACE, + ResourceLocation.withDefaultNamespace("laser"), + level, + LaserType.ANY + ); + } + + public static CelestialReformerInputRequirement laser(int level, boolean gamma) { + return laser(level, gamma ? LaserType.GAMMA : LaserType.NORMAL); + } + + public static CelestialReformerInputRequirement laser(int level, LaserType type) { + return new CelestialReformerInputRequirement( + CelestialReformerInputChannel.LASER_INTERFACE, + ResourceLocation.withDefaultNamespace("laser"), + level, + type + ); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/PlanetaryReformerHandler.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/PlanetaryReformerHandler.java new file mode 100644 index 00000000..769fa40d --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/PlanetaryReformerHandler.java @@ -0,0 +1,10 @@ +package dev.anvilcraft.pigsplus.block.entity.megastructure; + +public class PlanetaryReformerHandler extends ReformerHandler { + public static final String NAME = "planetary_reformer"; + + @Override + public String name() { + return NAME; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/ReformerHandler.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/ReformerHandler.java new file mode 100644 index 00000000..8432df2c --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/ReformerHandler.java @@ -0,0 +1,603 @@ +package dev.anvilcraft.pigsplus.block.entity.megastructure; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.requirement.RequirementEntry; +import dev.anvilcraft.pigsplus.init.AddonRecipeTypes; +import dev.anvilcraft.pigsplus.network.CelestialReformerSyncPacket; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe.LaserType; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilFluidInterfaceBlockEntity; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilLaserInterfaceBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialRefactorOption; +import dev.dubhe.anvilcraft.block.entity.megastructure.BaseMegastructureHandler; +import lombok.Getter; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.network.PacketDistributor; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * 行星/恒星改造器的公共处理器。 + * + *

负责从物流/流体/激光接口按配方吸收材料并推进进度,需求全部满足后调用 + * {@link ReformerModification} 修改天体属性;同时把运行状态同步给客户端, + * 供 Jade 等显示模块读取。

+ * + *

子类只需提供各自的 {@link #name()} 与巨构名称常量。

+ */ +public abstract class ReformerHandler extends BaseMegastructureHandler { + private @Nullable ResourceLocation activeRecipeId; + private @Nullable RecipeHolder currentRecipe; + @Getter + private int inputIndex; + @Getter + private int progress; + private int[] requirementProgresses = new int[0]; + private int cooldown; + + /** + * 巨构建造完成时调用,清空所有改造状态并同步客户端。 + */ + @Override + public void onBuild(CelestialForgingAnvilBlockEntity be) { + this.removeRecipe(be); + } + + /** + * 巨构拆除/解除绑定时调用,清空所有改造信息与进度并同步客户端。 + */ + @Override + public void onClear(CelestialForgingAnvilBlockEntity be) { + this.removeRecipe(be); + } + + /** + * 服务端每 tick 驱动改造流程。 + * + *

冷却结束后选择当前配方,一次吸收尽可能连续推进多个需求;全部需求完成后执行 + * 改造,并将进度变化同步给客户端。若配方含激光要求,激光仅作为本轮物品/流体吸取的 + * 前提条件,不再单独推进进度。

+ */ + @Override + public void serverTick(CelestialForgingAnvilBlockEntity be) { + if (be.getLevel() == null || be.getLevel().isClientSide()) return; + + CelestialRefactorOption option = be.getActiveMegastructureOption(); + if (option == null || !this.name().equals(option.megastructure())) return; + + // 工作冷却 + if (this.cooldown > 0) { + this.cooldown--; + return; + } + this.cooldown = AnvilCraftPigsPlus.CONFIG.reformerAbsorptionCooldown; + + // 检查正在执行的配方 + if (this.currentRecipe == null) { + List> recipes = new ArrayList<>( + be.getLevel().getRecipeManager().getAllRecipesFor(AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get()) + ); + RecipeHolder newRecipe = findRecipeById(recipes, this.activeRecipeId); + if (newRecipe != null) this.resetRecipe(be, newRecipe); + } + if (this.currentRecipe == null) { + RecipeHolder newRecipe = this.getServerRecipe(be); + if (newRecipe == null) return; + + this.resetRecipe(be, newRecipe); + } + + CelestialReformerRecipe recipe = this.currentRecipe.value(); + List requirements = this.toRequirements(recipe); + if (requirements.isEmpty()) { + this.applyModification(be, recipe.modification()); + return; + } + + boolean hasValidLaser = this.hasAnyValidLaser(be, recipe); + boolean hasRequirement = false; + // 有激光要求时,激光必须先于物品/流体吸取生效 + if (this.getLaserRequirement(recipe) == null || hasValidLaser) {// 吸收材料 + while (this.inputIndex < requirements.size()) { + CelestialReformerInputRequirement requirement = requirements.get(this.inputIndex); + if (requirement.channel() == CelestialReformerInputChannel.LASER_INTERFACE) { + this.inputIndex++; + continue; + } + int gained = this.tickRequirement(be, requirement); + if (gained <= 0) break; + this.progress += gained; + if (this.inputIndex < this.requirementProgresses.length) { + this.requirementProgresses[this.inputIndex] = this.progress; + } + hasRequirement = true; + if (this.progress >= this.getRequirementTarget(requirement)) { + if (this.inputIndex < this.requirementProgresses.length) { + this.requirementProgresses[this.inputIndex] = this.getRequirementTarget(requirement); + } + this.inputIndex++; + this.progress = 0; + continue; + } + break; + } + } + + // 没有任何材料就尝试刷新配方 + if (!hasRequirement) { + RecipeHolder newRecipe = this.getServerRecipe(be); + if (newRecipe == null) return; + + this.resetRecipe(be, newRecipe); + } + + if (this.inputIndex >= requirements.size()) { + this.applyModification(be, recipe.modification()); + } else if (hasRequirement) { + this.syncState(be); + } + + } + + private void resetRecipe(CelestialForgingAnvilBlockEntity be, RecipeHolder holder) { + this.currentRecipe = holder; + this.activeRecipeId = holder.id(); + this.resetProgress(); + this.requirementProgresses = new int[this.toRequirements(holder.value()).size()]; + this.syncState(be); + } + + private void removeRecipe(CelestialForgingAnvilBlockEntity be) { + this.activeRecipeId = null; + this.currentRecipe = null; + this.cooldown = AnvilCraftPigsPlus.CONFIG.reformerAbsorptionCooldown; + this.resetProgress(); + this.requirementProgresses = new int[0]; + this.syncState(be); + } + + /** + * 重置输入进度,使下一次从第一个需求开始。 + */ + private void resetProgress() { + this.inputIndex = 0; + this.progress = 0; + } + + /** + * 执行改造:调用注册表中的 {@link ReformerModification} 修改天体属性,随后清空进度、 + * 更新完成状态并同步客户端。 + */ + private void applyModification(CelestialForgingAnvilBlockEntity be, ResourceLocation modification) { + ReformerModification modificationEffect = + ReformerModifications.REGISTRY.get(modification); + if (modificationEffect != null) { + modificationEffect.apply(be); + } else { + AnvilCraftPigsPlus.LOGGER.warn("Unsupported planetary reformer modification: {}", modification); + } + this.removeRecipe(be); + this.syncCelestialBody(be); + } + + /** + * 将服务端已修改的天体数据立即推送给附近玩家,避免 GUI 打开后仍显示旧状态。 + */ + private void syncCelestialBody(CelestialForgingAnvilBlockEntity be) { + be.setChanged(); + if (be.getLevel() instanceof ServerLevel serverLevel) { + Packet packet = be.getUpdatePacket(); + for (ServerPlayer player : serverLevel.getChunkSource().chunkMap.getPlayers( + serverLevel.getChunkAt(be.getBlockPos()).getPos(), + false + )) { + player.connection.send(packet); + } + } + } + + /** + * 将当前 handler 状态通过自定义网络包同步给追踪该区块的玩家。 + * + *

只发送给服务端;客户端收到 {@link CelestialReformerSyncPacket} 后直接写入 + * 客户端 handler,保证多块结构上任意部件都能读到最新进度。

+ */ + private void syncState(CelestialForgingAnvilBlockEntity be) { + be.setChanged(); + if (be.getLevel() instanceof ServerLevel serverLevel) { + CompoundTag tag = new CompoundTag(); + this.writeUpdateTag(tag, serverLevel.registryAccess()); + PacketDistributor.sendToPlayersTrackingChunk( + serverLevel, + serverLevel.getChunkAt(be.getBlockPos()).getPos(), + new CelestialReformerSyncPacket(be.getBlockPos(), tag) + ); + } + } + + /** + * 获取当前应执行的配方。 + * + *

客户端只按已同步的 + * {@link #activeRecipeId} 做纯读取,不参与配方选择。

+ * + * @return 当前配方,无可用配方时返回 {@code null} + */ + private @Nullable RecipeHolder getClientRecipe(CelestialForgingAnvilBlockEntity be) { + // 客户端纯读取 + if (this.currentRecipe != null) return this.currentRecipe; + + if (be.getLevel() == null) { + return null; + } + + List> recipes = new ArrayList<>( + be.getLevel().getRecipeManager().getAllRecipesFor(AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get()) + ); + return findRecipeById(recipes, this.activeRecipeId); + } + + /** + * 获取当前应执行的配方。 + * + *

筛选满足条件且输入全部满足的配方

+ * + * @return 当前配方,无可用配方时返回 {@code null} + */ + private @Nullable RecipeHolder getServerRecipe(CelestialForgingAnvilBlockEntity be) { + if (be.getLevel() == null) return null; + + List> recipes = + new ArrayList<>(be.getLevel().getRecipeManager().getAllRecipesFor(AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get())); + recipes.removeIf(holder -> !matchesRequirements(be, holder.value())); + if (recipes.isEmpty()) return null; + + for (RecipeHolder holder : recipes) { + if (this.hasAllRequiredInputs(be, holder.value())) { + return holder; + } + } + return null; + } + + /** + * 校验配方携带的所有需求是否在当前天体上成立。 + * + * @return 任一需求不成立或需求未注册时返回 {@code false} + */ + public static boolean matchesRequirements(CelestialForgingAnvilBlockEntity be, CelestialReformerRecipe recipe) { + for (RequirementEntry entry : recipe.requirements()) { + if (!entry.requirement().test(be)) return false; + } + return true; + } + + /** + * 按配方 id 在候选配方中查找匹配项。 + * + * @param recipeId 配方 id,可为 {@code null} + * @return 匹配的配方,未找到时返回 {@code null} + */ + public static @Nullable RecipeHolder findRecipeById( + List> recipes, + @Nullable ResourceLocation recipeId + ) { + if (recipeId == null) return null; + return recipes.stream() + .filter(holder -> recipeId.equals(holder.id())) + .findFirst() + .orElse(null); + } + + /** + * 把配方中的物品/流体/激光输入展开为统一的输入需求列表。 + */ + private List toRequirements(CelestialReformerRecipe recipe) { + List requirements = new ArrayList<>(); + for (CelestialReformerRecipe.ItemInput input : recipe.items()) { + requirements.add(CelestialReformerInputRequirement.logisticsItem(input.item(), input.count())); + } + for (CelestialReformerRecipe.FluidInput input : recipe.fluids()) { + requirements.add(CelestialReformerInputRequirement.fluid(input.fluid(), input.amount())); + } + for (CelestialReformerRecipe.LaserInput input : recipe.lasers()) { + requirements.add(CelestialReformerInputRequirement.laser(input.level(), input.type())); + } + return requirements; + } + + /** + * 获取单个需求的完成目标。 + */ + private int getRequirementTarget(CelestialReformerInputRequirement requirement) { + return requirement.amount(); + } + + /** + * 检查配方所有输入是否同时在场(只判断类型存在,不要求数量足够)。 + */ + private boolean hasAllRequiredInputs(CelestialForgingAnvilBlockEntity be, CelestialReformerRecipe recipe) { + List requirements = this.toRequirements(recipe); + if (requirements.isEmpty()) return false; + for (CelestialReformerInputRequirement requirement : requirements) { + if (!this.hasRequirementInput(be, requirement)) return false; + } + return true; + } + + /** + * 检查单个输入通道中是否存在指定资源。 + */ + private boolean hasRequirementInput( + CelestialForgingAnvilBlockEntity be, + CelestialReformerInputRequirement requirement + ) { + return switch (requirement.channel()) { + case LOGISTICS_ITEM -> this.hasItemInInterfaces(be, requirement.resource()); + case FLUID_INTERFACE -> this.hasFluidInInterfaces(be, requirement.resource()); + case LASER_INTERFACE -> this.hasValidLaser(be, requirement); + }; + } + + /** + * 检查物流接口中是否存在指定物品。 + */ + private boolean hasItemInInterfaces(CelestialForgingAnvilBlockEntity be, ResourceLocation itemId) { + var item = BuiltInRegistries.ITEM.get(itemId); + if (item == Items.AIR) return true; + List interfaces = this.findLogisticsInterfaces(be); + if (interfaces == null) return false; + for (IItemHandler handler : interfaces) { + for (int slot = 0; slot < handler.getSlots(); slot++) { + if (handler.getStackInSlot(slot).is(item)) return true; + } + } + return false; + } + + /** + * 检查流体接口中是否存在指定流体。 + */ + private boolean hasFluidInInterfaces(CelestialForgingAnvilBlockEntity be, ResourceLocation fluidId) { + Fluid fluid = BuiltInRegistries.FLUID.get(fluidId); + if (fluid.isSame(Fluids.EMPTY)) return true; + for (CelestialForgingAnvilFluidInterfaceBlockEntity fluidInterface : this.findFluidInterfaces(be)) { + IFluidHandler handler = fluidInterface.getInternalFluidHandler(); + for (int tank = 0; tank < handler.getTanks(); tank++) { + FluidStack stack = handler.getFluidInTank(tank); + if (!stack.isEmpty() && stack.getFluid().isSame(fluid)) return true; + } + } + return false; + } + + /** + * 检查是否存在等级与伽马类型均满足要求的激光接口。 + */ + private boolean hasValidLaser( + CelestialForgingAnvilBlockEntity be, + CelestialReformerInputRequirement requirement + ) { + for (CelestialForgingAnvilLaserInterfaceBlockEntity laser : this.findLaserInterfaces(be)) { + LaserType type = requirement.laserType(); + if (laser.getReceivedLaserLevel() >= requirement.amount() + && (type == LaserType.ANY || laser.isReceivedGamma() == (type == LaserType.GAMMA))) { + return true; + } + } + return false; + } + + /** + * 检查配方中是否存在任意一个已满足的激光要求。 + */ + private boolean hasAnyValidLaser(CelestialForgingAnvilBlockEntity be, CelestialReformerRecipe recipe) { + for (CelestialReformerInputRequirement requirement : this.toRequirements(recipe)) { + if (requirement.channel() == CelestialReformerInputChannel.LASER_INTERFACE + && this.hasValidLaser(be, requirement)) { + return true; + } + } + return false; + } + + /** + * 获取配方中的第一个激光要求;无激光要求时返回 {@code null}。 + */ + private @Nullable CelestialReformerInputRequirement getLaserRequirement(CelestialReformerRecipe recipe) { + for (CelestialReformerInputRequirement requirement : this.toRequirements(recipe)) { + if (requirement.channel() == CelestialReformerInputChannel.LASER_INTERFACE) { + return requirement; + } + } + return null; + } + + /** + * 将当前激光需求的等级/伽马要求同步到所有激光接口。 + * + *

配方含激光要求时保持该激光要求,激光作为整轮物品/流体吸取的前提条件。

+ */ + public void syncLaserRequirements(CelestialForgingAnvilBlockEntity be) { + RecipeHolder clientRecipe = this.getClientRecipe(be); + CelestialReformerInputRequirement target = clientRecipe == null + ? null + : this.getLaserRequirement(clientRecipe.value()); + for (CelestialForgingAnvilLaserInterfaceBlockEntity laser : this.findLaserInterfaces(be)) { + if (target == null) { + laser.setLaserRequirement(0, false); + } else { + laser.setLaserRequirement(target.amount(), target.laserType() == LaserType.GAMMA); + } + } + } + + /** + * 推进单个需求:按需求通道消耗物品/流体,或校验激光是否满足要求。 + * + * @return 本次实际推进的数量;无法推进时返回 0 + */ + private int tickRequirement( + CelestialForgingAnvilBlockEntity be, + CelestialReformerInputRequirement requirement + ) { + int remaining = this.getRequirementTarget(requirement) - this.progress; + return switch (requirement.channel()) { + case LOGISTICS_ITEM -> this.consumeItems(be, requirement.resource(), remaining); + case FLUID_INTERFACE -> this.consumeFluid(be, requirement.resource(), remaining); + case LASER_INTERFACE -> 0; + }; + } + + /** + * 从所有物流接口中消耗指定物品,累计不超过 {@code limit}。 + * + * @return 实际消耗数量 + */ + private int consumeItems(CelestialForgingAnvilBlockEntity be, ResourceLocation itemId, int limit) { + if (limit <= 0) return 0; + var item = BuiltInRegistries.ITEM.get(itemId); + if (item == Items.AIR) return 0; + int consumed = 0; + for (IItemHandler handler : this.findLogisticsInterfaces(be)) { + for (int slot = 0; slot < handler.getSlots() && consumed < limit; slot++) { + ItemStack stack = handler.getStackInSlot(slot); + if (stack.isEmpty() || !stack.is(item)) continue; + int amount = Math.min(limit - consumed, stack.getCount()); + consumed += handler.extractItem(slot, amount, false).getCount(); + } + if (consumed >= limit) break; + } + return consumed; + } + + /** + * 从所有流体接口中消耗指定流体,累计不超过 {@code limit}。 + * + * @return 实际消耗数量(mB) + */ + private int consumeFluid(CelestialForgingAnvilBlockEntity be, ResourceLocation fluidId, int limit) { + if (limit <= 0) return 0; + Fluid fluid = BuiltInRegistries.FLUID.get(fluidId); + if (fluid.isSame(Fluids.EMPTY)) return 0; + int consumed = 0; + for (CelestialForgingAnvilFluidInterfaceBlockEntity fluidInterface : this.findFluidInterfaces(be)) { + IFluidHandler handler = fluidInterface.getInternalFluidHandler(); + FluidStack drained = handler.drain( + new FluidStack(fluid, limit - consumed), + IFluidHandler.FluidAction.EXECUTE + ); + consumed += drained.getAmount(); + if (consumed >= limit) break; + } + return consumed; + } + + /** + * 获取当前配方展开后的输入需求列表,供显示模块读取。 + */ + public List getInputRequirements(CelestialForgingAnvilBlockEntity be) { + RecipeHolder clientRecipe = this.getClientRecipe(be); + return clientRecipe == null ? List.of() : this.toRequirements(clientRecipe.value()); + } + + /** + * 获取当前配方每个输入需求各自的收集进度。 + */ + public int[] getRequirementProgresses() { + return this.requirementProgresses.clone(); + } + + /** + * 获取当前配方的改造 id,供显示模块读取。 + */ + public @Nullable ResourceLocation getActiveModification(CelestialForgingAnvilBlockEntity be) { + RecipeHolder clientRecipe = this.getClientRecipe(be); + return clientRecipe == null ? null : clientRecipe.value().modification(); + } + + /** + * 获取当前配方的需求 id 列表,供显示模块读取。 + */ + public List getRequirementIds(CelestialForgingAnvilBlockEntity be) { + RecipeHolder clientRecipe = this.getClientRecipe(be); + return clientRecipe == null ? List.of() : clientRecipe.value().requirements().stream().map(RequirementEntry::id).toList(); + } + + /** + * 获取当前配方的完整需求条目,供显示模块序列化后发送给客户端。 + */ + public List getRequirementEntries(CelestialForgingAnvilBlockEntity be) { + RecipeHolder clientRecipe = this.getClientRecipe(be); + return clientRecipe == null ? List.of() : clientRecipe.value().requirements(); + } + + /** + * 持久化当前改造状态。 + */ + @Override + public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { + tag.putString( + "pigsplusCelestialReformerRecipe", + this.activeRecipeId == null ? "" : this.activeRecipeId.toString() + ); + tag.putInt("pigsplusCelestialReformerInputIndex", this.inputIndex); + tag.putInt("pigsplusCelestialReformerProgress", this.progress); + tag.putIntArray("pigsplusCelestialReformerRequirementProgress", this.requirementProgresses); + } + + /** + * 从存档数据恢复当前改造状态。 + */ + @Override + public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { + String recipeId = tag.getString("pigsplusCelestialReformerRecipe"); + if (recipeId.isEmpty()) { + recipeId = tag.getString("pigsplusPlanetaryReformerRecipe"); + } + this.activeRecipeId = recipeId.isEmpty() ? null : ResourceLocation.tryParse(recipeId); + this.inputIndex = tag.contains("pigsplusCelestialReformerInputIndex") + ? tag.getInt("pigsplusCelestialReformerInputIndex") + : tag.getInt("pigsplusPlanetaryReformerInputIndex"); + this.progress = tag.contains("pigsplusCelestialReformerProgress") + ? tag.getInt("pigsplusCelestialReformerProgress") + : tag.getInt("pigsplusPlanetaryReformerProgress"); + this.requirementProgresses = tag.getIntArray("pigsplusCelestialReformerRequirementProgress"); + } + + /** + * 写入客户端同步标签,当前与存档序列化保持一致。 + */ + @Override + public void writeUpdateTag(CompoundTag tag, HolderLookup.Provider registries) { + this.saveAdditional(tag, registries); + } + + /** + * 读取客户端同步标签。 + */ + @Override + public void readUpdateTag(CompoundTag tag, HolderLookup.Provider registries) { + this.loadAdditional(tag, registries); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/StarReformerHandler.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/StarReformerHandler.java new file mode 100644 index 00000000..c0f237dd --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/StarReformerHandler.java @@ -0,0 +1,18 @@ +package dev.anvilcraft.pigsplus.block.entity.megastructure; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; + +public class StarReformerHandler extends ReformerHandler { + public static final String NAME = "star_reformer"; + + @Override + public String name() { + return NAME; + } + + @Override + public void serverTick(CelestialForgingAnvilBlockEntity be) { + if (!be.isAmplifierPresent()) return; + super.serverTick(be); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/package-info.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/package-info.java new file mode 100644 index 00000000..467a346b --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/megastructure/package-info.java @@ -0,0 +1,3 @@ +@net.minecraft.MethodsReturnNonnullByDefault +@javax.annotation.ParametersAreNonnullByDefault +package dev.anvilcraft.pigsplus.block.entity.megastructure; \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/client/AnvilCraftPigsPlusClient.java b/src/main/java/dev/anvilcraft/pigsplus/client/AnvilCraftPigsPlusClient.java index bfc36c55..4b7f477a 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/client/AnvilCraftPigsPlusClient.java +++ b/src/main/java/dev/anvilcraft/pigsplus/client/AnvilCraftPigsPlusClient.java @@ -2,6 +2,7 @@ import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; import dev.anvilcraft.pigsplus.client.markdown.recipe.MDPrecisionElectromagneticProcessingRecipeComponent; +import dev.anvilcraft.pigsplus.client.markdown.recipe.MDCelestialReformerRecipeComponent; import dev.anvilcraft.pigsplus.client.particle.ExpParticle; import dev.anvilcraft.pigsplus.init.AddonBlocks; import dev.anvilcraft.pigsplus.init.AddonFluids; @@ -36,6 +37,14 @@ public class AnvilCraftPigsPlusClient { ) ); + public static final DeferredHolder, MDRecipeComponent.RecipeComponentFactory> + CELESTIAL_REFORMER = RECIPE_COMPONENT_FACTORIES.register( + "celestial_reformer", () -> MDRecipeComponent.RecipeComponentFactory.create( + AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get(), + MDCelestialReformerRecipeComponent::new + ) + ); + public AnvilCraftPigsPlusClient(IEventBus modBus, ModContainer container) { modBus.addListener(RegisterParticleProvidersEvent.class, event -> event.registerSpriteSet(AddonParticleTypes.EXP.get(), ExpParticle.Provider::new)); diff --git a/src/main/java/dev/anvilcraft/pigsplus/client/event/RegisterAdditionalEventListener.java b/src/main/java/dev/anvilcraft/pigsplus/client/event/RegisterAdditionalEventListener.java index d05611f3..a3b72036 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/client/event/RegisterAdditionalEventListener.java +++ b/src/main/java/dev/anvilcraft/pigsplus/client/event/RegisterAdditionalEventListener.java @@ -17,5 +17,7 @@ public static void registerModels(ModelEvent.RegisterAdditional event) { event.register(ModelResourceLocation.standalone(AnvilCraftPigsPlus.of("block/enchanted_generator_head"))); event.register(ModelResourceLocation.standalone(AnvilCraftPigsPlus.of("block/adjustable_power_converter_core"))); event.register(ModelResourceLocation.standalone(AnvilCraftPigsPlus.of("block/adjustable_power_converter_core_out"))); + event.register(ModelResourceLocation.standalone(AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_1_reformer"))); + event.register(ModelResourceLocation.standalone(AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_4_reformer"))); } } diff --git a/src/main/java/dev/anvilcraft/pigsplus/client/jade/TextureElement.java b/src/main/java/dev/anvilcraft/pigsplus/client/jade/TextureElement.java new file mode 100644 index 00000000..9f67c1d2 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/client/jade/TextureElement.java @@ -0,0 +1,41 @@ +package dev.anvilcraft.pigsplus.client.jade; + +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec2; +import snownee.jade.api.ui.Element; + +/** + * Jade 中直接绘制普通纹理的图标元素。 + */ +public class TextureElement extends Element { + private final ResourceLocation texture; + private final int width; + private final int height; + + public TextureElement(ResourceLocation texture, int width, int height) { + this.texture = texture; + this.width = width; + this.height = height; + } + + @Override + public Vec2 getSize() { + return new Vec2(this.width, this.height); + } + + @Override + public void render(GuiGraphics guiGraphics, float x, float y, float alpha, float partialTick) { + guiGraphics.blit( + this.texture, + (int) x, + (int) y, + 0, + 0, + this.width, + this.height, + this.width, + this.height + ); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/client/markdown/recipe/MDCelestialReformerRecipeComponent.java b/src/main/java/dev/anvilcraft/pigsplus/client/markdown/recipe/MDCelestialReformerRecipeComponent.java new file mode 100644 index 00000000..925cc15c --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/client/markdown/recipe/MDCelestialReformerRecipeComponent.java @@ -0,0 +1,174 @@ +package dev.anvilcraft.pigsplus.client.markdown.recipe; + +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.requirement.RequirementEntry; +import dev.anvilcraft.pigsplus.api.requirement.ReformerRequirement; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe.LaserType; +import dev.anvilcraft.pigsplus.util.ReformerIcons; +import dev.anvilcraft.resource.ageratum.client.feat.markdown.MDRenderContext; +import dev.anvilcraft.resource.ageratum.client.feat.markdown.component.extend.MDRecipeComponent; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.util.AgeratumUtil; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; + +public class MDCelestialReformerRecipeComponent extends MDRecipeComponent { + private static final ResourceLocation TEXTURE = AnvilCraft.of("textures/gui/ageratum/128back.png"); + + private final CelestialReformerRecipe recipe; + + public MDCelestialReformerRecipeComponent( + CelestialReformerRecipe recipe, + boolean enableAlignCenter + ) { + super(TEXTURE, 128, componentHeight(recipe), enableAlignCenter); + this.recipe = recipe; + } + + @Override + protected void renderRecipe(MDRenderContext context, float mouseX, float mouseY) { + int x = 8; + for (CelestialReformerRecipe.ItemInput input : recipe.items()) { + var item = BuiltInRegistries.ITEM.get(input.item()); + ItemStack stack = new ItemStack(item, Math.min(input.count(), 64)); + AgeratumUtil.renderItem(context, stack, mouseX, mouseY, x, 24); + AgeratumUtil.renderText( + context.graphics(), + Component.literal(String.valueOf(input.count())), + x - 8, + 44 + ); + x += 20; + } + AgeratumUtil.renderArrow(context.graphics(), 78, 16); + int iconY = 56; + int iconIndex = 0; + ReformerModification modification = + ReformerModifications.REGISTRY.get(recipe.modification()); + if (modification != null) { + this.renderIconSlot( + context, + ReformerIcons.SLOT_CONCEPT, + modification.getIcon(), + modification.getDescription(), + iconY, + iconIndex, + mouseX, + mouseY + ); + iconIndex++; + } + for (RequirementEntry entry : recipe.requirements()) { + ReformerRequirement requirement = entry.requirement(); + this.renderIconSlot( + context, + ReformerIcons.SLOT_CONCEPT, + ReformerIcons.requirementIcon(entry.id()), + requirement.getDescription(), + iconY, + iconIndex, + mouseX, + mouseY + ); + iconIndex++; + } + for (CelestialReformerRecipe.LaserInput laser : recipe.lasers()) { + this.renderIconSlot( + context, + ReformerIcons.SLOT_CONCEPT, + ReformerIcons.laserIcon(), + Component.translatable( + "gui.anvilcraft_pigsplus.jei.laser", + laser.level(), + laserType(laser.type()) + ), + iconY, + iconIndex, + mouseX, + mouseY + ); + iconIndex++; + } + + int infoY = iconY + ((iconIndex + 5) / 6) * ReformerIcons.SLOT_SIZE + 8; + for (CelestialReformerRecipe.FluidInput input : recipe.fluids()) { + var fluid = BuiltInRegistries.FLUID.get(input.fluid()); + AgeratumUtil.renderText( + context.graphics(), + Component.translatable( + "gui.anvilcraft_pigsplus.jei.fluid", + fluid.getFluidType().getDescription(), + input.amount() + ), + 8, + infoY + ); + infoY += 10; + } + } + + private void renderIconSlot( + MDRenderContext context, + net.minecraft.resources.ResourceLocation slot, + net.minecraft.resources.ResourceLocation icon, + Component tooltip, + int startY, + int index, + float mouseX, + float mouseY + ) { + int x = 8 + (index % 6) * ReformerIcons.SLOT_SIZE; + int y = startY + (index / 6) * ReformerIcons.SLOT_SIZE; + context.graphics().blit( + slot, + x, + y, + 0, + 0, + ReformerIcons.SLOT_SIZE, + ReformerIcons.SLOT_SIZE, + ReformerIcons.SLOT_SIZE, + ReformerIcons.SLOT_SIZE + ); + context.graphics().blit( + icon, + x + 1, + y + 1, + 0, + 0, + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE + ); + if (AgeratumUtil.isHover( + x, + y, + ReformerIcons.SLOT_SIZE, + ReformerIcons.SLOT_SIZE, + mouseX, + mouseY + )) { + context.addTooltip(tooltip); + } + } + + private static int componentHeight(CelestialReformerRecipe recipe) { + int iconCount = 1 + recipe.requirements().size() + recipe.lasers().size(); + int rows = Math.max(1, (iconCount + 5) / 6); + return Math.max(96, 56 + rows * ReformerIcons.SLOT_SIZE + 20); + } + + private static Component laserType(LaserType type) { + String key = type == LaserType.ANY + ? "gui.anvilcraft_pigsplus.laser.type.any" + : type == LaserType.GAMMA + ? "gui.anvilcraft_pigsplus.laser.type.gamma" + : "gui.anvilcraft_pigsplus.laser.type.normal"; + return Component.translatable(key); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/config/AddonServerConfig.java b/src/main/java/dev/anvilcraft/pigsplus/config/AddonServerConfig.java index 489eeacc..87225b5a 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/config/AddonServerConfig.java +++ b/src/main/java/dev/anvilcraft/pigsplus/config/AddonServerConfig.java @@ -23,6 +23,11 @@ public class AddonServerConfig { @Comment("Allow the Void Acid to destroy blocks") public boolean voidAcidDestroy = true; + // 行星/恒星改造器 + @Comment("Absorption interval of planetary/star reformer (in ticks)") + @BoundedDiscrete(min = 1, max = 1000) + public int reformerAbsorptionCooldown = 8; + // 电力附魔台 @CollapsibleObject public ElectricEnchantingTable electricEnchantingTable = new ElectricEnchantingTable(); diff --git a/src/main/java/dev/anvilcraft/pigsplus/data/lang/LangHandler.java b/src/main/java/dev/anvilcraft/pigsplus/data/lang/LangHandler.java index 98d4f5fc..c38bfd58 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/data/lang/LangHandler.java +++ b/src/main/java/dev/anvilcraft/pigsplus/data/lang/LangHandler.java @@ -13,6 +13,7 @@ public class LangHandler { public static void init(RegistrumLangProvider provider) { ConfigData.readConfigClass(provider, AddonServerConfig.class); JeiLang.init(provider); + RecipeLang.init(provider); provider.add( "block.anvilcraft_pigsplus.enchanted_generator.placement_too_close_to_another", @@ -42,5 +43,21 @@ public static void init(RegistrumLangProvider provider) { provider.add("config.jade.plugin_anvilcraft_pigsplus.electric_enchanting_table", "Electric Enchanting Table"); provider.add("config.jade.plugin_anvilcraft_pigsplus.enchanted_generator", "Enchanted Generator"); provider.add("config.jade.plugin_anvilcraft_pigsplus.precision_magnetic_pivot", "Precision Magnetic Pivot"); + provider.add("config.jade.plugin_anvilcraft_pigsplus.celestial_reformer", "Celestial Reformer"); + provider.add("screen.anvilcraft.cfa.megastructure.planetary_reformer", "Planetary Reformer"); + provider.add("screen.anvilcraft.cfa.megastructure.star_reformer", "Star Reformer"); + provider.add("screen.anvilcraft.cfa.megastructure.planetary_reformer.usage", "Consume resources to reform the celestial body."); + provider.add("screen.anvilcraft.cfa.megastructure.star_reformer.usage", "Consume resources to reform the celestial body."); + provider.add("gui.anvilcraft_pigsplus.jei.fluid", "Fluid: %s: %s mB"); + provider.add("gui.anvilcraft_pigsplus.category.celestial_reformer", "Celestial Reformer"); + provider.add("gui.anvilcraft_pigsplus.jei.modification", "Modification: %s"); + provider.add("gui.anvilcraft_pigsplus.jei.laser", "Laser: level %s (%s)"); + provider.add("gui.anvilcraft_pigsplus.laser.type.any", "Any laser"); + provider.add("gui.anvilcraft_pigsplus.laser.type.gamma", "Gamma laser"); + provider.add("gui.anvilcraft_pigsplus.laser.type.normal", "Normal laser"); + provider.add("tooltip.anvilcraft_pigsplus.celestial_reformer.current.item", "%s: %s / %s"); + provider.add("tooltip.anvilcraft_pigsplus.celestial_reformer.current.fluid", "%s: %s / %s mB"); + provider.add("tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser", "Laser: level %s (%s)"); + provider.add("enchantment.anvilcraft_pigsplus.endurance", "Endurance"); } } diff --git a/src/main/java/dev/anvilcraft/pigsplus/data/lang/RecipeLang.java b/src/main/java/dev/anvilcraft/pigsplus/data/lang/RecipeLang.java new file mode 100644 index 00000000..027f34ef --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/data/lang/RecipeLang.java @@ -0,0 +1,60 @@ +package dev.anvilcraft.pigsplus.data.lang; + +import dev.anvilcraft.lib.v2.registrum.providers.RegistrumLangProvider; + +public class RecipeLang { + public static void init(RegistrumLangProvider provider) { + provider.add("modification.anvilcraft_pigsplus.unknown", "Unknown Modification"); + provider.add("modification.anvilcraft_pigsplus.slow_rotation", "Slow Down Rotation"); + provider.add("modification.anvilcraft_pigsplus.fast_rotation", "Speed Up Rotation"); + provider.add("modification.anvilcraft_pigsplus.strengthen_magnetic_field", "Strengthen Magnetic Field"); + provider.add("modification.anvilcraft_pigsplus.weaken_magnetic_field", "Weaken Magnetic Field"); + provider.add("modification.anvilcraft_pigsplus.increase_liquid_coverage", "Increase Ocean Coverage"); + provider.add("modification.anvilcraft_pigsplus.decrease_liquid_coverage", "Decrease Ocean Coverage"); + provider.add("modification.anvilcraft_pigsplus.add_atmosphere", "Add Atmosphere"); + provider.add("modification.anvilcraft_pigsplus.increase_temperature", "Increase Temperature"); + provider.add("modification.anvilcraft_pigsplus.decrease_temperature", "Decrease Temperature"); + provider.add("modification.anvilcraft_pigsplus.add_biological_resources", "Add Biological Resources"); + provider.add("modification.anvilcraft_pigsplus.add_civilization", "Add Low Civilization"); + provider.add("modification.anvilcraft_pigsplus.wasteland", "Turn Into Wasteland"); + provider.add("modification.anvilcraft_pigsplus.void_wasteland", "Turn Into Void Wasteland"); + + provider.add("concept.anvilcraft_pigsplus.rotation_speed", "Rotation Speed"); + provider.add("concept.anvilcraft_pigsplus.magnetic_field", "Magnetic Field"); + provider.add("concept.anvilcraft_pigsplus.sea", "Liquid Coverage"); + provider.add("concept.anvilcraft_pigsplus.temperature", "Temperature"); + provider.add("concept.anvilcraft_pigsplus.atmosphere", "Atmosphere"); + provider.add("concept.anvilcraft_pigsplus.biologic", "Biological Resources"); + provider.add("concept.anvilcraft_pigsplus.civilization", "Civilization"); + provider.add("concept.anvilcraft_pigsplus.plante_type", "Planet Type"); + provider.add("concept.anvilcraft_pigsplus.reformer", "Reformer"); + provider.add("concept.anvilcraft_pigsplus.laser", "Laser"); + provider.add("concept.anvilcraft_pigsplus.default", "Unknown Concept"); + + provider.add("requirement.anvilcraft_pigsplus.unknown", "Unknown Requirement"); + provider.add("requirement.anvilcraft_pigsplus.star_reformer", "Requires Star Reformer"); + provider.add("requirement.anvilcraft_pigsplus.planetary_reformer", "Requires Planetary Reformer"); + provider.add("requirement.anvilcraft_pigsplus.has_liquid", "Requires Liquid"); + provider.add("requirement.anvilcraft_pigsplus.no_liquid", "Requires No Liquid"); + provider.add("requirement.anvilcraft_pigsplus.has_atmosphere", "Requires Atmosphere"); + provider.add("requirement.anvilcraft_pigsplus.no_atmosphere", "Requires No Atmosphere"); + provider.add("requirement.anvilcraft_pigsplus.rotation_speed_at_least", "Rotation Speed >= %s"); + provider.add("requirement.anvilcraft_pigsplus.rotation_speed_at_most", "Rotation Speed <= %s"); + provider.add("requirement.anvilcraft_pigsplus.magnetic_field_at_least", "Magnetic Field >= %s"); + provider.add("requirement.anvilcraft_pigsplus.magnetic_field_at_most", "Magnetic Field <= %s"); + provider.add("requirement.anvilcraft_pigsplus.magnetic_field_between", "Magnetic Field >= %s and <= %s"); + provider.add("requirement.anvilcraft_pigsplus.rotation_speed_between", "Rotation Speed >= %s and <= %s"); + provider.add("requirement.anvilcraft_pigsplus.has_other_megastructure", "Requires Another Megastructure"); + provider.add("requirement.anvilcraft_pigsplus.no_other_megastructure", "Requires No Other Megastructure"); + provider.add("requirement.anvilcraft_pigsplus.rocky_planet", "Requires Rocky Planet"); + provider.add("requirement.anvilcraft_pigsplus.water_ocean", "Requires No Liquid Or Water Ocean Below Full Coverage"); + provider.add("requirement.anvilcraft_pigsplus.temperature_at_least", "Temperature >= %s"); + provider.add("requirement.anvilcraft_pigsplus.temperature_at_most", "Temperature <= %s"); + provider.add("requirement.anvilcraft_pigsplus.temperature_between", "Temperature %s - %s"); + provider.add("requirement.anvilcraft_pigsplus.liquid_coverage_at_least", "Liquid Coverage >= %s"); + provider.add("requirement.anvilcraft_pigsplus.liquid_coverage_at_most", "Liquid Coverage <= %s"); + provider.add("requirement.anvilcraft_pigsplus.liquid_coverage_between", "Liquid Coverage %s - %s"); + provider.add("requirement.anvilcraft_pigsplus.has_biological_resources", "Requires Biological Resources"); + provider.add("requirement.anvilcraft_pigsplus.has_civilization", "Requires Civilization"); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/data/recipe/CelestialReformerRecipeLoader.java b/src/main/java/dev/anvilcraft/pigsplus/data/recipe/CelestialReformerRecipeLoader.java new file mode 100644 index 00000000..0f4cd9cf --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/data/recipe/CelestialReformerRecipeLoader.java @@ -0,0 +1,200 @@ +package dev.anvilcraft.pigsplus.data.recipe; + +import dev.anvilcraft.lib.v2.registrum.providers.RegistrumRecipeProvider; +import dev.anvilcraft.pigsplus.init.AddonFluids; +import dev.anvilcraft.pigsplus.init.PigsReformerModifications; +import dev.anvilcraft.pigsplus.init.PigsReformerRequirements; +import dev.anvilcraft.pigsplus.api.requirement.LiquidCoverageRangeRequirement; +import dev.anvilcraft.pigsplus.api.requirement.MagneticFieldRequirement; +import dev.anvilcraft.pigsplus.api.requirement.RotationSpeedRequirement; +import dev.anvilcraft.pigsplus.api.requirement.TemperatureRangeRequirement; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; +import dev.dubhe.anvilcraft.block.entity.celestial.LiquidCoverage; +import dev.dubhe.anvilcraft.block.entity.celestial.Temperature; +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import dev.dubhe.anvilcraft.init.block.ModFluids; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.item.Items; + +public class CelestialReformerRecipeLoader { + public static void init(RegistrumRecipeProvider provider) { + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.SLOW_ROTATION) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement( + PigsReformerRequirements.ROTATION_SPEED, + new RotationSpeedRequirement(1, null) + ) + .item(ModBlocks.LEAD_BLOCK, 640) + .save(provider, "slow_rotation"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.FAST_ROTATION) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement( + PigsReformerRequirements.ROTATION_SPEED, + new RotationSpeedRequirement(null, 3) + ) + .item(ModBlocks.SUGAR_BLOCK, 640) + .save(provider, "fast_rotation"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.STRENGTHEN_MAGNETIC_FIELD) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement( + PigsReformerRequirements.MAGNETIC_FIELD, + new MagneticFieldRequirement(null, 3) + ) + .item(ModBlocks.MAGNET_BLOCK, 640) + .save(provider, "strengthen_magnetic_field"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.WEAKEN_MAGNETIC_FIELD) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement( + PigsReformerRequirements.MAGNETIC_FIELD, + new MagneticFieldRequirement(1, null) + ) + .item(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE, 640) + .save(provider, "weaken_magnetic_field"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.INCREASE_LIQUID_COVERAGE) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.WATER_OCEAN) + .fluid(ResourceLocation.withDefaultNamespace("water"), 320000) + .save(provider, "increase_liquid_coverage"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.DECREASE_LIQUID_COVERAGE) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.HAS_LIQUID) + .item(Items.BUCKET, 320) + .save(provider, "decrease_liquid_coverage"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.INCREASE_TEMPERATURE) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement( + PigsReformerRequirements.TEMPERATURE_RANGE, + new TemperatureRangeRequirement(Temperature.FREEZING, Temperature.HOT) + ) + .item(ModBlocks.HEATED_TUNGSTEN_BLOCK, 320) + .save(provider, "increase_temperature"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.DECREASE_TEMPERATURE) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement( + PigsReformerRequirements.TEMPERATURE_RANGE, + new TemperatureRangeRequirement(Temperature.COLD, Temperature.SCORCHED) + ) + .item(Blocks.BLUE_ICE, 320) + .save(provider, "decrease_temperature"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.ADD_ATMOSPHERE) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.NO_ATMOSPHERE) + .item(Items.GLASS_BOTTLE, 320) + .save(provider, "add_atmosphere"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.ADD_BIOLOGICAL_RESOURCES) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.HAS_ATMOSPHERE) + .requirement(PigsReformerRequirements.HAS_LIQUID) + .requirement( + PigsReformerRequirements.LIQUID_COVERAGE_RANGE, + new LiquidCoverageRangeRequirement(LiquidCoverage.NONE, LiquidCoverage.MEDIUM) + ) + .requirement( + PigsReformerRequirements.TEMPERATURE_RANGE, + new TemperatureRangeRequirement(Temperature.MILD, Temperature.MILD) + ) + .item(Blocks.BONE_BLOCK, 320) + .item(Blocks.MOSS_BLOCK, 320) + .item(Items.COD, 320) + .save(provider, "add_biological_resources"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.ADD_CIVILIZATION) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.HAS_BIOLOGICAL_RESOURCES) + .requirement( + PigsReformerRequirements.LIQUID_COVERAGE_RANGE, + new LiquidCoverageRangeRequirement(LiquidCoverage.MEDIUM, LiquidCoverage.MEDIUM) + ) + .item(Items.BOOK, 1280) + .fluid(ModFluids.EXP_FLUID.getId(), 1280000) + .save(provider, "add_civilization"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.WASTELAND) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.HAS_CIVILIZATION) + .item(ModBlocks.PLUTONIUM_BLOCK, 320) + .save(provider, "wasteland"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.VOID_WASTELAND) + .requirement(PigsReformerRequirements.PLANETARY_REFORMER) + .requirement(PigsReformerRequirements.ROCKY_PLANET) + .requirement(PigsReformerRequirements.HAS_CIVILIZATION) + .fluid(AddonFluids.VOID_ACID.getId(), 320000) + .save(provider, "void_wasteland"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.SLOW_ROTATION) + .requirement(PigsReformerRequirements.STAR_REFORMER) + .requirement( + PigsReformerRequirements.ROTATION_SPEED, + new RotationSpeedRequirement(1, null) + ) + .item(ModBlocks.LEAD_BLOCK, 3200) + .laser(16) + .save(provider, "star_slow_rotation"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.FAST_ROTATION) + .requirement(PigsReformerRequirements.STAR_REFORMER) + .requirement( + PigsReformerRequirements.ROTATION_SPEED, + new RotationSpeedRequirement(null, 3) + ) + .item(ModBlocks.SUGAR_BLOCK, 3200) + .laser(16) + .save(provider, "star_fast_rotation"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.STRENGTHEN_MAGNETIC_FIELD) + .requirement(PigsReformerRequirements.STAR_REFORMER) + .requirement( + PigsReformerRequirements.MAGNETIC_FIELD, + new MagneticFieldRequirement(null, 3) + ) + .item(ModBlocks.MAGNET_BLOCK, 3200) + .laser(16) + .save(provider, "star_strengthen_magnetic_field"); + + CelestialReformerRecipe.builder() + .modification(PigsReformerModifications.WEAKEN_MAGNETIC_FIELD) + .requirement(PigsReformerRequirements.STAR_REFORMER) + .requirement( + PigsReformerRequirements.MAGNETIC_FIELD, + new MagneticFieldRequirement(1, null) + ) + .item(Blocks.HEAVY_WEIGHTED_PRESSURE_PLATE, 3200) + .laser(16) + .save(provider, "star_weaken_magnetic_field"); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/data/recipe/RecipeHandler.java b/src/main/java/dev/anvilcraft/pigsplus/data/recipe/RecipeHandler.java index 305ad8e2..eaa6ae81 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/data/recipe/RecipeHandler.java +++ b/src/main/java/dev/anvilcraft/pigsplus/data/recipe/RecipeHandler.java @@ -22,6 +22,7 @@ public static void init(RegistrumRecipeProvider provider) { MultipleToOneSmithingRecipeLoader.init(provider); PrecisionElectromagneticProcessingLoader.init(provider); ProceduralProcessRecipeLoader.init(provider); + CelestialReformerRecipeLoader.init(provider); MineralFountainRecipe.builder() diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/ModAnvilBehaviors.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonAnvilBehaviors.java similarity index 96% rename from src/main/java/dev/anvilcraft/pigsplus/init/ModAnvilBehaviors.java rename to src/main/java/dev/anvilcraft/pigsplus/init/AddonAnvilBehaviors.java index 05119cc0..3c37657d 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/ModAnvilBehaviors.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonAnvilBehaviors.java @@ -9,7 +9,7 @@ import net.neoforged.fml.common.EventBusSubscriber; @EventBusSubscriber(modid = AnvilCraftPigsPlus.MOD_ID) -public class ModAnvilBehaviors { +public class AddonAnvilBehaviors { @SubscribeEvent public static void register(AnvilBehaviorRegisterEvent event) { event.registerBehavior(AddonBlocks.BLOCK_BREAKER.get(), new BlockBreakerBehavior()); diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/AddonItems.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonItems.java index 397f268b..3841c4e8 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/AddonItems.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonItems.java @@ -8,8 +8,10 @@ import dev.anvilcraft.pigsplus.item.PortableWirelessChargerItem; import dev.dubhe.anvilcraft.data.AnvilCraftDatagen; import dev.dubhe.anvilcraft.init.block.ModBlocks; +import dev.dubhe.anvilcraft.init.item.ModComponents; import dev.dubhe.anvilcraft.init.item.ModItemTags; import dev.dubhe.anvilcraft.init.item.ModItems; +import dev.dubhe.anvilcraft.item.property.component.Eternal; import dev.dubhe.anvilcraft.util.DataGenUtil; import dev.dubhe.anvilcraft.util.registrater.ModelProviderUtil; import net.minecraft.data.recipes.RecipeCategory; @@ -18,6 +20,7 @@ import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; +import net.minecraft.world.item.Rarity; import static dev.anvilcraft.pigsplus.AnvilCraftPigsPlus.REGISTRATE; @@ -50,6 +53,24 @@ public class AddonItems { .item("echo_geode", Item::new) .register(); + public static final ItemEntry CELESTIAL_REFORMER_COMPONENT = REGISTRATE + .item("celestial_reformer_component", Item::new) + .properties(properties -> properties + .fireResistant() + .rarity(Rarity.EPIC) + .component(ModComponents.ETERNAL, Eternal.INSTANCE) + ) + .tag(ModItemTags.EXPLOSION_PROOF) + .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get(), 4) + .pattern("TKT") + .pattern("K K") + .pattern("TKT") + .define('K', AddonItems.KARAKURI_COMPONENT) + .define('T', ModItems.TRANSCENDIUM_INGOT) + .unlockedBy(AnvilCraftDatagen.hasItem(ModItems.TRANSCENDIUM_INGOT), AnvilCraftDatagen.has(ModItems.TRANSCENDIUM_INGOT)) + .save(provider)) + .register(); + public static final ItemEntry CHAOTIC_RAW_ORE = REGISTRATE .item("chaotic_raw_ore", Item::new) .recipe((ctx, provider) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ctx.get(), 9) @@ -89,7 +110,13 @@ public class AddonItems { public static final ItemEntry MENGER_SPONGE_HOLY_STAFF = REGISTRATE .item("menger_sponge_holy_staff", MengerSpongeHolyStaffItem::new) - .properties((properties) -> properties.stacksTo(1)) + .properties(properties -> properties + .stacksTo(1) + .fireResistant() + .rarity(Rarity.EPIC) + .component(ModComponents.ETERNAL, Eternal.INSTANCE) + ) + .tag(ModItemTags.EXPLOSION_PROOF) .model(DataGenUtil::noExtraModelOrState) .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get()) .pattern("A") @@ -117,4 +144,4 @@ public class AddonItems { public static void register() { } -} \ No newline at end of file +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/AddonRecipeTypes.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonRecipeTypes.java index 668bcbaa..2aaa0137 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/AddonRecipeTypes.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonRecipeTypes.java @@ -1,6 +1,7 @@ package dev.anvilcraft.pigsplus.init; import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; import dev.anvilcraft.pigsplus.recipe.PrecisionElectromagneticProcessingRecipe; import net.minecraft.core.registries.Registries; import net.minecraft.world.item.crafting.Recipe; @@ -20,6 +21,10 @@ public class AddonRecipeTypes { registerType("precision_electromagnetic_processing"); public static final DeferredHolder, RecipeSerializer> PRECISION_ELECTROMAGNETIC_PROCESSING_SERIALIZER = RECIPE_SERIALIZERS.register("precision_electromagnetic_processing", PrecisionElectromagneticProcessingRecipe.Serializer::new); + public static final DeferredHolder, RecipeType> CELESTIAL_REFORMER_TYPE = + registerType("celestial_reformer"); + public static final DeferredHolder, RecipeSerializer> CELESTIAL_REFORMER_SERIALIZER = + RECIPE_SERIALIZERS.register("celestial_reformer", CelestialReformerRecipe.Serializer::new); private static > DeferredHolder, RecipeType> registerType(String name) { return RECIPE_TYPES.register( diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerModifications.java b/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerModifications.java new file mode 100644 index 00000000..5f532f75 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerModifications.java @@ -0,0 +1,57 @@ +package dev.anvilcraft.pigsplus.init; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.api.modification.AddBiologicalResourcesModification; +import dev.anvilcraft.pigsplus.api.modification.AddCivilizationModification; +import dev.anvilcraft.pigsplus.api.modification.AddAtmosphereModification; +import dev.anvilcraft.pigsplus.api.modification.DecreaseLiquidCoverageModification; +import dev.anvilcraft.pigsplus.api.modification.DecreaseTemperatureModification; +import dev.anvilcraft.pigsplus.api.modification.FastRotationModification; +import dev.anvilcraft.pigsplus.api.modification.IncreaseLiquidCoverageModification; +import dev.anvilcraft.pigsplus.api.modification.IncreaseTemperatureModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.modification.SlowRotationModification; +import dev.anvilcraft.pigsplus.api.modification.StrengthenMagneticFieldModification; +import dev.anvilcraft.pigsplus.api.modification.VoidWastelandModification; +import dev.anvilcraft.pigsplus.api.modification.WastelandModification; +import dev.anvilcraft.pigsplus.api.modification.WeakenMagneticFieldModification; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class PigsReformerModifications { + private static final DeferredRegister DF = + DeferredRegister.create(ReformerModifications.REGISTRY, AnvilCraftPigsPlus.MOD_ID); + + public static final DeferredHolder FAST_ROTATION = + DF.register("fast_rotation", FastRotationModification::new); + public static final DeferredHolder SLOW_ROTATION = + DF.register("slow_rotation", SlowRotationModification::new); + public static final DeferredHolder STRENGTHEN_MAGNETIC_FIELD = + DF.register("strengthen_magnetic_field", StrengthenMagneticFieldModification::new); + public static final DeferredHolder WEAKEN_MAGNETIC_FIELD = + DF.register("weaken_magnetic_field", WeakenMagneticFieldModification::new); + public static final DeferredHolder INCREASE_LIQUID_COVERAGE = + DF.register("increase_liquid_coverage", IncreaseLiquidCoverageModification::new); + public static final DeferredHolder DECREASE_LIQUID_COVERAGE = + DF.register("decrease_liquid_coverage", DecreaseLiquidCoverageModification::new); + public static final DeferredHolder ADD_ATMOSPHERE = + DF.register("add_atmosphere", AddAtmosphereModification::new); + public static final DeferredHolder INCREASE_TEMPERATURE = + DF.register("increase_temperature", IncreaseTemperatureModification::new); + public static final DeferredHolder DECREASE_TEMPERATURE = + DF.register("decrease_temperature", DecreaseTemperatureModification::new); + public static final DeferredHolder ADD_BIOLOGICAL_RESOURCES = + DF.register("add_biological_resources", AddBiologicalResourcesModification::new); + public static final DeferredHolder ADD_CIVILIZATION = + DF.register("add_civilization", AddCivilizationModification::new); + public static final DeferredHolder WASTELAND = + DF.register("wasteland", WastelandModification::new); + public static final DeferredHolder VOID_WASTELAND = + DF.register("void_wasteland", VoidWastelandModification::new); + + public static void register(IEventBus bus) { + DF.register(bus); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerRequirements.java b/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerRequirements.java new file mode 100644 index 00000000..08556a1c --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/init/PigsReformerRequirements.java @@ -0,0 +1,68 @@ +package dev.anvilcraft.pigsplus.init; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.api.requirement.CelestialReformerRequirements; +import dev.anvilcraft.pigsplus.api.requirement.HasAtmosphereRequirement; +import dev.anvilcraft.pigsplus.api.requirement.HasBiologicalResourcesRequirement; +import dev.anvilcraft.pigsplus.api.requirement.HasCivilizationRequirement; +import dev.anvilcraft.pigsplus.api.requirement.HasLiquidRequirement; +import dev.anvilcraft.pigsplus.api.requirement.HasOtherMegastructureRequirement; +import dev.anvilcraft.pigsplus.api.requirement.LiquidCoverageRangeRequirement; +import dev.anvilcraft.pigsplus.api.requirement.MagneticFieldRequirement; +import dev.anvilcraft.pigsplus.api.requirement.NoAtmosphereRequirement; +import dev.anvilcraft.pigsplus.api.requirement.NoLiquidRequirement; +import dev.anvilcraft.pigsplus.api.requirement.NoOtherMegastructureRequirement; +import dev.anvilcraft.pigsplus.api.requirement.PlanetaryReformerRequirement; +import dev.anvilcraft.pigsplus.api.requirement.ReformerRequirement; +import dev.anvilcraft.pigsplus.api.requirement.RockyPlanetRequirement; +import dev.anvilcraft.pigsplus.api.requirement.RotationSpeedRequirement; +import dev.anvilcraft.pigsplus.api.requirement.StarReformerRequirement; +import dev.anvilcraft.pigsplus.api.requirement.TemperatureRangeRequirement; +import dev.anvilcraft.pigsplus.api.requirement.WaterOceanRequirement; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class PigsReformerRequirements { + private static final DeferredRegister DF = DeferredRegister.create( + CelestialReformerRequirements.REGISTRY, + AnvilCraftPigsPlus.MOD_ID + ); + + public static final DeferredHolder STAR_REFORMER = + DF.register("star_reformer", StarReformerRequirement::new); + public static final DeferredHolder PLANETARY_REFORMER = + DF.register("planetary_reformer", PlanetaryReformerRequirement::new); + public static final DeferredHolder HAS_LIQUID = + DF.register("has_liquid", HasLiquidRequirement::new); + public static final DeferredHolder NO_LIQUID = + DF.register("no_liquid", NoLiquidRequirement::new); + public static final DeferredHolder HAS_ATMOSPHERE = + DF.register("has_atmosphere", HasAtmosphereRequirement::new); + public static final DeferredHolder NO_ATMOSPHERE = + DF.register("no_atmosphere", NoAtmosphereRequirement::new); + public static final DeferredHolder ROTATION_SPEED = + DF.register("rotation_speed", RotationSpeedRequirement::new); + public static final DeferredHolder MAGNETIC_FIELD = + DF.register("magnetic_field", MagneticFieldRequirement::new); + public static final DeferredHolder ROCKY_PLANET = + DF.register("rocky_planet", RockyPlanetRequirement::new); + public static final DeferredHolder WATER_OCEAN = + DF.register("water_ocean", WaterOceanRequirement::new); + public static final DeferredHolder TEMPERATURE_RANGE = + DF.register("temperature_range", TemperatureRangeRequirement::new); + public static final DeferredHolder LIQUID_COVERAGE_RANGE = + DF.register("liquid_coverage_range", LiquidCoverageRangeRequirement::new); + public static final DeferredHolder HAS_BIOLOGICAL_RESOURCES = + DF.register("has_biological_resources", HasBiologicalResourcesRequirement::new); + public static final DeferredHolder HAS_CIVILIZATION = + DF.register("has_civilization", HasCivilizationRequirement::new); + public static final DeferredHolder + HAS_OTHER_MEGASTRUCTURE = DF.register("has_other_megastructure", HasOtherMegastructureRequirement::new); + public static final DeferredHolder + NO_OTHER_MEGASTRUCTURE = DF.register("no_other_megastructure", NoOtherMegastructureRequirement::new); + + public static void register(IEventBus bus) { + DF.register(bus); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jade/AddonJadePlugin.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jade/AddonJadePlugin.java index 25b8f4fc..38e8fca4 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/integration/jade/AddonJadePlugin.java +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jade/AddonJadePlugin.java @@ -6,8 +6,10 @@ import dev.anvilcraft.pigsplus.block.entity.ElectricEnchantingTableBlockEntity; import dev.anvilcraft.pigsplus.block.entity.PecisionMagneticPivotBlockEntity; import dev.anvilcraft.pigsplus.integration.jade.provider.BrassSinkJadeProvider; +import dev.anvilcraft.pigsplus.integration.jade.provider.CelestialReformerJadeProvider; import dev.anvilcraft.pigsplus.integration.jade.provider.ElectricEnchantingTableProvider; import dev.anvilcraft.pigsplus.integration.jade.provider.PecisionMagneticPivotProvider; +import dev.dubhe.anvilcraft.block.cfa.CelestialForgingAnvilBlock; import snownee.jade.api.IWailaClientRegistration; import snownee.jade.api.IWailaCommonRegistration; import snownee.jade.api.IWailaPlugin; @@ -21,6 +23,7 @@ public void register(IWailaCommonRegistration registration) { // registration.registerItemStorage(CrabTrapStorageProvider.INSTANCE, CrabTrapBlockEntity.class); registration.registerBlockDataProvider(ElectricEnchantingTableProvider.INSTANCE, ElectricEnchantingTableBlockEntity.class); registration.registerBlockDataProvider(PecisionMagneticPivotProvider.INSTANCE, PecisionMagneticPivotBlockEntity.class); + registration.registerBlockDataProvider(CelestialReformerJadeProvider.INSTANCE, CelestialForgingAnvilBlock.class); } @Override @@ -29,5 +32,6 @@ public void registerClient(IWailaClientRegistration registration) { registration.registerBlockComponent(BrassSinkJadeProvider.INSTANCE, BrassSinkBlock.class); registration.registerBlockComponent(ElectricEnchantingTableProvider.INSTANCE, ElectricEnchantingTableBlock.class); registration.registerBlockComponent(PecisionMagneticPivotProvider.INSTANCE, PecisionMagneticPivotBlock.class); + registration.registerBlockComponent(CelestialReformerJadeProvider.INSTANCE, CelestialForgingAnvilBlock.class); } } diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jade/provider/CelestialReformerJadeProvider.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jade/provider/CelestialReformerJadeProvider.java new file mode 100644 index 00000000..4a091f6f --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jade/provider/CelestialReformerJadeProvider.java @@ -0,0 +1,280 @@ +package dev.anvilcraft.pigsplus.integration.jade.provider; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.requirement.RequirementEntry; +import dev.anvilcraft.pigsplus.api.requirement.ReformerRequirement; +import dev.anvilcraft.pigsplus.block.entity.megastructure.ReformerHandler; +import dev.anvilcraft.pigsplus.block.entity.megastructure.CelestialReformerInputChannel; +import dev.anvilcraft.pigsplus.block.entity.megastructure.CelestialReformerInputRequirement; +import dev.anvilcraft.pigsplus.client.jade.TextureElement; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe.LaserType; +import dev.anvilcraft.pigsplus.util.CelestialReformerHooks; +import dev.anvilcraft.pigsplus.util.ReformerIcons; +import dev.dubhe.anvilcraft.block.cfa.CelestialForgingAnvilBlock; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.megastructure.IMegastructureHandler; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import snownee.jade.api.BlockAccessor; +import snownee.jade.api.IBlockComponentProvider; +import snownee.jade.api.IServerDataProvider; +import snownee.jade.api.ITooltip; +import snownee.jade.api.config.IPluginConfig; +import snownee.jade.api.ui.BoxStyle; +import snownee.jade.api.ui.IElement; +import snownee.jade.api.ui.IElementHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public enum CelestialReformerJadeProvider implements IBlockComponentProvider, IServerDataProvider { + INSTANCE; + + private static final String DATA_MODIFICATION = "pigsplusModification"; + private static final String DATA_REQUIREMENT_ENTRIES = "pigsplusRequirementEntries"; + private static final String DATA_REQUIREMENTS = "pigsplusRequirements"; + private static final String DATA_REQUIREMENT_PROGRESS = "pigsplusRequirementProgress"; + + @Override + public void appendServerData(CompoundTag data, BlockAccessor accessor) { + try { + // 服务端把完整需求条目序列化进 NBT + CelestialForgingAnvilBlockEntity be = findController(accessor); + if (be == null) return; + ReformerHandler handler = getReformerHandler(be); + if (handler == null || !CelestialReformerHooks.isActive(be)) return; + ResourceLocation modification = handler.getActiveModification(be); + if (modification == null) return; + + data.putString(DATA_MODIFICATION, modification.toString()); + data.putIntArray(DATA_REQUIREMENT_PROGRESS, handler.getRequirementProgresses()); + + // RequirementEntry.CODEC 会保留参数化需求,例如 rotation_speed 的 min/max。 + ListTag requirementEntries = new ListTag(); + for (RequirementEntry entry : handler.getRequirementEntries(be)) { + Tag encoded = RequirementEntry.CODEC.encodeStart(NbtOps.INSTANCE, entry) + .result() + .orElseGet(CompoundTag::new); + requirementEntries.add(encoded); + } + data.put(DATA_REQUIREMENT_ENTRIES, requirementEntries); + + // 物品/流体/激光输入用于显示所有收集进度,和服务端需求条目分开传递。 + ListTag requirements = new ListTag(); + for (CelestialReformerInputRequirement requirement : handler.getInputRequirements(be)) { + CompoundTag entry = new CompoundTag(); + entry.putString("channel", requirement.channel().name()); + entry.putString("resource", requirement.resource().toString()); + entry.putInt("amount", requirement.amount()); + entry.putString( + "laserType", + requirement.laserType() == null ? "none" : requirement.laserType().getSerializedName() + ); + requirements.add(entry); + } + data.put(DATA_REQUIREMENTS, requirements); + } catch (RuntimeException | LinkageError ignored) { + } + } + + @Override + public boolean shouldRequestData(BlockAccessor accessor) { + return true; + } + + @Override + public void appendTooltip(ITooltip tooltip, BlockAccessor accessor, IPluginConfig config) { + try { + // 客户端只负责读取服务端已序列化的配方数据,并展示改造、需求与所有输入收集进度。 + CelestialForgingAnvilBlockEntity be = findController(accessor); + if (be == null) return; + ReformerHandler handler = getReformerHandler(be); + if (handler == null || !CelestialReformerHooks.isActive(be)) return; + + CompoundTag serverData = accessor.getServerData(); + if (!serverData.contains(DATA_MODIFICATION)) return; + ResourceLocation modification = ResourceLocation.tryParse(serverData.getString(DATA_MODIFICATION)); + List requirementEntries = readRequirementEntries( + serverData.getList(DATA_REQUIREMENT_ENTRIES, Tag.TAG_COMPOUND) + ); + List requirements = readRequirements(serverData.getList(DATA_REQUIREMENTS, Tag.TAG_COMPOUND)); + int[] requirementProgresses = serverData.getIntArray(DATA_REQUIREMENT_PROGRESS); + if (modification == null || requirements.isEmpty()) return; + + IElementHelper helper = IElementHelper.get(); + ReformerModification effect = ReformerModifications.REGISTRY.get(modification); + if (effect != null) { + tooltip.add(List.of( + new TextureElement( + effect.getIcon(), + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE + ), + helper.text(effect.getDescription()) + )); + } + List requirementIcons = new ArrayList<>(); + for (RequirementEntry entry : requirementEntries) { + ReformerRequirement requirement = entry.requirement(); + if (requirement != null) { + requirementIcons.add(new TextureElement( + ReformerIcons.requirementIcon(entry.id()), + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE + )); + } + } + for (CelestialReformerInputRequirement input : requirements) { + if (input.channel() == CelestialReformerInputChannel.LASER_INTERFACE) { + requirementIcons.add(new TextureElement( + ReformerIcons.laserIcon(), + ReformerIcons.ICON_SIZE, + ReformerIcons.ICON_SIZE + )); + } + } + if (!requirementIcons.isEmpty()) { + tooltip.add(requirementIcons); + } + + for (int i = 0; i < requirements.size(); i++) { + CelestialReformerInputRequirement requirement = requirements.get(i); + if (requirement.channel() == CelestialReformerInputChannel.LASER_INTERFACE) { + tooltip.add(Component.translatable( + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser", + requirement.amount(), + laserType(requirement.laserType()) + )); + continue; + } + int total = requirement.amount(); + if (total <= 0) continue; + int current = i < requirementProgresses.length ? requirementProgresses[i] : 0; + float percentage = (float) Math.min(current, total) / total; + tooltip.add(helper.progress( + percentage, + requirementText(requirement, current, total), + helper.progressStyle().color(0xFF4C6FDB, 0xFF86A8FF).textColor(0xFFFFFFFF), + BoxStyle.getNestedBox(), + true + )); + } + } catch (RuntimeException | LinkageError ignored) { + } + } + + private static @Nullable CelestialForgingAnvilBlockEntity findController(BlockAccessor accessor) { + // 多块结构的所有部件都会把主方块定位到锻星砧控制器。 + if (!(accessor.getBlockState().getBlock() instanceof CelestialForgingAnvilBlock block)) return null; + + BlockPos mainPos = block.getMainPartPos(accessor.getPosition(), accessor.getBlockState()); + BlockEntity main = accessor.getLevel().getBlockEntity(mainPos); + return main instanceof CelestialForgingAnvilBlockEntity controller ? controller : null; + } + + private static @Nullable ReformerHandler getReformerHandler(CelestialForgingAnvilBlockEntity be) { + // 只处理当前激活的巨构是行星/恒星改造器的情况。 + IMegastructureHandler active = be.getMegastructureManager().getActiveHandler(be); + return active instanceof ReformerHandler handler ? handler : null; + } + + @Override + public ResourceLocation getUid() { + return AnvilCraftPigsPlus.of("celestial_reformer"); + } + + private static Component requirementText( + CelestialReformerInputRequirement requirement, + int current, + int total + ) { + return switch (requirement.channel()) { + case LOGISTICS_ITEM -> { + var item = BuiltInRegistries.ITEM.get(requirement.resource()); + yield Component.translatable( + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.item", + new ItemStack(item).getHoverName(), + current, + total + ); + } + case FLUID_INTERFACE -> { + var fluid = BuiltInRegistries.FLUID.get(requirement.resource()); + yield Component.translatable( + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.fluid", + fluid.getFluidType().getDescription(), + current, + total + ); + } + case LASER_INTERFACE -> Component.translatable( + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser", + requirement.amount(), + laserType(requirement.laserType()) + ); + }; + } + + private static Component laserType(@Nullable LaserType type) { + String key; + if (type == null || type == LaserType.ANY) { + key = "gui.anvilcraft_pigsplus.laser.type.any"; + } else if (type == LaserType.GAMMA) { + key = "gui.anvilcraft_pigsplus.laser.type.gamma"; + } else { + key = "gui.anvilcraft_pigsplus.laser.type.normal"; + } + return Component.translatable(key); + } + + private static List readRequirements(ListTag list) { + // 这些是物品/流体/激光输入,用于展示所有收集进度条。 + List requirements = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + CompoundTag entry = list.getCompound(i); + CelestialReformerInputChannel channel = + CelestialReformerInputChannel.valueOf(entry.getString("channel")); + ResourceLocation resource = ResourceLocation.tryParse(entry.getString("resource")); + requirements.add(new CelestialReformerInputRequirement( + channel, + resource, + entry.getInt("amount"), + readLaserType(entry) + )); + } + return requirements; + } + + /** + * 从服务端 NBT 中恢复完整需求条目。 + * + *

这里的 CODEC 与配方数据包使用同一套逻辑,因此能还原带参数的 + * {@link dev.anvilcraft.pigsplus.api.requirement.RotationSpeedRequirement} 等需求对象。

+ */ + private static List readRequirementEntries(ListTag list) { + List entries = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + RequirementEntry.CODEC.parse(NbtOps.INSTANCE, list.get(i)) + .result() + .ifPresent(entries::add); + } + return entries; + } + + private static @Nullable LaserType readLaserType(CompoundTag entry) { + String type = entry.getString("laserType"); + if (type.isEmpty() || "none".equals(type)) return null; + return LaserType.fromName(type); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/AddonJeiPlugin.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/AddonJeiPlugin.java index 8aab74a2..819eaeac 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/AddonJeiPlugin.java +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/AddonJeiPlugin.java @@ -2,20 +2,37 @@ import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; import dev.anvilcraft.pigsplus.init.AddonItems; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.requirement.CelestialReformerRequirements; +import dev.anvilcraft.pigsplus.api.requirement.ReformerRequirement; import dev.anvilcraft.pigsplus.integration.jei.category.PrecisionElectromagneticProcessingCategory; +import dev.anvilcraft.pigsplus.integration.jei.category.CelestialReformerCategory; +import dev.anvilcraft.pigsplus.integration.jei.ingredient.ReformerConcept; +import dev.anvilcraft.pigsplus.integration.jei.ingredient.ReformerConceptHelper; +import dev.anvilcraft.pigsplus.integration.jei.ingredient.ReformerConceptRenderer; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; import dev.anvilcraft.pigsplus.recipe.PrecisionElectromagneticProcessingRecipe; +import dev.anvilcraft.pigsplus.util.ReformerIcons; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.helpers.IGuiHelper; import mezz.jei.api.helpers.IJeiHelpers; import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.registration.IModIngredientRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCategoryRegistration; import mezz.jei.api.registration.IRecipeRegistration; +import net.minecraft.resources.ResourceKey; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.crafting.RecipeHolder; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + import static dev.anvilcraft.pigsplus.item.KarakuriComponentItem.PROBABILITY; import static dev.anvilcraft.pigsplus.util.EnderComponentConversionUtil.ConversionChance; @@ -24,18 +41,32 @@ public class AddonJeiPlugin implements IModPlugin { public static final RecipeType> PRECISION_ELECTROMAGNETIC_PROCESSING = createRecipeHolderType("precision_electromagnetic_processing"); + public static final RecipeType> CELESTIAL_REFORMER = + createRecipeHolderType("celestial_reformer"); @Override public ResourceLocation getPluginUid() { return AnvilCraftPigsPlus.of("jei_plugin"); } + @Override + public void registerIngredients(IModIngredientRegistration registration) { + registration.register( + ReformerConcept.TYPE, + collectConcepts(), + new ReformerConceptHelper(), + new ReformerConceptRenderer(), + ReformerConcept.CODEC + ); + } + @Override public void registerCategories(IRecipeCategoryRegistration registration) { IJeiHelpers jeiHelpers = registration.getJeiHelpers(); IGuiHelper guiHelper = jeiHelpers.getGuiHelper(); registration.addRecipeCategories(new PrecisionElectromagneticProcessingCategory(guiHelper)); + registration.addRecipeCategories(new CelestialReformerCategory(guiHelper)); } @Override @@ -51,14 +82,29 @@ public void registerRecipes(IRecipeRegistration registration) { ); PrecisionElectromagneticProcessingCategory.registerRecipes(registration); + CelestialReformerCategory.registerRecipes(registration); } @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { PrecisionElectromagneticProcessingCategory.registerRecipeCatalysts(registration); + CelestialReformerCategory.registerRecipeCatalysts(registration); } private static > RecipeType> createRecipeHolderType(String name) { return RecipeType.createRecipeHolderType(AnvilCraftPigsPlus.of(name)); } + + private static Collection collectConcepts() { + Set icons = new LinkedHashSet<>(); + for (ReformerModification modification : ReformerModifications.REGISTRY) { + icons.add(modification.getIcon()); + } + for (Map.Entry, ReformerRequirement> entry + : CelestialReformerRequirements.REGISTRY.entrySet()) { + icons.add(ReformerIcons.requirementIcon(entry.getKey().location())); + } + icons.add(ReformerIcons.laserIcon()); + return icons.stream().map(ReformerConcept::new).toList(); + } } diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/category/CelestialReformerCategory.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/category/CelestialReformerCategory.java new file mode 100644 index 00000000..2f913faa --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/category/CelestialReformerCategory.java @@ -0,0 +1,246 @@ +package dev.anvilcraft.pigsplus.integration.jei.category; + +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.modification.ReformerModifications; +import dev.anvilcraft.pigsplus.api.requirement.RequirementEntry; +import dev.anvilcraft.pigsplus.init.AddonItems; +import dev.anvilcraft.pigsplus.init.AddonRecipeTypes; +import dev.anvilcraft.pigsplus.integration.jei.AddonJeiPlugin; +import dev.anvilcraft.pigsplus.integration.jei.ingredient.ReformerConcept; +import dev.anvilcraft.pigsplus.integration.jei.util.AddonJeiUtil; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe; +import dev.anvilcraft.pigsplus.recipe.CelestialReformerRecipe.LaserType; +import dev.anvilcraft.pigsplus.util.ReformerIcons; +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import dev.dubhe.anvilcraft.integration.jei.util.JeiRecipeUtil; +import dev.dubhe.anvilcraft.integration.jei.util.JeiRenderHelper; +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.drawable.IDrawable; +import mezz.jei.api.gui.ingredient.IRecipeSlotsView; +import mezz.jei.api.helpers.IGuiHelper; +import mezz.jei.api.recipe.IFocusGroup; +import mezz.jei.api.recipe.RecipeIngredientRole; +import mezz.jei.api.recipe.RecipeType; +import mezz.jei.api.recipe.category.IRecipeCategory; +import mezz.jei.api.registration.IRecipeCatalystRegistration; +import mezz.jei.api.registration.IRecipeRegistration; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; + +public class CelestialReformerCategory implements IRecipeCategory> { + private static final int WIDTH = 162; + private static final int HEIGHT = 64; + private static final int SLOT_SIZE = 18; + private static final int SLOT_SPACING = SLOT_SIZE + 1; + // 162px 宽度下可容纳 6 列槽位 + private static final int SLOTS_PER_ROW = 6; + + private final IDrawable icon; + private final IDrawable slotDefault; + private final IDrawable conceptSlot; + private final Component title; + + public CelestialReformerCategory(IGuiHelper helper) { + this.icon = helper.createDrawableItemLike(ModBlocks.CELESTIAL_FORGING_ANVIL.asItem()); + this.slotDefault = JeiRenderHelper.getSlotDefault(helper); + this.conceptSlot = helper.drawableBuilder( + ReformerIcons.SLOT_CONCEPT, + 0, + 0, + ReformerIcons.SLOT_SIZE, + ReformerIcons.SLOT_SIZE + ).setTextureSize(ReformerIcons.SLOT_SIZE, ReformerIcons.SLOT_SIZE).build(); + this.title = Component.translatable("gui.anvilcraft_pigsplus.category.celestial_reformer"); + } + + @Override + public RecipeType> getRecipeType() { + return AddonJeiPlugin.CELESTIAL_REFORMER; + } + + @Override + public Component getTitle() { + return title; + } + + @Override + public int getWidth() { + return WIDTH; + } + + @Override + public int getHeight() { + return HEIGHT; + } + + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public void setRecipe( + IRecipeLayoutBuilder builder, + RecipeHolder recipeHolder, + IFocusGroup focuses + ) { + CelestialReformerRecipe recipe = recipeHolder.value(); + int slotIndex = 0; + for (CelestialReformerRecipe.ItemInput input : recipe.items()) { + var item = BuiltInRegistries.ITEM.get(input.item()); + if (item == Items.AIR) continue; + AddonJeiUtil.addItemInputSlot( + builder, + getSlotX(slotIndex), + getSlotY(slotIndex), + item, + input.count() + ); + slotIndex++; + } + for (CelestialReformerRecipe.FluidInput input : recipe.fluids()) { + Fluid fluid = BuiltInRegistries.FLUID.get(input.fluid()); + if (fluid.isSame(Fluids.EMPTY)) continue; + AddonJeiUtil.addFluidInputSlot( + builder, + getSlotX(slotIndex), + getSlotY(slotIndex), + fluid, + input.amount() + ); + slotIndex++; + } + + int iconY = getIconsY(recipe); + int iconIndex = 0; + for (RequirementEntry entry : recipe.requirements()) { + var requirement = entry.requirement(); + if (requirement != null) { + this.addConceptSlot( + builder, + RecipeIngredientRole.INPUT, + new ReformerConcept(ReformerIcons.requirementIcon(entry.id())), + requirement.getDescription(), + getIconX(iconIndex), + iconY + ); + } + iconIndex++; + } + for (CelestialReformerRecipe.LaserInput laser : recipe.lasers()) { + this.addConceptSlot( + builder, + RecipeIngredientRole.INPUT, + new ReformerConcept(ReformerIcons.laserIcon()), + Component.translatable( + "gui.anvilcraft_pigsplus.jei.laser", + laser.level(), + laserType(laser.type()) + ), + getIconX(iconIndex), + iconY + ); + iconIndex++; + } + + ReformerModification modification = + ReformerModifications.REGISTRY.get(recipe.modification()); + ReformerConcept outputConcept = modification == null + ? new ReformerConcept(ReformerIcons.DEFAULT) + : new ReformerConcept(modification.getIcon()); + Component outputTooltip = modification == null + ? Component.translatable("modification.anvilcraft_pigsplus.unknown") + : modification.getDescription(); + this.addConceptSlot( + builder, + RecipeIngredientRole.OUTPUT, + outputConcept, + outputTooltip, + getModificationX(), + getSlotY(0) + ); + } + + @Override + public void draw( + RecipeHolder recipeHolder, + IRecipeSlotsView recipeSlotsView, + GuiGraphics guiGraphics, + double mouseX, + double mouseY + ) { + CelestialReformerRecipe recipe = recipeHolder.value(); + for (int i = 0; i < inputSlotCount(recipe); i++) { + slotDefault.draw(guiGraphics, getSlotX(i) - 1, getSlotY(i) - 1); + } + } + + public static void registerRecipes(IRecipeRegistration registration) { + registration.addRecipes( + AddonJeiPlugin.CELESTIAL_REFORMER, + JeiRecipeUtil.getRecipeHoldersFromType(AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get()) + ); + } + + public static void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { + registration.addRecipeCatalyst(ModBlocks.CELESTIAL_FORGING_ANVIL, AddonJeiPlugin.CELESTIAL_REFORMER); + registration.addRecipeCatalyst(ModBlocks.CELESTIAL_FORGING_ANVIL_LOGISTICS_INTERFACE, AddonJeiPlugin.CELESTIAL_REFORMER); + registration.addRecipeCatalyst(ModBlocks.CELESTIAL_FORGING_ANVIL_FLUID_INTERFACE, AddonJeiPlugin.CELESTIAL_REFORMER); + registration.addRecipeCatalyst(ModBlocks.CELESTIAL_FORGING_ANVIL_LASER_INTERFACE, AddonJeiPlugin.CELESTIAL_REFORMER); + registration.addRecipeCatalyst(ModBlocks.CELESTIAL_FORGING_ANVIL_AMPLIFIER, AddonJeiPlugin.CELESTIAL_REFORMER); + registration.addRecipeCatalyst(AddonItems.CELESTIAL_REFORMER_COMPONENT, AddonJeiPlugin.CELESTIAL_REFORMER); + } + + private static int getSlotX(int index) { + return 8 + (index % SLOTS_PER_ROW) * SLOT_SPACING; + } + + private static int getSlotY(int index) { + return 8 + (index / SLOTS_PER_ROW) * SLOT_SPACING; + } + + private static int getIconX(int index) { + return 8 + index * SLOT_SPACING; + } + + private static int getModificationX() { + return WIDTH - SLOT_SIZE; + } + + private static int getIconsY(CelestialReformerRecipe recipe) { + int rowCount = (inputSlotCount(recipe) + SLOTS_PER_ROW - 1) / SLOTS_PER_ROW; + return 8 + Math.max(1, rowCount) * SLOT_SPACING + 4; + } + + private void addConceptSlot( + IRecipeLayoutBuilder builder, + RecipeIngredientRole role, + ReformerConcept concept, + Component tooltip, + int x, + int y + ) { + builder.addSlot(role, x, y) + .setBackground(this.conceptSlot, -1, -1) + .addIngredient(ReformerConcept.TYPE, concept) + .addRichTooltipCallback((slotView, tooltipBuilder) -> tooltipBuilder.add(tooltip)); + } + + private static int inputSlotCount(CelestialReformerRecipe recipe) { + return recipe.items().size() + recipe.fluids().size(); + } + + private static Component laserType(LaserType type) { + String key = type == LaserType.ANY + ? "gui.anvilcraft_pigsplus.laser.type.any" + : type == LaserType.GAMMA + ? "gui.anvilcraft_pigsplus.laser.type.gamma" + : "gui.anvilcraft_pigsplus.laser.type.normal"; + return Component.translatable(key); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConcept.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConcept.java new file mode 100644 index 00000000..2f478dc4 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConcept.java @@ -0,0 +1,23 @@ +package dev.anvilcraft.pigsplus.integration.jei.ingredient; + +import com.mojang.serialization.Codec; +import mezz.jei.api.ingredients.IIngredientType; +import net.minecraft.resources.ResourceLocation; + +/** + * JEI 中表示天体改造需求/修改的概念 ingredient。 + */ +public record ReformerConcept(ResourceLocation icon) { + public static final IIngredientType TYPE = () -> ReformerConcept.class; + public static final Codec CODEC = + ResourceLocation.CODEC.xmap(ReformerConcept::new, ReformerConcept::icon); + + public String translationKey() { + String path = this.icon.getPath(); + String name = path.substring(path.lastIndexOf('/') + 1); + if (name.endsWith(".png")) { + name = name.substring(0, name.length() - 4); + } + return "concept.anvilcraft_pigsplus." + name; + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptHelper.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptHelper.java new file mode 100644 index 00000000..d4954ec8 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptHelper.java @@ -0,0 +1,41 @@ +package dev.anvilcraft.pigsplus.integration.jei.ingredient; + +import mezz.jei.api.ingredients.IIngredientHelper; +import mezz.jei.api.ingredients.IIngredientType; +import mezz.jei.api.ingredients.subtypes.UidContext; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; + +public class ReformerConceptHelper implements IIngredientHelper { + @Override + public IIngredientType getIngredientType() { + return ReformerConcept.TYPE; + } + + @Override + public String getDisplayName(ReformerConcept ingredient) { + return Component.translatable(ingredient.translationKey()).getString(); + } + + @Override + @SuppressWarnings("removal") + public String getUniqueId(ReformerConcept ingredient, UidContext context) { + return ingredient.icon().toString(); + } + + @Override + public ResourceLocation getResourceLocation(ReformerConcept ingredient) { + return ingredient.icon(); + } + + @Override + public ReformerConcept copyIngredient(ReformerConcept ingredient) { + return ingredient; + } + + @Override + public String getErrorInfo(@Nullable ReformerConcept ingredient) { + return ingredient == null ? "null" : ingredient.icon().toString(); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptRenderer.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptRenderer.java new file mode 100644 index 00000000..fa9ffc4e --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/ReformerConceptRenderer.java @@ -0,0 +1,30 @@ +package dev.anvilcraft.pigsplus.integration.jei.ingredient; + +import mezz.jei.api.ingredients.IIngredientRenderer; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.TooltipFlag; + +import java.util.List; + +public class ReformerConceptRenderer implements IIngredientRenderer { + @Override + public void render(GuiGraphics guiGraphics, ReformerConcept ingredient) { + guiGraphics.blit( + ingredient.icon(), + 0, + 0, + 0, + 0, + 16, + 16, + 16, + 16 + ); + } + + @Override + public List getTooltip(ReformerConcept ingredient, TooltipFlag tooltipFlag) { + return List.of(Component.translatable(ingredient.translationKey())); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/package-info.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/package-info.java new file mode 100644 index 00000000..11447b41 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/ingredient/package-info.java @@ -0,0 +1,3 @@ +@net.minecraft.MethodsReturnNonnullByDefault +@javax.annotation.ParametersAreNonnullByDefault +package dev.anvilcraft.pigsplus.integration.jei.ingredient; \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/integration/jei/util/AddonJeiUtil.java b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/util/AddonJeiUtil.java new file mode 100644 index 00000000..3f272aeb --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/integration/jei/util/AddonJeiUtil.java @@ -0,0 +1,53 @@ +package dev.anvilcraft.pigsplus.integration.jei.util; + +import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; +import mezz.jei.api.gui.builder.IRecipeSlotBuilder; +import mezz.jei.api.recipe.RecipeIngredientRole; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.material.Fluid; + +public final class AddonJeiUtil { + private AddonJeiUtil() { + } + + /** + * 添加带数量的物品输入格 + */ + public static IRecipeSlotBuilder addItemInputSlot( + IRecipeLayoutBuilder builder, + int x, + int y, + ItemStack stack + ) { + return builder.addSlot(RecipeIngredientRole.INPUT, x, y).addItemStack(stack); + } + + /** + * 添加带数量的物品输入格 + */ + public static IRecipeSlotBuilder addItemInputSlot( + IRecipeLayoutBuilder builder, + int x, + int y, + ItemLike item, + int count + ) { + return addItemInputSlot(builder, x, y, new ItemStack(item, count)); + } + + /** + * 添加带数量的流体输入格 + */ + public static IRecipeSlotBuilder addFluidInputSlot( + IRecipeLayoutBuilder builder, + int x, + int y, + Fluid fluid, + long amount + ) { + return builder.addSlot(RecipeIngredientRole.INPUT, x, y) + .setFluidRenderer(amount, false, 16, 16) + .addFluidStack(fluid, amount); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialForgingAnvilBlockEntityRendererMixin.java b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialForgingAnvilBlockEntityRendererMixin.java new file mode 100644 index 00000000..41f05793 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialForgingAnvilBlockEntityRendererMixin.java @@ -0,0 +1,74 @@ +package dev.anvilcraft.pigsplus.mixin.integration; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.block.entity.megastructure.StarReformerHandler; +import dev.anvilcraft.pigsplus.util.CelestialReformerHooks; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.client.renderer.blockentity.CelestialForgingAnvilBlockEntityRenderer; +import net.minecraft.client.resources.model.ModelResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(CelestialForgingAnvilBlockEntityRenderer.class) +public abstract class CelestialForgingAnvilBlockEntityRendererMixin { + @Unique + private static final ModelResourceLocation PLANETARY_REFORMER_MODEL = ModelResourceLocation.standalone( + AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_1_reformer") + ); + @Unique + private static final ModelResourceLocation STAR_REFORMER_MODEL = ModelResourceLocation.standalone( + AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_4_reformer") + ); + + @Inject(method = "getRing1Model", at = @At("HEAD"), cancellable = true) + private void replaceRing1Model( + CelestialForgingAnvilBlockEntity anvil, + CallbackInfoReturnable cir + ) { + anvilcraft_pigsplus$setReformerModel(anvil, cir, 1); + } + + @Inject(method = "getRing2Model", at = @At("HEAD"), cancellable = true) + private void replaceRing2Model( + CelestialForgingAnvilBlockEntity anvil, + CallbackInfoReturnable cir + ) { + anvilcraft_pigsplus$setReformerModel(anvil, cir, 2); + } + + @Inject(method = "getRing4Model", at = @At("HEAD"), cancellable = true) + private void replaceRing4Model( + CelestialForgingAnvilBlockEntity anvil, + CallbackInfoReturnable cir + ) { + anvilcraft_pigsplus$setReformerModel(anvil, cir, 4); + } + + @Inject(method = "getRing5Model", at = @At("HEAD"), cancellable = true) + private void replaceRing5Model( + CelestialForgingAnvilBlockEntity anvil, + CallbackInfoReturnable cir + ) { + anvilcraft_pigsplus$setReformerModel(anvil, cir, 5); + } + + @Unique + private static void anvilcraft_pigsplus$setReformerModel( + CelestialForgingAnvilBlockEntity anvil, + CallbackInfoReturnable cir, + int ring + ) { + if (CelestialReformerHooks.isActive(anvil, ring)) { + cir.setReturnValue(anvilcraft_pigsplus$isStarReformer(anvil) ? STAR_REFORMER_MODEL : PLANETARY_REFORMER_MODEL); + } + } + + @Unique + private static boolean anvilcraft_pigsplus$isStarReformer(CelestialForgingAnvilBlockEntity anvil) { + var option = anvil.getActiveMegastructureOption(); + return option != null && StarReformerHandler.NAME.equals(option.megastructure()); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialRefactorRegistryMixin.java b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialRefactorRegistryMixin.java new file mode 100644 index 00000000..207eae2f --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CelestialRefactorRegistryMixin.java @@ -0,0 +1,73 @@ +package dev.anvilcraft.pigsplus.mixin.integration; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.block.entity.megastructure.PlanetaryReformerHandler; +import dev.anvilcraft.pigsplus.block.entity.megastructure.StarReformerHandler; +import dev.anvilcraft.pigsplus.init.AddonItems; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialRefactorOption; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialRefactorRegistry; +import dev.dubhe.anvilcraft.block.entity.celestial.GiantPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.PlanetaryResourceSet; +import dev.dubhe.anvilcraft.block.entity.celestial.RockyPlanetData; +import dev.dubhe.anvilcraft.block.entity.celestial.SpecialCelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.StarData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.ArrayList; +import java.util.List; + +@Mixin(CelestialRefactorRegistry.class) +public abstract class CelestialRefactorRegistryMixin { + + @Inject(method = "getOptions", at = @At("RETURN"), cancellable = true) + private static void addPlanetaryReformer( + CelestialBodyData body, + boolean amplified, + PlanetaryResourceSet resources, + CallbackInfoReturnable> cir + ) { + try { + if (!anvilcraft_pigsplus$isPlanet(body) && !(body instanceof StarData)) return; + List original = cir.getReturnValue(); + if (original == null) return; + List options = new ArrayList<>(original); + if (options.stream().anyMatch(option -> PlanetaryReformerHandler.NAME.equals(option.megastructure()))) return; + + int ring = CelestialRefactorRegistry.getInnermostRing(body, amplified); + if (anvilcraft_pigsplus$isPlanet(body)) { + options.add(CelestialRefactorOption.withMaterial( + ring, + PlanetaryReformerHandler.NAME, + AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_1_reformer"), + "screen.anvilcraft.cfa.megastructure.planetary_reformer", + AddonItems.CELESTIAL_REFORMER_COMPONENT.asItem(), + 16 + )); + } else { + options.add(CelestialRefactorOption.withMaterial( + ring, + StarReformerHandler.NAME, + AnvilCraftPigsPlus.of("block/celestial_forging_anvil_ring_4_reformer"), + "screen.anvilcraft.cfa.megastructure.star_reformer", + AddonItems.CELESTIAL_REFORMER_COMPONENT.asItem(), + 64 + )); + } + cir.setReturnValue(options); + } catch (RuntimeException | LinkageError ex) { + AnvilCraftPigsPlus.LOGGER.warn("Failed to add planetary reformer option", ex); + } + } + + @Unique + private static boolean anvilcraft_pigsplus$isPlanet(CelestialBodyData body) { + return body instanceof RockyPlanetData + || body instanceof GiantPlanetData + || (body instanceof SpecialCelestialBodyData special && !special.isErrorPlanet()); + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CfaMegastructureManagerMixin.java b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CfaMegastructureManagerMixin.java new file mode 100644 index 00000000..868879d0 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/mixin/integration/CfaMegastructureManagerMixin.java @@ -0,0 +1,154 @@ +package dev.anvilcraft.pigsplus.mixin.integration; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.block.entity.megastructure.PlanetaryReformerHandler; +import dev.anvilcraft.pigsplus.block.entity.megastructure.ReformerHandler; +import dev.anvilcraft.pigsplus.block.entity.megastructure.StarReformerHandler; +import dev.dubhe.anvilcraft.block.entity.CfaMegastructureManager; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialRefactorOption; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialRefactorRegistry; +import dev.dubhe.anvilcraft.block.entity.megastructure.IMegastructureHandler; +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(CfaMegastructureManager.class) +public abstract class CfaMegastructureManagerMixin { + @Unique + private static final String ACTIVE_MEGASTRUCTURE_NAME_KEY = "pigsplusActiveMegastructure"; + + @Shadow + private int activeMegastructureIndex; + + // Base mod resolves active megastructures by list index, which shifts when options change. + @Unique + private @Nullable String anvilcraft_pigsplus$activeMegastructureName; + + @Shadow + private void registerHandler(IMegastructureHandler handler) { + } + + @Inject(method = "", at = @At("RETURN")) + private void addPlanetaryReformer(CallbackInfo ci) { + try { + this.registerHandler(new PlanetaryReformerHandler()); + this.registerHandler(new StarReformerHandler()); + } catch (RuntimeException | LinkageError ex) { + AnvilCraftPigsPlus.LOGGER.warn("Failed to register planetary reformer handler", ex); + } + } + + @Inject(method = "buildMegastructure", at = @At("HEAD")) + private void captureBuiltMegastructureName( + int index, + CelestialForgingAnvilBlockEntity be, + CallbackInfo ci + ) { + if (be.getCelestialBodyData() == null) return; + List options = be.getClientVisibleOptions(); + if (index < 0 || index >= options.size()) return; + + CelestialRefactorOption option = options.get(index); + if ("stellar_evolution_accelerator".equals(option.megastructure())) return; + if (this.activeMegastructureIndex >= 0) return; + this.anvilcraft_pigsplus$activeMegastructureName = option.megastructure(); + } + + @Inject(method = "getActiveOption", at = @At("HEAD"), cancellable = true) + private void resolveActiveOptionByStableName( + CelestialForgingAnvilBlockEntity be, + CallbackInfoReturnable cir + ) { + String name = this.anvilcraft_pigsplus$activeMegastructureName; + if (name == null || name.isBlank()) return; + if (this.activeMegastructureIndex < 0 || be.getCelestialBodyData() == null) { + cir.setReturnValue(null); + return; + } + + List options = CelestialRefactorRegistry.getOptions( + be.getCelestialBodyData(), + be.isAmplify(), + be.getPlanetaryResourceSet() + ); + for (int i = 0; i < options.size(); i++) { + if (name.equals(options.get(i).megastructure())) { + this.activeMegastructureIndex = i; + cir.setReturnValue(options.get(i)); + return; + } + } + cir.setReturnValue(null); + } + + @Inject(method = "clearMegastructure", at = @At("TAIL")) + private void clearActiveMegastructureName(CelestialForgingAnvilBlockEntity be, CallbackInfo ci) { + this.anvilcraft_pigsplus$activeMegastructureName = null; + } + + @Inject(method = "saveAdditional", at = @At("TAIL")) + private void saveActiveMegastructureName( + CompoundTag tag, + HolderLookup.Provider registries, + CallbackInfo ci + ) { + this.anvilcraft_pigsplus$writeActiveMegastructureName(tag); + } + + @Inject(method = "loadAdditional", at = @At("TAIL")) + private void loadActiveMegastructureName( + CompoundTag tag, + HolderLookup.Provider registries, + CallbackInfo ci + ) { + this.anvilcraft_pigsplus$readActiveMegastructureName(tag); + } + + @Inject(method = "writeUpdateTag", at = @At("TAIL")) + private void writeActiveMegastructureName( + CompoundTag tag, + HolderLookup.Provider registries, + CallbackInfo ci + ) { + this.anvilcraft_pigsplus$writeActiveMegastructureName(tag); + } + + @Inject(method = "readUpdateTag", at = @At("TAIL")) + private void readActiveMegastructureName( + CompoundTag tag, + HolderLookup.Provider registries, + CallbackInfo ci + ) { + this.anvilcraft_pigsplus$readActiveMegastructureName(tag); + } + + @Unique + private void anvilcraft_pigsplus$writeActiveMegastructureName(CompoundTag tag) { + String name = this.anvilcraft_pigsplus$activeMegastructureName; + tag.putString(ACTIVE_MEGASTRUCTURE_NAME_KEY, name == null ? "" : name); + } + + @Unique + private void anvilcraft_pigsplus$readActiveMegastructureName(CompoundTag tag) { + String name = tag.getString(ACTIVE_MEGASTRUCTURE_NAME_KEY); + this.anvilcraft_pigsplus$activeMegastructureName = name.isEmpty() ? null : name; + } + + @Inject(method = "syncLaserRequirements", at = @At("TAIL")) + private void syncPlanetaryReformerLaserRequirements(CelestialForgingAnvilBlockEntity anvil, CallbackInfo ci) { + IMegastructureHandler active = ((CfaMegastructureManager) (Object) this).getActiveHandler(anvil); + if (active instanceof ReformerHandler handler) { + handler.syncLaserRequirements(anvil); + } + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/network/CelestialReformerSyncPacket.java b/src/main/java/dev/anvilcraft/pigsplus/network/CelestialReformerSyncPacket.java new file mode 100644 index 00000000..6432c3e6 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/network/CelestialReformerSyncPacket.java @@ -0,0 +1,43 @@ +package dev.anvilcraft.pigsplus.network; + +import dev.anvilcraft.lib.v2.network.packet.IClientboundPacket; +import dev.anvilcraft.lib.v2.network.packet.IPacket; +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.block.entity.megastructure.ReformerHandler; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.megastructure.IMegastructureHandler; +import io.netty.buffer.ByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.block.entity.BlockEntity; + +public record CelestialReformerSyncPacket(BlockPos pos, CompoundTag tag) implements IClientboundPacket { + public static final Type TYPE = + IPacket.type(AnvilCraftPigsPlus.of("celestial_reformer_sync")); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, + CelestialReformerSyncPacket::pos, + ByteBufCodecs.COMPOUND_TAG, + CelestialReformerSyncPacket::tag, + CelestialReformerSyncPacket::new + ); + + @Override + public Type type() { + return TYPE; + } + + @Override + public void handleOnClient(Player player) { + BlockEntity be = player.level().getBlockEntity(this.pos); + if (be instanceof CelestialForgingAnvilBlockEntity anvil) { + IMegastructureHandler active = anvil.getMegastructureManager().getActiveHandler(anvil); + if (active instanceof ReformerHandler handler) { + handler.readUpdateTag(this.tag, player.level().registryAccess()); + } + } + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/recipe/CelestialReformerRecipe.java b/src/main/java/dev/anvilcraft/pigsplus/recipe/CelestialReformerRecipe.java new file mode 100644 index 00000000..cf5dfad7 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/recipe/CelestialReformerRecipe.java @@ -0,0 +1,300 @@ +package dev.anvilcraft.pigsplus.recipe; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.anvilcraft.pigsplus.api.modification.ReformerModification; +import dev.anvilcraft.pigsplus.api.requirement.CelestialReformerRequirements; +import dev.anvilcraft.pigsplus.api.requirement.RequirementEntry; +import dev.anvilcraft.pigsplus.api.requirement.ReformerRequirement; +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import dev.anvilcraft.pigsplus.init.AddonRecipeTypes; +import dev.dubhe.anvilcraft.recipe.anvil.builder.AbstractRecipeBuilder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeInput; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; +import net.minecraft.util.StringRepresentable; +import net.neoforged.neoforge.registries.DeferredHolder; + +import java.util.List; +import java.util.ArrayList; + +public record CelestialReformerRecipe( + ResourceLocation modification, + List requirements, + List items, + List fluids, + List lasers +) implements Recipe { + + @Override + public boolean matches(Input input, Level level) { + return true; + } + + @Override + public ItemStack assemble(Input input, HolderLookup.Provider registries) { + return ItemStack.EMPTY; + } + + @Override + public boolean canCraftInDimensions(int width, int height) { + return true; + } + + @Override + public ItemStack getResultItem(HolderLookup.Provider registries) { + return ItemStack.EMPTY; + } + + @Override + public RecipeSerializer getSerializer() { + return AddonRecipeTypes.CELESTIAL_REFORMER_SERIALIZER.get(); + } + + @Override + public RecipeType getType() { + return AddonRecipeTypes.CELESTIAL_REFORMER_TYPE.get(); + } + + @Override + public boolean isSpecial() { + return true; + } + + public record Input() implements RecipeInput { + @Override + public ItemStack getItem(int index) { + return ItemStack.EMPTY; + } + + @Override + public int size() { + return 0; + } + } + + public record ItemInput(ResourceLocation item, int count) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ResourceLocation.CODEC.fieldOf("item").forGetter(ItemInput::item), + Codec.intRange(1, Integer.MAX_VALUE).optionalFieldOf("count", 1).forGetter(ItemInput::count) + ).apply(instance, ItemInput::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ResourceLocation.STREAM_CODEC, ItemInput::item, + ByteBufCodecs.INT, ItemInput::count, + ItemInput::new + ); + } + + public record FluidInput(ResourceLocation fluid, int amount) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ResourceLocation.CODEC.fieldOf("fluid").forGetter(FluidInput::fluid), + Codec.intRange(1, Integer.MAX_VALUE).optionalFieldOf("amount", 1000).forGetter(FluidInput::amount) + ).apply(instance, FluidInput::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ResourceLocation.STREAM_CODEC, FluidInput::fluid, + ByteBufCodecs.INT, FluidInput::amount, + FluidInput::new + ); + } + + public enum LaserType implements StringRepresentable { + NORMAL("normal"), + GAMMA("gamma"), + ANY("any"); + + public static final Codec CODEC = Codec.STRING.xmap( + LaserType::fromName, + LaserType::getSerializedName + ); + + private final String name; + + LaserType(String name) { + this.name = name; + } + + public static LaserType fromName(String name) { + return switch (name) { + case "normal" -> NORMAL; + case "gamma" -> GAMMA; + case "any" -> ANY; + default -> throw new IllegalArgumentException("Unknown laser type: " + name); + }; + } + + @Override + public String getSerializedName() { + return this.name; + } + } + + public record LaserInput(int level, LaserType type) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + Codec.intRange(1, Integer.MAX_VALUE).fieldOf("level").forGetter(LaserInput::level), + LaserType.CODEC.fieldOf("type").forGetter(LaserInput::type) + ).apply(instance, LaserInput::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.INT, LaserInput::level, + ByteBufCodecs.STRING_UTF8.map(LaserType::fromName, LaserType::getSerializedName), + LaserInput::type, + LaserInput::new + ); + } + + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ResourceLocation.CODEC.fieldOf("modification").forGetter(CelestialReformerRecipe::modification), + RequirementEntry.CODEC.listOf().optionalFieldOf("requirements", List.of()) + .forGetter(CelestialReformerRecipe::requirements), + ItemInput.CODEC.codec().listOf().optionalFieldOf("items", List.of()).forGetter(CelestialReformerRecipe::items), + FluidInput.CODEC.codec().listOf().optionalFieldOf("fluids", List.of()).forGetter(CelestialReformerRecipe::fluids), + LaserInput.CODEC.codec().listOf().optionalFieldOf("lasers", List.of()).forGetter(CelestialReformerRecipe::lasers) + ).apply(instance, CelestialReformerRecipe::new)); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ResourceLocation.STREAM_CODEC, CelestialReformerRecipe::modification, + RequirementEntry.STREAM_CODEC.apply(ByteBufCodecs.list()), CelestialReformerRecipe::requirements, + ItemInput.STREAM_CODEC.apply(ByteBufCodecs.list()), CelestialReformerRecipe::items, + FluidInput.STREAM_CODEC.apply(ByteBufCodecs.list()), CelestialReformerRecipe::fluids, + LaserInput.STREAM_CODEC.apply(ByteBufCodecs.list()), CelestialReformerRecipe::lasers, + CelestialReformerRecipe::new + ); + + public static class Serializer implements RecipeSerializer { + @Override + public MapCodec codec() { + return CODEC; + } + + @Override + public StreamCodec streamCodec() { + return STREAM_CODEC; + } + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder extends AbstractRecipeBuilder { + private ResourceLocation modification; + private final List requirements = new ArrayList<>(); + private final List items = new ArrayList<>(); + private final List fluids = new ArrayList<>(); + private final List lasers = new ArrayList<>(); + + public Builder modification(ResourceLocation modification) { + this.modification = modification; + return this; + } + + public Builder modification(String modification) { + this.modification = ResourceLocation.parse(modification); + return this; + } + + public Builder modification(DeferredHolder modification) { + return modification(modification.getId()); + } + + public Builder requirement(ResourceLocation requirement) { + requirements.add(new RequirementEntry( + requirement, + CelestialReformerRequirements.REGISTRY.get(requirement) + )); + return this; + } + + public Builder requirement(String requirement) { + return requirement(ResourceLocation.parse(requirement)); + } + + public Builder requirement(DeferredHolder requirement) { + return requirement(requirement.getId()); + } + + public Builder requirement(DeferredHolder holder, ReformerRequirement requirement) { + requirements.add(new RequirementEntry(holder.getId(), requirement)); + return this; + } + + public Builder item(ItemLike item, int count) { + items.add(new ItemInput(BuiltInRegistries.ITEM.getKey(item.asItem()), count)); + return this; + } + + public Builder item(ResourceLocation item, int count) { + items.add(new ItemInput(item, count)); + return this; + } + + public Builder fluid(ResourceLocation fluid, int amount) { + fluids.add(new FluidInput(fluid, amount)); + return this; + } + + public Builder laser(int level) { + lasers.add(new LaserInput(level, LaserType.ANY)); + return this; + } + + public Builder laser(int level, boolean gamma) { + lasers.add(new LaserInput(level, gamma ? LaserType.GAMMA : LaserType.NORMAL)); + return this; + } + + public Builder laser(int level, LaserType type) { + lasers.add(new LaserInput(level, type)); + return this; + } + + @Override + public CelestialReformerRecipe buildRecipe() { + return new CelestialReformerRecipe(modification, requirements, items, fluids, lasers); + } + + @Override + public void validate(ResourceLocation id) { + if (modification == null) { + throw new IllegalArgumentException("Modification must not be null, RecipeId: " + id); + } + if (items.isEmpty() && fluids.isEmpty() && lasers.isEmpty()) { + throw new IllegalArgumentException("Recipe inputs must not be empty, RecipeId: " + id); + } + } + + @Override + public String getType() { + return "celestial_reformer"; + } + + @Override + public Item getResult() { + if (!items.isEmpty()) { + return BuiltInRegistries.ITEM.get(items.getFirst().item()); + } + return Items.AIR; + } + + @Override + public void save(RecipeOutput output, String id) { + save(output, AnvilCraftPigsPlus.of("celestial_reformer/" + id)); + } + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerHooks.java b/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerHooks.java new file mode 100644 index 00000000..635db08f --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerHooks.java @@ -0,0 +1,23 @@ +package dev.anvilcraft.pigsplus.util; + +import dev.anvilcraft.pigsplus.block.entity.megastructure.PlanetaryReformerHandler; +import dev.anvilcraft.pigsplus.block.entity.megastructure.StarReformerHandler; +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; + +public final class CelestialReformerHooks { + private CelestialReformerHooks() { + } + + public static boolean isActive(CelestialForgingAnvilBlockEntity cfa) { + return isActive(cfa, -1); + } + + public static boolean isActive(CelestialForgingAnvilBlockEntity cfa, int ring) { + var option = cfa.getActiveMegastructureOption(); + String name = option == null ? null : option.megastructure(); + return option != null + && (PlanetaryReformerHandler.NAME.equals(name) || StarReformerHandler.NAME.equals(name)) + && (ring < 0 || option.ring() == ring); + } + +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerPlanetUtil.java b/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerPlanetUtil.java new file mode 100644 index 00000000..6df79227 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/util/CelestialReformerPlanetUtil.java @@ -0,0 +1,146 @@ +package dev.anvilcraft.pigsplus.util; + +import dev.dubhe.anvilcraft.block.entity.CelestialForgingAnvilBlockEntity; +import dev.dubhe.anvilcraft.block.entity.celestial.CelestialBodyData; +import dev.dubhe.anvilcraft.block.entity.celestial.PlanetResourceGenerator; +import dev.dubhe.anvilcraft.block.entity.celestial.PlanetaryResourceSet; +import dev.dubhe.anvilcraft.block.entity.celestial.PlanetaryResourceSet.WeightedItemStack; +import net.minecraft.resources.ResourceLocation; + +import java.lang.reflect.Method; +import java.util.List; + +/** + * 行星资源生成的共用工具,优先复用铁砧工艺本体的资源生成逻辑。 + */ +public final class CelestialReformerPlanetUtil { + private CelestialReformerPlanetUtil() { + } + + /** + * 更新天体参数,并按照本体规则重新生成资源集。 + */ + public static void regenerate(CelestialForgingAnvilBlockEntity be, CelestialBodyData body) { + PlanetaryResourceSet resources = generate(be, body); + be.setCelestialBodyData(body); + be.setPlanetaryResourceSet(resources); + be.setChanged(); + } + + /** + * 清除原有生物资源,并按本体逻辑重新随机生成一份生物资源。 + */ + public static void addBiologicalResources(CelestialForgingAnvilBlockEntity be) { + CelestialBodyData body = be.getCelestialBodyData(); + if (body == null || be.getLevel() == null) return; + long randomOffset = be.getLevel().getRandom().nextLong(); + PlanetaryResourceSet generated = null; + for (int i = 0; i < 64; i++) { + PlanetaryResourceSet candidate = generate(be, body, randomOffset + i); + if (!candidate.getBiologicalItems().isEmpty() || !candidate.getBiologicalFluids().isEmpty()) { + generated = candidate; + break; + } + } + if (generated == null) { + generated = generate(be, body, randomOffset); + } + PlanetaryResourceSet resources = ensureResources(be); + listField(resources, "biologicalItems").addAll(generated.getBiologicalItems()); + listField(resources, "biologicalFluids").addAll(generated.getBiologicalFluids()); + be.setPlanetaryResourceSet(resources); + be.setChanged(); + } + + /** + * 添加低等文明,并清空生物资源。 + */ + public static void addCivilization(CelestialForgingAnvilBlockEntity be) { + PlanetaryResourceSet resources = ensureResources(be); + listField(resources, "biologicalItems").clear(); + listField(resources, "biologicalFluids").clear(); + invokeVoid(resources, "setHasCivilization"); + be.setChanged(); + } + + /** + * 转为废土世界;虚空废土使用虚空物质替换粗铀与钚粒。 + */ + public static void setWasteland(CelestialForgingAnvilBlockEntity be, boolean voidWasteland) { + PlanetaryResourceSet resources = ensureResources(be); + listField(resources, "biologicalItems").clear(); + listField(resources, "biologicalFluids").clear(); + listField(resources, "offerings").clear(); + listField(resources, "wastelandItems").clear(); + invokeVoid(resources, "setWasteland"); + + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:reinforced_concrete_gray"), 60)); + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:circuit_board"), 30)); + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:processor"), 5)); + if (voidWasteland) { + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:void_matter"), 5)); + } else { + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:raw_uranium"), 3)); + invokeAdd(resources, "addWastelandItem", new WeightedItemStack(ResourceLocation.parse("anvilcraft:plutonium_nugget"), 2)); + } + be.setChanged(); + } + + private static PlanetaryResourceSet generate(CelestialForgingAnvilBlockEntity be, CelestialBodyData body) { + return generate(be, body, 0); + } + + private static PlanetaryResourceSet generate( + CelestialForgingAnvilBlockEntity be, + CelestialBodyData body, + long seedOffset + ) { + return PlanetResourceGenerator.generate( + body, + be.getAgeAnvilCount(), + be.getLevel(), + be.getBodySeed() + seedOffset, + null + ); + } + + private static PlanetaryResourceSet ensureResources(CelestialForgingAnvilBlockEntity be) { + PlanetaryResourceSet resources = be.getPlanetaryResourceSet(); + if (resources == null) { + resources = new PlanetaryResourceSet(); + be.setPlanetaryResourceSet(resources); + } + return resources; + } + + private static void invokeVoid(PlanetaryResourceSet resources, String methodName) { + try { + Method method = PlanetaryResourceSet.class.getDeclaredMethod(methodName); + method.setAccessible(true); + method.invoke(resources); + } catch (ReflectiveOperationException ex) { + throw new IllegalStateException("Failed to modify planetary resource set", ex); + } + } + + @SuppressWarnings("unchecked") + private static List listField(PlanetaryResourceSet resources, String fieldName) { + try { + var field = PlanetaryResourceSet.class.getDeclaredField(fieldName); + field.setAccessible(true); + return (List) field.get(resources); + } catch (ReflectiveOperationException ex) { + throw new IllegalStateException("Failed to modify planetary resource set", ex); + } + } + + private static void invokeAdd(PlanetaryResourceSet resources, String methodName, Object value) { + try { + Method method = PlanetaryResourceSet.class.getDeclaredMethod(methodName, value.getClass()); + method.setAccessible(true); + method.invoke(resources, value); + } catch (ReflectiveOperationException ex) { + throw new IllegalStateException("Failed to modify planetary resource set", ex); + } + } +} diff --git a/src/main/java/dev/anvilcraft/pigsplus/util/ReformerIcons.java b/src/main/java/dev/anvilcraft/pigsplus/util/ReformerIcons.java new file mode 100644 index 00000000..051959bb --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/util/ReformerIcons.java @@ -0,0 +1,50 @@ +package dev.anvilcraft.pigsplus.util; + +import dev.anvilcraft.pigsplus.AnvilCraftPigsPlus; +import net.minecraft.resources.ResourceLocation; + +/** + * 天体改造图标与槽位的统一资源定位。 + */ +public final class ReformerIcons { + public static final int ICON_SIZE = 16; + public static final int SLOT_SIZE = 18; + + public static final ResourceLocation SLOT_CONCEPT = + AnvilCraftPigsPlus.of("textures/gui/reformer/slot/concept_slot.png"); + public static final ResourceLocation DEFAULT = + AnvilCraftPigsPlus.of("textures/gui/reformer/default.png"); + + private ReformerIcons() { + } + + public static ResourceLocation requirementIcon(ResourceLocation id) { + return icon(id); + } + + public static ResourceLocation laserIcon() { + return AnvilCraftPigsPlus.of("textures/gui/reformer/laser.png"); + } + + private static ResourceLocation icon(ResourceLocation id) { + String name = switch (id.getPath()) { + case "fast_rotation", "slow_rotation", "star_fast_rotation", "star_slow_rotation", "rotation_speed" -> + "rotation_speed"; + case "strengthen_magnetic_field", "weaken_magnetic_field", + "star_strengthen_magnetic_field", "star_weaken_magnetic_field", "magnetic_field" -> + "magnetic_field"; + case "increase_liquid_coverage", "decrease_liquid_coverage", "has_liquid", "no_liquid", + "water_ocean", "liquid_coverage_range" -> + "sea"; + case "increase_temperature", "decrease_temperature", "temperature_range" -> "temperature"; + case "add_atmosphere", "has_atmosphere", "no_atmosphere" -> "atmosphere"; + case "add_biological_resources", "has_biological_resources" -> "biologic"; + case "add_civilization", "has_civilization" -> "civilization"; + case "planetary_reformer", "star_reformer" -> "reformer"; + case "rocky_planet" -> "plante_type"; + case "laser" -> "laser"; + default -> "default"; + }; + return AnvilCraftPigsPlus.of("textures/gui/reformer/" + name + ".png"); + } +} diff --git a/src/main/resources/anvilcraft_pigsplus.integration.mixins.json b/src/main/resources/anvilcraft_pigsplus.integration.mixins.json new file mode 100644 index 00000000..ba402b17 --- /dev/null +++ b/src/main/resources/anvilcraft_pigsplus.integration.mixins.json @@ -0,0 +1,19 @@ +{ + "required": false, + "minVersion": "0.8", + "package": "dev.anvilcraft.pigsplus.mixin.integration", + "compatibilityLevel": "JAVA_21", + "mixins": [ + "CelestialRefactorRegistryMixin", + "CfaMegastructureManagerMixin" + ], + "client": [ + "CelestialForgingAnvilBlockEntityRendererMixin" + ], + "injectors": { + "defaultRequire": 0 + }, + "overwrites": { + "requireAnnotations": true + } +} diff --git a/src/main/resources/anvilcraft_pigsplus.mixins.json b/src/main/resources/anvilcraft_pigsplus.mixins.json index 3e552d02..ab7a30a8 100644 --- a/src/main/resources/anvilcraft_pigsplus.mixins.json +++ b/src/main/resources/anvilcraft_pigsplus.mixins.json @@ -7,8 +7,6 @@ "EntityMixin", "PistonStructureResolverMixin" ], - "client": [ - ], "injectors": { "defaultRequire": 1 }, diff --git a/src/main/resources/assets/anvilcraft/ageratum/zh_cn/100_pigsplus_automation_components/332_planetary_reformer.md b/src/main/resources/assets/anvilcraft/ageratum/zh_cn/100_pigsplus_automation_components/332_planetary_reformer.md new file mode 100644 index 00000000..8386bac6 --- /dev/null +++ b/src/main/resources/assets/anvilcraft/ageratum/zh_cn/100_pigsplus_automation_components/332_planetary_reformer.md @@ -0,0 +1,56 @@ +--- +navigation: + title: "§5天体改造" + icon: "anvilcraft_pigsplus:celestial_reformer_component" +items: + - anvilcraft_pigsplus:celestial_reformer_component +--- + +# + + + +# 行星改造器 + +- 建造需要消耗 **16 个天体改造器部件** +- 只能在岩石行星、巨行星等行星类天体上建造 + +# 恒星改造器 + +- 恒星天体可以建造**恒星改造器** +- 建造需要消耗 **64 个天体改造器部件** + +# 改造方式 + +将对应材料放入锻星砧物流接口后,行星改造器会自动选择满足条件的配方: + +- 如果正在执行的配方材料仍然存在,则继续执行当前改造 +- 如果当前配方材料消失,但出现了其他配方材料且完全满足其他配方,则重置进度并切换改造 +- 每次吸收会一次性取走接口内所有对应材料;单次吸收间隔可以通过配置项更改 + +# 内置配方 + + + + + + + + + + + + + +其他附属模组可以注册新的行星改造效果: + +1. 继承 `ReformerModification` +2. 在 `ReformerModifications.REGISTRY` 上使用 `DeferredRegister` 注册 +3. 在数据包中新增 `anvilcraft_pigsplus:celestial_reformer` 配方,将 `modification` 指向注册的效果 id +4. 配方可以附带多个 `langs` 翻译键,JEI 与 Jade 会通过翻译键显示改造内容 + +配方还可以通过`requirements`添加需求条目,例如限制行星/恒星改造器、天体环境、转速、磁场或巨构状态 + +需求条目同样通过注册表扩展 + + diff --git a/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json b/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json index e5f01421..513aea84 100644 --- a/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json +++ b/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json @@ -24,6 +24,8 @@ "anvilcraft_pigsplus.configuration.enchanted_generator.tooltip": "附魔发电机", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion": "Portable Wireless Charger Energy Conversion (kW)", "anvilcraft_pigsplus.configuration.portable_wireless_charger_energy_conversion.tooltip": "便携无线充电器的能量转换量", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown": "改造器吸收间隔", + "anvilcraft_pigsplus.configuration.reformer_absorption_cooldown.tooltip": "行星/恒星改造器的吸收间隔(tick)", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "铁砧工艺:猪+ 服务端配置", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "铁砧工艺:猪+ 服务端配置", "anvilcraft_pigsplus.configuration.title": "铁砧工艺:猪+ 配置", @@ -57,12 +59,22 @@ "block.anvilcraft_pigsplus.weak_resin_block": "虚弱树脂块", "config.jade.plugin_anvilcraft_pigsplus.electric_enchanting_table": "电力附魔台", "config.jade.plugin_anvilcraft_pigsplus.enchanted_generator": "附魔发电机", + "config.jade.plugin_anvilcraft_pigsplus.celestial_reformer": "天体改造器", "config.jade.plugin_anvilcraft_pigsplus.precision_magnetic_pivot": "精密磁枢", + "enchantment.anvilcraft_pigsplus.endurance": "耐力", + "gui.anvilcraft_pigsplus.category.celestial_reformer": "天体改造器", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing": "精密电磁加工", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.consume_fluid": "消耗:%1$d mB 的 %2$s", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.need_activated": "需要激活的", "gui.anvilcraft_pigsplus.category.precision_electromagnetic_processing.produce_fluid": "产出:%1$d mB 的 %2$s", + "gui.anvilcraft_pigsplus.jei.fluid": "流体:%s:%s mB", + "gui.anvilcraft_pigsplus.jei.laser": "激光:等级 %s(%s)", + "gui.anvilcraft_pigsplus.jei.modification": "修改:%s", + "gui.anvilcraft_pigsplus.laser.type.any": "任意激光", + "gui.anvilcraft_pigsplus.laser.type.gamma": "伽马激光", + "gui.anvilcraft_pigsplus.laser.type.normal": "普通激光", "item.anvilcraft_pigsplus.chaotic_raw_ore": "混沌粗矿", + "item.anvilcraft_pigsplus.celestial_reformer_component": "天体改造器部件", "item.anvilcraft_pigsplus.echo_geode": "回响晶洞", "item.anvilcraft_pigsplus.ender_component": "末影部件", "item.anvilcraft_pigsplus.karakuri_component": "机巧部件", @@ -75,8 +87,65 @@ "itemGroup.anvilcraft_pigsplus.addon_items": "铁砧工艺:猪+", "jei.anvilcraft.pigsplus.info.ender_component": "将机巧部件丢入末地传送门,有%.0f%%概率获得", "jei.anvilcraft.pigsplus.info.spiritual_component": "携带附魔的机巧部件被摧毁时,每条附魔提供%.0f%%的概率,生成最多一个灵媒部件", + "modification.anvilcraft_pigsplus.fast_rotation": "加快转速", + "modification.anvilcraft_pigsplus.add_biological_resources": "添加生物资源", + "modification.anvilcraft_pigsplus.add_civilization": "添加低等文明", + "modification.anvilcraft_pigsplus.add_atmosphere": "添加大气层", + "modification.anvilcraft_pigsplus.decrease_liquid_coverage": "降低海洋覆盖度", + "modification.anvilcraft_pigsplus.decrease_temperature": "降低温度", + "modification.anvilcraft_pigsplus.increase_liquid_coverage": "提升海洋覆盖度", + "modification.anvilcraft_pigsplus.increase_temperature": "提升温度", + "modification.anvilcraft_pigsplus.slow_rotation": "减慢转速", + "modification.anvilcraft_pigsplus.strengthen_magnetic_field": "增强磁场", + "modification.anvilcraft_pigsplus.unknown": "未知改造", + "modification.anvilcraft_pigsplus.void_wasteland": "变为虚空废土世界", + "modification.anvilcraft_pigsplus.wasteland": "变为废土世界", + "modification.anvilcraft_pigsplus.weaken_magnetic_field": "减弱磁场", + "concept.anvilcraft_pigsplus.rotation_speed": "旋转速度", + "concept.anvilcraft_pigsplus.magnetic_field": "磁场", + "concept.anvilcraft_pigsplus.sea": "液体覆盖", + "concept.anvilcraft_pigsplus.temperature": "温度", + "concept.anvilcraft_pigsplus.atmosphere": "大气层", + "concept.anvilcraft_pigsplus.biologic": "生物资源", + "concept.anvilcraft_pigsplus.civilization": "文明", + "concept.anvilcraft_pigsplus.plante_type": "行星类型", + "concept.anvilcraft_pigsplus.reformer": "改造器", + "concept.anvilcraft_pigsplus.laser": "激光", + "concept.anvilcraft_pigsplus.default": "未知概念", + "requirement.anvilcraft_pigsplus.has_atmosphere": "需要天体存在大气", + "requirement.anvilcraft_pigsplus.has_liquid": "需要天体存在液体", + "requirement.anvilcraft_pigsplus.has_other_megastructure": "需要存在其它巨构", + "requirement.anvilcraft_pigsplus.has_biological_resources": "需要存在生物资源", + "requirement.anvilcraft_pigsplus.has_civilization": "需要存在文明", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_least": "需要液体覆盖不低于 %s", + "requirement.anvilcraft_pigsplus.liquid_coverage_at_most": "需要液体覆盖不高于 %s", + "requirement.anvilcraft_pigsplus.liquid_coverage_between": "需要液体覆盖不低于 %s 且不高于 %s", + "requirement.anvilcraft_pigsplus.magnetic_field_at_least": "需要磁场不低于 %s", + "requirement.anvilcraft_pigsplus.magnetic_field_at_most": "需要磁场不高于 %s", + "requirement.anvilcraft_pigsplus.magnetic_field_between": "需要磁场不低于 %s 且不高于 %s", + "requirement.anvilcraft_pigsplus.no_atmosphere": "需要天体不存在大气", + "requirement.anvilcraft_pigsplus.no_liquid": "需要天体不存在液体", + "requirement.anvilcraft_pigsplus.no_other_megastructure": "需要不存在其它巨构", + "requirement.anvilcraft_pigsplus.planetary_reformer": "需要行星改造器", + "requirement.anvilcraft_pigsplus.rocky_planet": "需要岩石行星", + "requirement.anvilcraft_pigsplus.rotation_speed_at_least": "需要转速不低于 %s", + "requirement.anvilcraft_pigsplus.rotation_speed_at_most": "需要转速不高于 %s", + "requirement.anvilcraft_pigsplus.rotation_speed_between": "需要转速不低于 %s 且不高于 %s", + "requirement.anvilcraft_pigsplus.star_reformer": "需要恒星改造器", + "requirement.anvilcraft_pigsplus.temperature_at_least": "需要温度不低于 %s", + "requirement.anvilcraft_pigsplus.temperature_at_most": "需要温度不高于 %s", + "requirement.anvilcraft_pigsplus.temperature_between": "需要温度不低于 %s 且不高于 %s", + "requirement.anvilcraft_pigsplus.unknown": "未知需求", + "requirement.anvilcraft_pigsplus.water_ocean": "需要无液体或液体为水且覆盖度未满", + "screen.anvilcraft.cfa.megastructure.planetary_reformer": "行星改造器", + "screen.anvilcraft.cfa.megastructure.planetary_reformer.usage": "消耗资源,改造天体", + "screen.anvilcraft.cfa.megastructure.star_reformer": "恒星改造器", + "screen.anvilcraft.cfa.megastructure.star_reformer.usage": "消耗资源,改造天体", "tooltip.anvilcraft_pigsplus.enchanted_generator.decrease_rate": "XP减免: %s", "tooltip.anvilcraft_pigsplus.menger_sponge_staff": "清除一大片液体", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.fluid": "%s:%s / %s mB", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.item": "%s:%s / %s", + "tooltip.anvilcraft_pigsplus.celestial_reformer.current.laser": "激光:等级 %s(%s)", "tooltip.anvilcraft_pigsplus.portable_wireless_charger": "放在背包里,消耗 %d kW 以生产 %d FE/t", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.clockwise": "旋转方向: %s", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.clockwise.clockwise": "顺时针", @@ -87,6 +156,5 @@ "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.pre_direction.none": "无", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time": "状态: %s", "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.stopped": "停止工作", - "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "工作中", - "enchantment.anvilcraft_pigsplus.endurance": "耐力" -} \ No newline at end of file + "tooltip.anvilcraft_pigsplus.precision_magnetic_pivot.time.working": "工作中" +} diff --git a/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_1_reformer.json b/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_1_reformer.json new file mode 100644 index 00000000..d24a1293 --- /dev/null +++ b/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_1_reformer.json @@ -0,0 +1,547 @@ +{ + "format_version": "1.9.0", + "credit": "Made by XeKr with Blockbench", + "parent": "anvilcraft:block/celestial_forging_anvil_ring_small", + "render_type": "minecraft:cutout", + "textures": { + "0": "anvilcraft:block/celestial_forging_anvil_top", + "1": "anvilcraft_pigsplus:block/celestial_forging_anvil_ring_reformer", + "particle": "anvilcraft:block/celestial_forging_anvil_top" + }, + "elements": [ + { + "from": [2.5, 1.5, -0.75], + "to": [4.75, 2, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#0"}, + "east": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"}, + "south": {"uv": [13, 7, 15.25, 7.5], "texture": "#0"}, + "west": {"uv": [13, 7.5, 13.5, 9], "rotation": 270, "texture": "#0"}, + "up": {"uv": [13, 7.5, 15.25, 9], "texture": "#0"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [2.5, -2, -0.75], + "to": [4.75, -1.5, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#0"}, + "east": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"}, + "south": {"uv": [13, 7.5, 15.25, 7], "texture": "#0"}, + "west": {"uv": [13, 7.5, 13.5, 9], "rotation": 90, "texture": "#0"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 180, "texture": "#0"}, + "down": {"uv": [13, 7.5, 15.25, 9], "texture": "#0"} + } + }, + { + "from": [3, -1.5, -0.5], + "to": [4.5, 1.5, 0.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 2.5, 10.5, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [7.5, 0, 10.5, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [7.5, 1, 10.5, 2.5], "rotation": 90, "texture": "#0"}, + "west": {"uv": [7.5, 2.5, 10.5, 3.5], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-0.75, 1.5, 2.5], + "to": [0.75, 2, 4.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 13.5, 9], "rotation": 270, "texture": "#0"}, + "east": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#0"}, + "south": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"}, + "west": {"uv": [13, 7, 15.25, 7.5], "texture": "#0"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-0.5, -1.5, 3], + "to": [0.5, 1.5, 4.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 2.5, 10.5, 3.5], "rotation": 270, "texture": "#0"}, + "east": {"uv": [7.5, 2.5, 10.5, 1], "rotation": 90, "texture": "#0"}, + "south": {"uv": [7.5, 0, 10.5, 1], "rotation": 90, "texture": "#0"}, + "west": {"uv": [7.5, 1, 10.5, 2.5], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-0.75, -2, 2.5], + "to": [0.75, -1.5, 4.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 13.5, 9], "rotation": 90, "texture": "#0"}, + "east": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#0"}, + "south": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"}, + "west": {"uv": [13, 7.5, 15.25, 7], "texture": "#0"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 270, "texture": "#0"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-4.75, 1.5, -0.75], + "to": [-2.5, 2, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7, 15.25, 7.5], "texture": "#0"}, + "east": {"uv": [13, 7.5, 13.5, 9], "rotation": 270, "texture": "#0"}, + "south": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#0"}, + "west": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 180, "texture": "#0"}, + "down": {"uv": [15.25, 7.5, 13, 9], "texture": "#0"} + } + }, + { + "from": [-4.5, -1.5, -0.5], + "to": [-3, 1.5, 0.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 1, 10.5, 2.5], "rotation": 90, "texture": "#0"}, + "east": {"uv": [7.5, 2.5, 10.5, 3.5], "rotation": 270, "texture": "#0"}, + "south": {"uv": [7.5, 2.5, 10.5, 1], "rotation": 90, "texture": "#0"}, + "west": {"uv": [7.5, 0, 10.5, 1], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-4.75, -2, -0.75], + "to": [-2.5, -1.5, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 7], "texture": "#0"}, + "east": {"uv": [13, 7.5, 13.5, 9], "rotation": 90, "texture": "#0"}, + "south": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#0"}, + "west": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"}, + "up": {"uv": [15.25, 7.5, 13, 9], "texture": "#0"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [-0.75, 1.5, -4.75], + "to": [0.75, 2, -2.5], + "shade": false, + "faces": { + "north": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"}, + "east": {"uv": [13, 7, 15.25, 7.5], "texture": "#0"}, + "south": {"uv": [13, 7.5, 13.5, 9], "rotation": 270, "texture": "#0"}, + "west": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#0"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-0.5, -1.5, -4.5], + "to": [0.5, 1.5, -3], + "shade": false, + "faces": { + "north": {"uv": [7.5, 0, 10.5, 1], "rotation": 90, "texture": "#0"}, + "east": {"uv": [7.5, 1, 10.5, 2.5], "rotation": 90, "texture": "#0"}, + "south": {"uv": [7.5, 2.5, 10.5, 3.5], "rotation": 270, "texture": "#0"}, + "west": {"uv": [7.5, 2.5, 10.5, 1], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-0.75, -2, -4.75], + "to": [0.75, -1.5, -2.5], + "shade": false, + "faces": { + "north": {"uv": [15.75, 7.5, 15.25, 9], "rotation": 270, "texture": "#0"}, + "east": {"uv": [13, 7.5, 15.25, 7], "texture": "#0"}, + "south": {"uv": [13, 7.5, 13.5, 9], "rotation": 90, "texture": "#0"}, + "west": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#0"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 90, "texture": "#0"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-2.75, -0.25, 3.25], + "to": [2.75, 0.25, 4.25], + "shade": false, + "faces": { + "north": {"uv": [9, 4.75, 14.5, 5.25], "texture": "#0"}, + "south": {"uv": [9, 3.5, 14.5, 4], "texture": "#0"}, + "up": {"uv": [9, 5, 14.5, 4], "texture": "#0"}, + "down": {"uv": [9, 4, 14.5, 5], "texture": "#0"} + } + }, + { + "from": [2.75, -0.5, 3.25], + "to": [3.25, 0.5, 4.25], + "shade": false, + "faces": { + "east": {"uv": [13.5, 1.5, 12.5, 2.5], "texture": "#0"}, + "south": {"uv": [13.5, 1.5, 14, 2.5], "texture": "#0"}, + "west": {"uv": [12.5, 1.5, 13.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1, 12.5, 0], "texture": "#0"}, + "down": {"uv": [12, 0, 12.5, 1], "texture": "#0"} + } + }, + { + "from": [2.75, -0.5, 2.75], + "to": [4.25, 0.5, 3.25], + "shade": false, + "faces": { + "north": {"uv": [13.5, 1.5, 12, 2.5], "texture": "#0"}, + "east": {"uv": [14, 1.5, 13.5, 2.5], "texture": "#0"}, + "south": {"uv": [12, 1.5, 13.5, 2.5], "texture": "#0"}, + "west": {"uv": [12, 1.5, 12.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1.5, 13.5, 1], "texture": "#0"}, + "down": {"uv": [12, 1, 13.5, 1.5], "texture": "#0"} + } + }, + { + "from": [3.25, -0.25, -2.75], + "to": [4.25, 0.25, 2.75], + "shade": false, + "faces": { + "east": {"uv": [9, 3.5, 14.5, 4], "texture": "#0"}, + "west": {"uv": [9, 4.75, 14.5, 5.25], "texture": "#0"}, + "up": {"uv": [9, 5, 14.5, 4], "rotation": 270, "texture": "#0"}, + "down": {"uv": [9, 4, 14.5, 5], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [3.25, -0.5, -3.25], + "to": [4.25, 0.5, -2.75], + "shade": false, + "faces": { + "north": {"uv": [13.5, 1.5, 12.5, 2.5], "texture": "#0"}, + "east": {"uv": [13.5, 1.5, 14, 2.5], "texture": "#0"}, + "south": {"uv": [12.5, 1.5, 13.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1, 12.5, 0], "rotation": 270, "texture": "#0"}, + "down": {"uv": [12, 0, 12.5, 1], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [2.75, -0.5, -4.25], + "to": [3.25, 0.5, -2.75], + "shade": false, + "faces": { + "north": {"uv": [14, 1.5, 13.5, 2.5], "texture": "#0"}, + "east": {"uv": [12, 1.5, 13.5, 2.5], "texture": "#0"}, + "south": {"uv": [12, 1.5, 12.5, 2.5], "texture": "#0"}, + "west": {"uv": [13.5, 1.5, 12, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1.5, 13.5, 1], "rotation": 270, "texture": "#0"}, + "down": {"uv": [12, 1, 13.5, 1.5], "rotation": 90, "texture": "#0"} + } + }, + { + "from": [-2.75, -0.25, -4.25], + "to": [2.75, 0.25, -3.25], + "shade": false, + "faces": { + "north": {"uv": [9, 3.5, 14.5, 4], "texture": "#0"}, + "south": {"uv": [9, 4.75, 14.5, 5.25], "texture": "#0"}, + "up": {"uv": [9, 5, 14.5, 4], "rotation": 180, "texture": "#0"}, + "down": {"uv": [9, 4, 14.5, 5], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [-3.25, -0.5, -4.25], + "to": [-2.75, 0.5, -3.25], + "shade": false, + "faces": { + "north": {"uv": [13.5, 1.5, 14, 2.5], "texture": "#0"}, + "east": {"uv": [12.5, 1.5, 13.5, 2.5], "texture": "#0"}, + "west": {"uv": [13.5, 1.5, 12.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1, 12.5, 0], "rotation": 180, "texture": "#0"}, + "down": {"uv": [12, 0, 12.5, 1], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [-4.25, -0.5, -3.25], + "to": [-2.75, 0.5, -2.75], + "shade": false, + "faces": { + "north": {"uv": [12, 1.5, 13.5, 2.5], "texture": "#0"}, + "east": {"uv": [12, 1.5, 12.5, 2.5], "texture": "#0"}, + "south": {"uv": [13.5, 1.5, 12, 2.5], "texture": "#0"}, + "west": {"uv": [14, 1.5, 13.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1.5, 13.5, 1], "rotation": 180, "texture": "#0"}, + "down": {"uv": [12, 1, 13.5, 1.5], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [-4.25, -0.25, -2.75], + "to": [-3.25, 0.25, 2.75], + "shade": false, + "faces": { + "east": {"uv": [9, 4.75, 14.5, 5.25], "texture": "#0"}, + "west": {"uv": [9, 3.5, 14.5, 4], "texture": "#0"}, + "up": {"uv": [9, 5, 14.5, 4], "rotation": 90, "texture": "#0"}, + "down": {"uv": [9, 4, 14.5, 5], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-4.25, -0.5, 2.75], + "to": [-3.25, 0.5, 3.25], + "shade": false, + "faces": { + "north": {"uv": [12.5, 1.5, 13.5, 2.5], "texture": "#0"}, + "south": {"uv": [13.5, 1.5, 12.5, 2.5], "texture": "#0"}, + "west": {"uv": [13.5, 1.5, 14, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1, 12.5, 0], "rotation": 90, "texture": "#0"}, + "down": {"uv": [12, 0, 12.5, 1], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-3.25, -0.5, 2.75], + "to": [-2.75, 0.5, 4.25], + "shade": false, + "faces": { + "north": {"uv": [12, 1.5, 12.5, 2.5], "texture": "#0"}, + "east": {"uv": [13.5, 1.5, 12, 2.5], "texture": "#0"}, + "south": {"uv": [14, 1.5, 13.5, 2.5], "texture": "#0"}, + "west": {"uv": [12, 1.5, 13.5, 2.5], "texture": "#0"}, + "up": {"uv": [12, 1.5, 13.5, 1], "rotation": 90, "texture": "#0"}, + "down": {"uv": [12, 1, 13.5, 1.5], "rotation": 270, "texture": "#0"} + } + }, + { + "from": [-0.125, -0.125, 0.5], + "to": [0.125, 0.125, 2.75], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "east": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "south": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "west": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 180, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, 0.5], + "to": [0.125, 0.125, 2.75], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "east": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "south": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "west": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 180, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "texture": "#1"} + } + }, + { + "from": [0.5, -0.125, -0.125], + "to": [2.75, 0.125, 0.125], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "east": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "south": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-2.75, -0.125, -0.125], + "to": [-0.5, 0.125, 0.125], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "south": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "west": {"uv": [3, 1, 4, 6], "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [0.5, -0.125, -0.125], + "to": [2.75, 0.125, 0.125], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "east": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "south": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, -2.75], + "to": [0.125, 0.125, -0.5], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "east": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "south": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "west": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, -2.75], + "to": [0.125, 0.125, -0.5], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "east": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "south": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "west": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-2.75, -0.125, -0.125], + "to": [-0.5, 0.125, 0.125], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 1, 4, 10], "rotation": 90, "texture": "#1"}, + "east": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "south": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "west": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "up": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"}, + "down": {"uv": [3, 1, 4, 10], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [2.75, -0.375, -0.375], + "to": [4, 0.375, 0.375], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "east": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, 2.75], + "to": [0.375, 0.375, 4], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "south": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, 2.75], + "to": [0.375, 0.375, 4], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 8, 3, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "south": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "texture": "#1"} + } + }, + { + "from": [-4, -0.375, -0.375], + "to": [-2.75, 0.375, 0.375], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "west": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [-4, -0.375, -0.375], + "to": [-2.75, 0.375, 0.375], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "west": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, -4], + "to": [0.375, 0.375, -2.75], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "south": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, -4], + "to": [0.375, 0.375, -2.75], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "south": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [2.75, -0.375, -0.375], + "to": [4, 0.375, 0.375], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "east": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"} + } + } + ], + "groups": [ + { + "name": "group", + "origin": [0, 14, 0], + "scope": 0, + "color": 0, + "shade": false, + "children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] + }, + { + "name": "group", + "origin": [0, 0, 0], + "scope": 0, + "color": 0, + "shade": false, + "children": [24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_4_reformer.json b/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_4_reformer.json new file mode 100644 index 00000000..c4135b1d --- /dev/null +++ b/src/main/resources/assets/anvilcraft_pigsplus/models/block/celestial_forging_anvil_ring_4_reformer.json @@ -0,0 +1,806 @@ +{ + "format_version": "1.9.0", + "credit": "Made by XeKr with Blockbench", + "parent": "anvilcraft:block/celestial_forging_anvil_ring_big", + "render_type": "minecraft:cutout", + "textures": { + "1": "anvilcraft_pigsplus:block/celestial_forging_anvil_ring_reformer", + "particle": "anvilcraft:block/celestial_forging_anvil_top" + }, + "elements": [ + { + "from": [6.25, -0.25, 0.5], + "to": [7.25, 0.25, 6], + "shade": false, + "faces": { + "east": {"uv": [10.25, 3.5, 15.75, 4], "texture": "#particle"}, + "west": {"uv": [10.25, 4.75, 15.75, 5.25], "texture": "#particle"}, + "up": {"uv": [15.75, 5, 10.25, 4], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [15.75, 4, 10.25, 5], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [6.25, -0.25, -6], + "to": [7.25, 0.25, -0.5], + "shade": false, + "faces": { + "east": {"uv": [15.75, 3.5, 10.25, 4], "texture": "#particle"}, + "west": {"uv": [15.75, 4.75, 10.25, 5.25], "texture": "#particle"}, + "up": {"uv": [10.25, 5, 15.75, 4], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [10.25, 4, 15.75, 5], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [6, -2, -0.5], + "to": [7.5, 2, 0.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 7.75, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "east": {"uv": [7.5, 5.25, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "south": {"uv": [7.5, 6.25, 11.5, 7.75], "rotation": 90, "texture": "#particle"}, + "west": {"uv": [7.5, 7.75, 11.5, 8.75], "rotation": 270, "texture": "#particle"}, + "up": {"uv": [11.5, 5.25, 13, 6.25], "texture": "#particle"}, + "down": {"uv": [13, 5.25, 11.5, 6.25], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [5.5, -0.75, 6], + "to": [6, 0.75, 7.75], + "shade": false, + "faces": { + "east": {"uv": [15.25, 7.5, 13.5, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "west": {"uv": [13.5, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 13.5, 5.25], "texture": "#particle"}, + "down": {"uv": [13, 5.25, 13.5, 7], "texture": "#particle"} + } + }, + { + "from": [5.5, -0.75, 5.5], + "to": [7.75, 0.75, 6], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"} + } + }, + { + "from": [6, -0.75, 1.5], + "to": [8.25, 0.75, 2], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"} + } + }, + { + "from": [6, -0.75, 3], + "to": [8.25, 0.75, 3.5], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"} + } + }, + { + "from": [6, -0.75, -2], + "to": [8.25, 0.75, -1.5], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"} + } + }, + { + "from": [6, -0.75, -3.5], + "to": [8.25, 0.75, -3], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"} + } + }, + { + "from": [-2, -0.75, -8.25], + "to": [-1.5, 0.75, -6], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-3.5, -0.75, -8.25], + "to": [-3, 0.75, -6], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [1.5, -0.75, -8.25], + "to": [2, 0.75, -6], + "shade": false, + "faces": { + "north": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [3, -0.75, -8.25], + "to": [3.5, 0.75, -6], + "shade": false, + "faces": { + "north": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-8.25, -0.75, 1.5], + "to": [-6, 0.75, 2], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-8.25, -0.75, 3], + "to": [-6, 0.75, 3.5], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-8.25, -0.75, -2], + "to": [-6, 0.75, -1.5], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-8.25, -0.75, -3.5], + "to": [-6, 0.75, -3], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [1.5, -0.75, 6], + "to": [2, 0.75, 8.25], + "shade": false, + "faces": { + "north": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [3, -0.75, 6], + "to": [3.5, 0.75, 8.25], + "shade": false, + "faces": { + "north": {"uv": [13.5, 7.5, 13, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 15.25, 7.5], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 7], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-2, -0.75, 6], + "to": [-1.5, 0.75, 8.25], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-3.5, -0.75, 6], + "to": [-3, 0.75, 8.25], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [5.5, -2.5, -0.75], + "to": [7.75, -2, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 90, "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "west": {"uv": [13.5, 7.5, 13, 9], "rotation": 270, "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [5.5, 2, -0.75], + "to": [7.75, 2.5, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 270, "texture": "#particle"}, + "south": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "west": {"uv": [13.5, 7.5, 13, 9], "rotation": 90, "texture": "#particle"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"} + } + }, + { + "from": [-6, -0.25, 6.25], + "to": [-0.5, 0.25, 7.25], + "shade": false, + "faces": { + "north": {"uv": [10.25, 4.75, 15.75, 5.25], "texture": "#particle"}, + "south": {"uv": [10.25, 3.5, 15.75, 4], "texture": "#particle"}, + "up": {"uv": [15.75, 5, 10.25, 4], "texture": "#particle"}, + "down": {"uv": [15.75, 4, 10.25, 5], "texture": "#particle"} + } + }, + { + "from": [0.5, -0.25, 6.25], + "to": [6, 0.25, 7.25], + "shade": false, + "faces": { + "north": {"uv": [15.75, 4.75, 10.25, 5.25], "texture": "#particle"}, + "south": {"uv": [15.75, 3.5, 10.25, 4], "texture": "#particle"}, + "up": {"uv": [10.25, 5, 15.75, 4], "texture": "#particle"}, + "down": {"uv": [10.25, 4, 15.75, 5], "texture": "#particle"} + } + }, + { + "from": [-0.5, -2, 6], + "to": [0.5, 2, 7.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 7.75, 11.5, 8.75], "rotation": 270, "texture": "#particle"}, + "east": {"uv": [7.5, 7.75, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "south": {"uv": [7.5, 5.25, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "west": {"uv": [7.5, 6.25, 11.5, 7.75], "rotation": 90, "texture": "#particle"}, + "up": {"uv": [11.5, 5.25, 13, 6.25], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 11.5, 6.25], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-7.75, -0.75, 5.5], + "to": [-6, 0.75, 6], + "shade": false, + "faces": { + "north": {"uv": [13.5, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13.5, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 13.5, 5.25], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 13.5, 7], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-6, -0.75, 5.5], + "to": [-5.5, 0.75, 7.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "south": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-0.75, -2.5, 5.5], + "to": [0.75, -2, 7.75], + "shade": false, + "faces": { + "north": {"uv": [13.5, 7.5, 13, 9], "rotation": 270, "texture": "#particle"}, + "east": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 90, "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-0.75, 2, 5.5], + "to": [0.75, 2.5, 7.75], + "shade": false, + "faces": { + "north": {"uv": [13.5, 7.5, 13, 9], "rotation": 90, "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 270, "texture": "#particle"}, + "west": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-7.25, -0.25, -6], + "to": [-6.25, 0.25, -0.5], + "shade": false, + "faces": { + "east": {"uv": [10.25, 4.75, 15.75, 5.25], "texture": "#particle"}, + "west": {"uv": [10.25, 3.5, 15.75, 4], "texture": "#particle"}, + "up": {"uv": [15.75, 5, 10.25, 4], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [15.75, 4, 10.25, 5], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-7.25, -0.25, 0.5], + "to": [-6.25, 0.25, 6], + "shade": false, + "faces": { + "east": {"uv": [15.75, 4.75, 10.25, 5.25], "texture": "#particle"}, + "west": {"uv": [15.75, 3.5, 10.25, 4], "texture": "#particle"}, + "up": {"uv": [10.25, 5, 15.75, 4], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [10.25, 4, 15.75, 5], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-7.5, -2, -0.5], + "to": [-6, 2, 0.5], + "shade": false, + "faces": { + "north": {"uv": [7.5, 6.25, 11.5, 7.75], "rotation": 90, "texture": "#particle"}, + "east": {"uv": [7.5, 7.75, 11.5, 8.75], "rotation": 270, "texture": "#particle"}, + "south": {"uv": [7.5, 7.75, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "west": {"uv": [7.5, 5.25, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "up": {"uv": [11.5, 5.25, 13, 6.25], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 11.5, 6.25], "texture": "#particle"} + } + }, + { + "from": [-6, -0.75, -7.75], + "to": [-5.5, 0.75, -6], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "east": {"uv": [13.5, 7.5, 15.25, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13.5, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 13.5, 5.25], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 13.5, 7], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-7.75, -0.75, -6], + "to": [-5.5, 0.75, -5.5], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "south": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "west": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-7.75, -2.5, -0.75], + "to": [-5.5, -2, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "east": {"uv": [13.5, 7.5, 13, 9], "rotation": 270, "texture": "#particle"}, + "south": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 90, "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"} + } + }, + { + "from": [-7.75, 2, -0.75], + "to": [-5.5, 2.5, 0.75], + "shade": false, + "faces": { + "north": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "east": {"uv": [13.5, 7.5, 13, 9], "rotation": 90, "texture": "#particle"}, + "south": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 270, "texture": "#particle"}, + "up": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [0.5, -0.25, -7.25], + "to": [6, 0.25, -6.25], + "shade": false, + "faces": { + "north": {"uv": [10.25, 3.5, 15.75, 4], "texture": "#particle"}, + "south": {"uv": [10.25, 4.75, 15.75, 5.25], "texture": "#particle"}, + "up": {"uv": [15.75, 5, 10.25, 4], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [15.75, 4, 10.25, 5], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-6, -0.25, -7.25], + "to": [-0.5, 0.25, -6.25], + "shade": false, + "faces": { + "north": {"uv": [15.75, 3.5, 10.25, 4], "texture": "#particle"}, + "south": {"uv": [15.75, 4.75, 10.25, 5.25], "texture": "#particle"}, + "up": {"uv": [10.25, 5, 15.75, 4], "rotation": 180, "texture": "#particle"}, + "down": {"uv": [10.25, 4, 15.75, 5], "rotation": 180, "texture": "#particle"} + } + }, + { + "from": [-0.5, -2, -7.5], + "to": [0.5, 2, -6], + "shade": false, + "faces": { + "north": {"uv": [7.5, 5.25, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "east": {"uv": [7.5, 6.25, 11.5, 7.75], "rotation": 90, "texture": "#particle"}, + "south": {"uv": [7.5, 7.75, 11.5, 8.75], "rotation": 270, "texture": "#particle"}, + "west": {"uv": [7.5, 7.75, 11.5, 6.25], "rotation": 90, "texture": "#particle"}, + "up": {"uv": [11.5, 5.25, 13, 6.25], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 11.5, 6.25], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [6, -0.75, -6], + "to": [7.75, 0.75, -5.5], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 13.5, 9], "texture": "#particle"}, + "east": {"uv": [15.25, 7.5, 15.75, 9], "texture": "#particle"}, + "south": {"uv": [13.5, 7.5, 15.25, 9], "texture": "#particle"}, + "up": {"uv": [13, 7, 13.5, 5.25], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 5.25, 13.5, 7], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [5.5, -0.75, -7.75], + "to": [6, 0.75, -5.5], + "shade": false, + "faces": { + "north": {"uv": [15.75, 7.5, 15.25, 9], "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 9], "texture": "#particle"}, + "south": {"uv": [13, 7.5, 13.5, 9], "texture": "#particle"}, + "west": {"uv": [15.25, 7.5, 13, 9], "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 7], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [13, 7, 15.25, 7.5], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-0.75, -2.5, -7.75], + "to": [0.75, -2, -5.5], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 90, "texture": "#particle"}, + "east": {"uv": [13, 7.5, 15.25, 7], "texture": "#particle"}, + "south": {"uv": [13.5, 7.5, 13, 9], "rotation": 270, "texture": "#particle"}, + "west": {"uv": [13, 7, 15.25, 7.5], "rotation": 180, "texture": "#particle"}, + "up": {"uv": [13, 7.5, 15.25, 9], "rotation": 270, "texture": "#particle"}, + "down": {"uv": [15.25, 7.5, 13, 9], "rotation": 270, "texture": "#particle"} + } + }, + { + "from": [-0.75, 2, -7.75], + "to": [0.75, 2.5, -5.5], + "shade": false, + "faces": { + "north": {"uv": [15.25, 7.5, 15.75, 9], "rotation": 270, "texture": "#particle"}, + "east": {"uv": [13, 7, 15.25, 7.5], "texture": "#particle"}, + "south": {"uv": [13.5, 7.5, 13, 9], "rotation": 90, "texture": "#particle"}, + "west": {"uv": [13, 7.5, 15.25, 7], "rotation": 180, "texture": "#particle"}, + "up": {"uv": [15.25, 7.5, 13, 9], "rotation": 90, "texture": "#particle"}, + "down": {"uv": [13, 7.5, 15.25, 9], "rotation": 90, "texture": "#particle"} + } + }, + { + "from": [-0.125, -0.125, 1.5], + "to": [0.125, 0.125, 5.75], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "east": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "south": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "west": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 180, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, 1.5], + "to": [0.125, 0.125, 5.75], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "east": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "south": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "west": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 180, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "texture": "#1"} + } + }, + { + "from": [1.5, -0.125, -0.125], + "to": [5.75, 0.125, 0.125], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "east": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "south": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-5.75, -0.125, -0.125], + "to": [-1.5, 0.125, 0.125], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "south": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "west": {"uv": [3, 1, 4, 6], "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [1.5, -0.125, -0.125], + "to": [5.75, 0.125, 0.125], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "east": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "south": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "west": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, -5.75], + "to": [0.125, 0.125, -1.5], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "east": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "south": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "west": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-0.125, -0.125, -5.75], + "to": [0.125, 0.125, -1.5], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "east": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "south": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "west": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-5.75, -0.125, -0.125], + "to": [-1.5, 0.125, 0.125], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [3, 0, 4, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [3, 10, 4, 11], "texture": "#1"}, + "south": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "west": {"uv": [3, 0, 4, 1], "texture": "#1"}, + "up": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"}, + "down": {"uv": [3, 0, 4, 11], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [5.75, -0.375, -0.375], + "to": [7, 0.375, 0.375], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "east": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, 5.75], + "to": [0.375, 0.375, 7], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "south": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, 5.75], + "to": [0.375, 0.375, 7], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 8, 3, 11], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "south": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "texture": "#1"} + } + }, + { + "from": [-7, -0.375, -0.375], + "to": [-5.75, 0.375, 0.375], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "west": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [-7, -0.375, -0.375], + "to": [-5.75, 0.375, 0.375], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "west": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, -7], + "to": [0.375, 0.375, -5.75], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "south": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [-0.375, -0.375, -7], + "to": [0.375, 0.375, -5.75], + "shade": false, + "rotation": {"angle": -22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 0, 3, 3], "rotation": 90, "texture": "#1"}, + "east": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "south": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "west": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 180, "texture": "#1"} + } + }, + { + "from": [5.75, -0.375, -0.375], + "to": [7, 0.375, 0.375], + "shade": false, + "rotation": {"angle": 22.5, "axis": "y", "origin": [0, 0, 0]}, + "faces": { + "north": {"uv": [0, 3, 3, 8], "rotation": 270, "texture": "#1"}, + "east": {"uv": [0, 0, 3, 3], "texture": "#1"}, + "south": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "west": {"uv": [0, 8, 3, 11], "texture": "#1"}, + "up": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"}, + "down": {"uv": [0, 3, 3, 8], "rotation": 90, "texture": "#1"} + } + } + ], + "groups": [ + { + "name": "group", + "origin": [0, 0, 0], + "scope": 0, + "color": 0, + "shade": false, + "children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43] + }, + { + "name": "group", + "origin": [0, 0, 0], + "scope": 0, + "color": 0, + "shade": false, + "children": [44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/block/celestial_forging_anvil_ring_reformer.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/celestial_forging_anvil_ring_reformer.png new file mode 100644 index 00000000..32ab66d6 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/celestial_forging_anvil_ring_reformer.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/atmosphere.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/atmosphere.png new file mode 100644 index 00000000..b02520dd Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/atmosphere.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/biologic.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/biologic.png new file mode 100644 index 00000000..83ac6144 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/biologic.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/civilization.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/civilization.png new file mode 100644 index 00000000..ea0b4d8c Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/civilization.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/default.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/default.png new file mode 100644 index 00000000..80e344da Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/default.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/laser.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/laser.png new file mode 100644 index 00000000..dab36568 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/laser.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/magnetic_field.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/magnetic_field.png new file mode 100644 index 00000000..1ef600d6 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/magnetic_field.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/plante_type.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/plante_type.png new file mode 100644 index 00000000..3174f57b Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/plante_type.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/reformer.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/reformer.png new file mode 100644 index 00000000..e540930f Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/reformer.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/rotation_speed.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/rotation_speed.png new file mode 100644 index 00000000..ed688f1a Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/rotation_speed.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/sea.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/sea.png new file mode 100644 index 00000000..d0a15ac4 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/sea.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/slot/concept_slot.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/slot/concept_slot.png new file mode 100644 index 00000000..28976fc9 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/slot/concept_slot.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/temperature.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/temperature.png new file mode 100644 index 00000000..1e279bb5 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/gui/reformer/temperature.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/item/celestial_reformer_component.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/celestial_reformer_component.png new file mode 100644 index 00000000..e540930f Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/celestial_reformer_component.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/item/karakuri_component.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/karakuri_component.png index 25403af4..e1cf0739 100644 Binary files a/src/main/resources/assets/anvilcraft_pigsplus/textures/item/karakuri_component.png and b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/karakuri_component.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/item/portable_wireless_charger.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/portable_wireless_charger.png index 6b27220a..f567d6bc 100644 Binary files a/src/main/resources/assets/anvilcraft_pigsplus/textures/item/portable_wireless_charger.png and b/src/main/resources/assets/anvilcraft_pigsplus/textures/item/portable_wireless_charger.png differ diff --git a/src/main/templates/META-INF/neoforge.mods.toml b/src/main/templates/META-INF/neoforge.mods.toml index d94c798b..f4899639 100644 --- a/src/main/templates/META-INF/neoforge.mods.toml +++ b/src/main/templates/META-INF/neoforge.mods.toml @@ -39,6 +39,9 @@ description = '''${mod_description}''' [[mixins]] config = "${mod_id}.mixins.json" +[[mixins]] +config = "${mod_id}.integration.mixins.json" + # The [[accessTransformers]] block allows you to declare where your AT file is. # If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg #[[accessTransformers]]