From a4f4f14c8e97d286d7a4c24ec466abb17888c43f Mon Sep 17 00:00:00 2001 From: Altnoir <2474515202@qq.com> Date: Sun, 20 Sep 2026 09:46:57 +0800 Subject: [PATCH 1/3] dev-0920 --- build.gradle | 7 + gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../resources/assets/mia/lang/en_ud.json | 311 +++ .../resources/assets/mia/lang/en_us.json | 5 + src/main/java/com/altnoir/mia/MIA.java | 40 +- .../java/com/altnoir/mia/MiaItemGroups.java | 541 +++-- .../altnoir/mia/datagen/BlockStateGen.java | 695 ++++++ .../altnoir/mia/datagen/DataGenerators.java | 14 +- .../mia/datagen/MiaBlockLootTable.java | 353 --- .../mia/datagen/MiaBlockStateProvider.java | 820 ------- .../mia/datagen/MiaItemModelProvider.java | 68 - .../com/altnoir/mia/datagen/MiaLangData.java | 109 + .../altnoir/mia/datagen/MiaLangProvider.java | 115 - .../com/altnoir/mia/datagen/MiaLootGen.java | 208 ++ .../mia/datagen/MiaLootTableProvider.java | 3 +- .../java/com/altnoir/mia/init/MiaBlocks.java | 2006 ++++++++++++----- .../java/com/altnoir/mia/init/MiaItems.java | 183 +- .../altnoir/mia/init/MiaPaintingVariants.java | 13 +- .../altnoir/mia/worldgen/biome/MiaBiomes.java | 12 +- .../assets/mia/lang/default/interface.json | 6 + src/main/resources/assets/mia/lang/zh_cn.json | 6 + .../mia/textures/gui/ctab/artifacts.png | Bin 0 -> 1284 bytes .../assets/mia/textures/gui/ctab/building.png | Bin 0 -> 1189 bytes .../mia/textures/gui/ctab/functional.png | Bin 0 -> 1404 bytes .../assets/mia/textures/gui/ctab/items.png | Bin 0 -> 1037 bytes .../assets/mia/textures/gui/ctab/natural.png | Bin 0 -> 1479 bytes 27 files changed, 3265 insertions(+), 2258 deletions(-) create mode 100644 src/generated/resources/assets/mia/lang/en_ud.json create mode 100644 src/main/java/com/altnoir/mia/datagen/BlockStateGen.java delete mode 100644 src/main/java/com/altnoir/mia/datagen/MiaBlockLootTable.java delete mode 100644 src/main/java/com/altnoir/mia/datagen/MiaBlockStateProvider.java delete mode 100644 src/main/java/com/altnoir/mia/datagen/MiaItemModelProvider.java create mode 100644 src/main/java/com/altnoir/mia/datagen/MiaLangData.java delete mode 100644 src/main/java/com/altnoir/mia/datagen/MiaLangProvider.java create mode 100644 src/main/java/com/altnoir/mia/datagen/MiaLootGen.java create mode 100644 src/main/resources/assets/mia/textures/gui/ctab/artifacts.png create mode 100644 src/main/resources/assets/mia/textures/gui/ctab/building.png create mode 100644 src/main/resources/assets/mia/textures/gui/ctab/functional.png create mode 100644 src/main/resources/assets/mia/textures/gui/ctab/items.png create mode 100644 src/main/resources/assets/mia/textures/gui/ctab/natural.png diff --git a/build.gradle b/build.gradle index 50f211f9..6cff4418 100644 --- a/build.gradle +++ b/build.gradle @@ -33,6 +33,7 @@ repositories { maven { url = "https://maven.createmod.net" } // Ponder, Flywheel maven { url = "https://jitpack.io" } maven { url = "https://maven.firstdark.dev/snapshots" } // LDLib2 + maven { url = "https://maven.ringlo.im/releases" } // AbyssLib(Reginth 注册框架 + 分区创造栏) } base { @@ -118,6 +119,12 @@ configurations { dependencies { implementation "net.neoforged:neoforge:${neo_version}" + // AbyssLib:Reginth 注册框架(fork 自 Registrate)+ 分区创造栏。 + // 坐标带 MC 线后缀(abysslib-1.21.1),26.1 线是 abysslib-26.1.2 —— 两条线同 group、 + // 同 mod_version,artifactId 不区分 MC 版本会互相覆盖,别漏掉后缀。 + // 注册框架的类就在这个 jar 里(不再有上游 com.tterrag.registrate 依赖,也不要再 jarJar 它)。 + implementation "com.altnoir:abysslib-1.21.1:${abysslib_version}" + // Curios compileOnly "top.theillusivec4.curios:curios-neoforge:${curios_version}:api" runtimeOnly "top.theillusivec4.curios:curios-neoforge:${curios_version}" diff --git a/gradle.properties b/gradle.properties index 28682fa7..fdf84273 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,10 +24,14 @@ mae_version=1.0.2 ponder_version=1.0.81 flywheel_version=1.0.6 +# AbyssLib(Reginth 注册框架 + 分区创造栏)。坐标是 com.altnoir:abysslib-:<版本>, +# artifactId 里的 MC 后缀由 AbyssLib 的 mod_mc_suffix 决定,写漏会解析不到。 +abysslib_version=1.0.0 + mod_id=mia mod_name=Memento In Abyss mod_license=MIT -mod_version=0.1.0-alpha.30 +mod_version=0.2.0-alpha.31 mod_group_id=com.altnoir.mia mod_authors=Altnoir, lonelyicer, zljtt, zhaijineet mod_description=Memento In Abyss. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118f..129cb9dd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.6.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/generated/resources/assets/mia/lang/en_ud.json b/src/generated/resources/assets/mia/lang/en_ud.json new file mode 100644 index 00000000..c6655745 --- /dev/null +++ b/src/generated/resources/assets/mia/lang/en_ud.json @@ -0,0 +1,311 @@ +{ + "attribute.name.generic.critical_hit": "ǝɔuɐɥƆ ʇıH ןɐɔıʇıɹƆ", + "attribute.name.generic.critical_hit_damage": "ǝbɐɯɐᗡ ʇıH ןɐɔıʇıɹƆ", + "biome.mia.great_fault/great_fault": "ʇןnɐℲ ʇɐǝɹ⅁", + "biome.mia.great_fault/the_great_fault": "ʇןnɐℲ ʇɐǝɹ⅁ ǝɥ⟘", + "biome.mia.the_abyss/abyss_dripstone_caves": "sǝʌɐƆ ǝuoʇsdıɹᗡ ssʎqⱯ", + "biome.mia.the_abyss/abyss_lush_caves": "sǝʌɐƆ ɥsnꞀ ssʎqⱯ", + "biome.mia.the_abyss/abyss_plains": "suıɐןԀ ssʎqⱯ", + "biome.mia.the_abyss/dense_skyfog_forest": "ʇsǝɹoℲ boɟʎʞS ǝsuǝᗡ", + "biome.mia.the_abyss/fossilized_forest": "ʇsǝɹoℲ pǝzıןıssoℲ", + "biome.mia.the_abyss/inverted_forest": "ʇsǝɹoℲ pǝʇɹǝʌuI", + "biome.mia.the_abyss/prasiolite_caves": "sǝʌɐƆ ǝʇıןoısɐɹԀ", + "biome.mia.the_abyss/rich_fossilized_forest": "ʇsǝɹoℲ pǝzıןıssoℲ ɥɔıᴚ", + "biome.mia.the_abyss/skyfog_forest": "ʇsǝɹoℲ boɟʎʞS", + "biome.mia.the_abyss/temptation_forest": "ʇsǝɹoℲ uoıʇɐʇdɯǝ⟘", + "biome.mia.the_abyss/the_abyss": "ssʎqⱯ ǝɥ⟘", + "biome.mia.the_abyss/under_fossilized_forest": "ʇsǝɹoℲ pǝzıןıssoℲ ɹǝpu∩", + "block.mia.abyss_andesite": "ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_bricks": "sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_bricks_slab": "qɐןS sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_bricks_wall": "ןןɐM sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_column": "uɯnןoƆ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_pillar": "ɹɐןןıԀ ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_slab": "qɐןS ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_stairs": "sɹıɐʇS ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_andesite_wall": "ןןɐM ǝʇısǝpuⱯ ssʎqⱯ", + "block.mia.abyss_chlorophyte_ore": "ǝɹO ǝʇʎɥdoɹoןɥƆ ssʎqⱯ", + "block.mia.abyss_cobbled_andesite": "ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ", + "block.mia.abyss_cobbled_andesite_slab": "qɐןS ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ", + "block.mia.abyss_cobbled_andesite_stairs": "sɹıɐʇS ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ", + "block.mia.abyss_cobbled_andesite_wall": "ןןɐM ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ", + "block.mia.abyss_copper_ore": "ǝɹO ɹǝddoƆ ssʎqⱯ", + "block.mia.abyss_diamond_ore": "ǝɹO puoɯɐıᗡ ssʎqⱯ", + "block.mia.abyss_emerald_ore": "ǝɹO pןɐɹǝɯƎ ssʎqⱯ", + "block.mia.abyss_gold_ore": "ǝɹO pןo⅁ ssʎqⱯ", + "block.mia.abyss_iron_ore": "ǝɹO uoɹI ssʎqⱯ", + "block.mia.abyss_lapis_ore": "ǝɹO sıdɐꞀ ssʎqⱯ", + "block.mia.abyss_portal": "ןɐʇɹoԀ ssʎqⱯ", + "block.mia.abyss_portal_core": "ǝɹoƆ ןɐʇɹoԀ ssʎqⱯ", + "block.mia.abyss_portal_frame": "ǝɯɐɹℲ ןɐʇɹoԀ ssʎqⱯ", + "block.mia.abyss_quartz_ore": "ǝɹO zʇɹɐnὉ ssʎqⱯ", + "block.mia.abyss_redstone_ore": "ǝɹO ǝuoʇspǝᴚ ssʎqⱯ", + "block.mia.abyss_spawner": "ɹǝuʍɐdS ssʎqⱯ", + "block.mia.amethyst_lamptube": "ǝqnʇdɯɐꞀ ʇsʎɥʇǝɯⱯ", + "block.mia.artifact_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ʇɔɐɟıʇɹⱯ", + "block.mia.balloon_plant": "ʇuɐןԀ uooןןɐᗺ", + "block.mia.budding_caerulite": "ǝʇıןnɹǝɐƆ buıppnᗺ", + "block.mia.budding_prasiolite": "ǝʇıןoısɐɹԀ buıppnᗺ", + "block.mia.caerulite_block": "ʞɔoןᗺ ǝʇıןnɹǝɐƆ", + "block.mia.caerulite_cluster": "ɹǝʇsnןƆ ǝʇıןnɹǝɐƆ", + "block.mia.cave_explorer_beacon": "uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ", + "block.mia.chiseled_abyss_andesite": "ǝʇısǝpuⱯ ssʎqⱯ pǝןǝsıɥƆ", + "block.mia.chiseled_stripped_fossilized_wood": "pooM pǝzıןıssoℲ pǝddıɹʇS pǝןǝsıɥƆ", + "block.mia.chlorophyte_block": "ʞɔoןᗺ ǝʇʎɥdoɹoןɥƆ", + "block.mia.covergrass_abyss_andesite": "ǝʇısǝpuⱯ ssʎqⱯ ssɐɹbɹǝʌoƆ", + "block.mia.covergrass_tuff": "ɟɟn⟘ ssɐɹbɹǝʌoƆ", + "block.mia.cracked_abyss_andesite_bricks": "sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ pǝʞɔɐɹƆ", + "block.mia.crimson_veilgrass": "ssɐɹbןıǝΛ uosɯıɹƆ", + "block.mia.dream_lichee_plant": "ʇuɐןԀ ǝǝɥɔıꞀ ɯɐǝɹᗡ", + "block.mia.endless_cup": "dnƆ ssǝןpuƎ", + "block.mia.fortitude_flower": "ɹǝʍoןℲ ǝpnʇıʇɹoℲ", + "block.mia.fossilized_log": "boꞀ pǝzıןıssoℲ", + "block.mia.fossilized_wood": "pooM pǝzıןıssoℲ", + "block.mia.fossilized_wood_bricks": "sʞɔıɹᗺ pooM pǝzıןıssoℲ", + "block.mia.fossilized_wood_bricks_slab": "qɐןS sʞɔıɹᗺ pooM pǝzıןıssoℲ", + "block.mia.fossilized_wood_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ pooM pǝzıןıssoℲ", + "block.mia.fossilized_wood_bricks_wall": "ןןɐM sʞɔıɹᗺ pooM pǝzıןıssoℲ", + "block.mia.gloom_berry_plant": "ʇuɐןԀ ʎɹɹǝᗺ ɯooן⅁", + "block.mia.green_perilla": "ɐןןıɹǝԀ uǝǝɹ⅁", + "block.mia.hopper_farmland": "puɐןɯɹɐℲ ɹǝddoH", + "block.mia.inverted_button": "uoʇʇnᗺ pǝʇɹǝʌuI", + "block.mia.inverted_door": "ɹooᗡ pǝʇɹǝʌuI", + "block.mia.inverted_fence": "ǝɔuǝℲ pǝʇɹǝʌuI", + "block.mia.inverted_fence_gate": "ǝʇɐ⅁ ǝɔuǝℲ pǝʇɹǝʌuI", + "block.mia.inverted_leaves": "sǝʌɐǝꞀ pǝʇɹǝʌuI", + "block.mia.inverted_log": "boꞀ pǝʇɹǝʌuI", + "block.mia.inverted_planks": "sʞuɐןԀ pǝʇɹǝʌuI", + "block.mia.inverted_pressure_plate": "ǝʇɐןԀ ǝɹnssǝɹԀ pǝʇɹǝʌuI", + "block.mia.inverted_sapling": "buıןdɐS pǝʇɹǝʌuI", + "block.mia.inverted_slab": "qɐןS pǝʇɹǝʌuI", + "block.mia.inverted_stairs": "sɹıɐʇS pǝʇɹǝʌuI", + "block.mia.inverted_trapdoor": "ɹoopdɐɹ⟘ pǝʇɹǝʌuI", + "block.mia.inverted_wood": "pooM pǝʇɹǝʌuI", + "block.mia.konjac_root": "ʇooᴚ ɔɐظuoʞ", + "block.mia.lantern_plant": "ʇuɐןԀ uɹǝʇuɐꞀ", + "block.mia.large_caerulite_bud": "pnᗺ ǝʇıןnɹǝɐƆ ǝbɹɐꞀ", + "block.mia.large_prasiolite_bud": "pnᗺ ǝʇıןoısɐɹԀ ǝbɹɐꞀ", + "block.mia.marginal_weed": "pǝǝM ןɐuıbɹɐW", + "block.mia.marlith": "ɥʇıןɹɐW", + "block.mia.medium_caerulite_bud": "pnᗺ ǝʇıןnɹǝɐƆ ɯnıpǝW", + "block.mia.medium_prasiolite_bud": "pnᗺ ǝʇıןoısɐɹԀ ɯnıpǝW", + "block.mia.mossy_abyss_andesite_bricks": "sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_andesite_bricks_slab": "qɐןS sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_andesite_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_andesite_bricks_wall": "ןןɐM sʞɔıɹᗺ ǝʇısǝpuⱯ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_cobbled_andesite": "ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_cobbled_andesite_slab": "qɐןS ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_cobbled_andesite_stairs": "sɹıɐʇS ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ ʎssoW", + "block.mia.mossy_abyss_cobbled_andesite_wall": "ןןɐM ǝʇısǝpuⱯ pǝןqqoƆ ssʎqⱯ ʎssoW", + "block.mia.mossy_fossilized_log": "boꞀ pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_fossilized_wood": "pooM pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_fossilized_wood_bricks": "sʞɔıɹᗺ pooM pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_fossilized_wood_bricks_slab": "qɐןS sʞɔıɹᗺ pooM pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_fossilized_wood_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ pooM pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_fossilized_wood_bricks_wall": "ןןɐM sʞɔıɹᗺ pooM pǝzıןıssoℲ ʎssoW", + "block.mia.mossy_stripped_fossilized_log": "boꞀ pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.mossy_stripped_fossilized_wood": "pooM pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.mossy_stripped_fossilized_wood_bricks": "sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.mossy_stripped_fossilized_wood_bricks_slab": "qɐןS sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.mossy_stripped_fossilized_wood_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.mossy_stripped_fossilized_wood_bricks_wall": "ןןɐM sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS ʎssoW", + "block.mia.pedestal": "ןɐʇsǝpǝԀ", + "block.mia.polished_abyss_andesite": "ǝʇısǝpuⱯ ssʎqⱯ pǝɥsıןoԀ", + "block.mia.polished_abyss_andesite_slab": "qɐןS ǝʇısǝpuⱯ ssʎqⱯ pǝɥsıןoԀ", + "block.mia.polished_abyss_andesite_stairs": "sɹıɐʇS ǝʇısǝpuⱯ ssʎqⱯ pǝɥsıןoԀ", + "block.mia.polished_abyss_andesite_wall": "ןןɐM ǝʇısǝpuⱯ ssʎqⱯ pǝɥsıןoԀ", + "block.mia.polished_fossilized_wood": "pooM pǝzıןıssoℲ pǝɥsıןoԀ", + "block.mia.polished_fossilized_wood_slab": "qɐןS pooM pǝzıןıssoℲ pǝɥsıןoԀ", + "block.mia.polished_fossilized_wood_stairs": "sɹıɐʇS pooM pǝzıןıssoℲ pǝɥsıןoԀ", + "block.mia.polished_fossilized_wood_wall": "ןןɐM pooM pǝzıןıssoℲ pǝɥsıןoԀ", + "block.mia.polished_stripped_fossilized_wood": "pooM pǝzıןıssoℲ pǝddıɹʇS pǝɥsıןoԀ", + "block.mia.polished_stripped_fossilized_wood_slab": "qɐןS pooM pǝzıןıssoℲ pǝddıɹʇS pǝɥsıןoԀ", + "block.mia.polished_stripped_fossilized_wood_stairs": "sɹıɐʇS pooM pǝzıןıssoℲ pǝddıɹʇS pǝɥsıןoԀ", + "block.mia.polished_stripped_fossilized_wood_wall": "ןןɐM pooM pǝzıןıssoℲ pǝddıɹʇS pǝɥsıןoԀ", + "block.mia.prasiolite_block": "ʞɔoןᗺ ǝʇıןoısɐɹԀ", + "block.mia.prasiolite_cluster": "ɹǝʇsnןƆ ǝʇıןoısɐɹԀ", + "block.mia.prasiolite_lamptube": "ǝqnʇdɯɐꞀ ǝʇıןoısɐɹԀ", + "block.mia.raw_chlorophyte_block": "ʞɔoןᗺ ǝʇʎɥdoɹoןɥƆ ʍɐᴚ", + "block.mia.reed": "pǝǝᴚ", + "block.mia.rope": "ǝdoᴚ", + "block.mia.scorchleaf": "ɟɐǝןɥɔɹoɔS", + "block.mia.silveaf_fungus": "snbunℲ ɟɐǝʌןıS", + "block.mia.skyfog_button": "uoʇʇnᗺ boɟʎʞS", + "block.mia.skyfog_door": "ɹooᗡ boɟʎʞS", + "block.mia.skyfog_fence": "ǝɔuǝℲ boɟʎʞS", + "block.mia.skyfog_fence_gate": "ǝʇɐ⅁ ǝɔuǝℲ boɟʎʞS", + "block.mia.skyfog_leaves": "sǝʌɐǝꞀ boɟʎʞS", + "block.mia.skyfog_leaves_with_fruits": "sʇınɹℲ ɥʇıM sǝʌɐǝꞀ boɟʎʞS", + "block.mia.skyfog_log": "boꞀ boɟʎʞS", + "block.mia.skyfog_planks": "sʞuɐןԀ boɟʎʞS", + "block.mia.skyfog_pressure_plate": "ǝʇɐןԀ ǝɹnssǝɹԀ boɟʎʞS", + "block.mia.skyfog_sapling": "buıןdɐS boɟʎʞS", + "block.mia.skyfog_slab": "qɐןS boɟʎʞS", + "block.mia.skyfog_stairs": "sɹıɐʇS boɟʎʞS", + "block.mia.skyfog_trapdoor": "ɹoopdɐɹ⟘ boɟʎʞS", + "block.mia.skyfog_wood": "pooM boɟʎʞS", + "block.mia.small_caerulite_bud": "pnᗺ ǝʇıןnɹǝɐƆ ןןɐɯS", + "block.mia.small_prasiolite_bud": "pnᗺ ǝʇıןoısɐɹԀ ןןɐɯS", + "block.mia.stripped_fossilized_log": "boꞀ pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_fossilized_wood": "pooM pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_fossilized_wood_bricks": "sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_fossilized_wood_bricks_slab": "qɐןS sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_fossilized_wood_bricks_stairs": "sɹıɐʇS sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_fossilized_wood_bricks_wall": "ןןɐM sʞɔıɹᗺ pooM pǝzıןıssoℲ pǝddıɹʇS", + "block.mia.stripped_inverted_log": "boꞀ pǝʇɹǝʌuI pǝddıɹʇS", + "block.mia.stripped_inverted_wood": "pooM pǝʇɹǝʌuI pǝddıɹʇS", + "block.mia.stripped_skyfog_log": "boꞀ boɟʎʞS pǝddıɹʇS", + "block.mia.stripped_skyfog_wood": "pooM boɟʎʞS pǝddıɹʇS", + "block.mia.stripped_verdant_hyphae": "ǝɐɥdʎH ʇuɐpɹǝΛ pǝddıɹʇS", + "block.mia.stripped_verdant_stem": "ɯǝʇS ʇuɐpɹǝΛ pǝddıɹʇS", + "block.mia.sun_stone": "ǝuoʇS unS", + "block.mia.suspicious_abyss_andesite": "ǝʇısǝpuⱯ ssʎqⱯ snoıɔıdsnS", + "block.mia.verdant_button": "uoʇʇnᗺ ʇuɐpɹǝΛ", + "block.mia.verdant_door": "ɹooᗡ ʇuɐpɹǝΛ", + "block.mia.verdant_fence": "ǝɔuǝℲ ʇuɐpɹǝΛ", + "block.mia.verdant_fence_gate": "ǝʇɐ⅁ ǝɔuǝℲ ʇuɐpɹǝΛ", + "block.mia.verdant_fungus": "snbunℲ ʇuɐpɹǝΛ", + "block.mia.verdant_hyphae": "ǝɐɥdʎH ʇuɐpɹǝΛ", + "block.mia.verdant_leaves": "sǝʌɐǝꞀ ʇuɐpɹǝΛ", + "block.mia.verdant_planks": "sʞuɐןԀ ʇuɐpɹǝΛ", + "block.mia.verdant_pressure_plate": "ǝʇɐןԀ ǝɹnssǝɹԀ ʇuɐpɹǝΛ", + "block.mia.verdant_slab": "qɐןS ʇuɐpɹǝΛ", + "block.mia.verdant_stairs": "sɹıɐʇS ʇuɐpɹǝΛ", + "block.mia.verdant_stem": "ɯǝʇS ʇuɐpɹǝΛ", + "block.mia.verdant_trapdoor": "ɹoopdɐɹ⟘ ʇuɐpɹǝΛ", + "container.mia.artifact.smithing.title": "ǝןqɐ⟘ buıɥʇıɯS ʇɔɐɟıʇɹⱯ", + "curios.identifier.whistle": "ǝןʇsıɥM", + "curios.modifiers.whistle": "sǝʇnqıɹʇʇⱯ ǝןʇsıɥM", + "emi.category.mia.lamp_tube": "sısʎןɐʇɐƆ ɹǝsɐꞀ", + "gui.mia.disconnect": "¿ʇınὉ", + "item.mia.artifact_haste": "ǝʇsɐH ʇɔɐɟıʇɹⱯ", + "item.mia.blaze_reap": "dɐǝᴚ ǝzɐןᗺ", + "item.mia.blue_whistle": "ǝןʇsıɥM ǝnןᗺ", + "item.mia.caerulite_shard": "pɹɐɥS ǝʇıןnɹǝɐƆ", + "item.mia.chlorophyte_ingot": "ʇobuI ǝʇʎɥdoɹoןɥƆ", + "item.mia.chlorophyte_nugget": "ʇǝbbnN ǝʇʎɥdoɹoןɥƆ", + "item.mia.debug_attribute_tool": "ןoo⟘ ǝʇnqıɹʇʇⱯ bnqǝᗡ", + "item.mia.dream_lichee": "ǝǝɥɔıꞀ ɯɐǝɹᗡ", + "item.mia.fancy_artifact_bundle": "ǝןpunᗺ ʇɔɐɟıʇɹⱯ ʎɔuɐℲ", + "item.mia.gloom_berry": "ʎɹɹǝᗺ ɯooן⅁", + "item.mia.grappling_hook": "ʞooH buıןddɐɹ⅁", + "item.mia.gray_artifact_bundle": "ǝןpunᗺ ʇɔɐɟıʇɹⱯ ʎɐɹ⅁", + "item.mia.grow_sword": "pɹoʍS ʍoɹ⅁", + "item.mia.health_junkie": "ǝıʞunſ ɥʇןɐǝH", + "item.mia.mistfuzz_peach": "ɥɔɐǝԀ zznɟʇsıW", + "item.mia.peace_phobia": "ɐıqoɥԀ ǝɔɐǝԀ", + "item.mia.prasiolite_hoe": "ǝoH ǝʇıןoısɐɹԀ", + "item.mia.prasiolite_pickaxe": "ǝxɐʞɔıԀ ǝʇıןoısɐɹԀ", + "item.mia.prasiolite_shard": "pɹɐɥS ǝʇıןoısɐɹԀ", + "item.mia.raw_chlorophyte": "ǝʇʎɥdoɹoןɥƆ ʍɐᴚ", + "item.mia.red_whistle": "ǝןʇsıɥM pǝᴚ", + "item.mia.star_compass": "ssɐdɯoƆ ɹɐʇS", + "item.mia.test_artifact_1": "Ɩ ʇɔɐɟıʇɹⱯ ʇsǝ⟘", + "item.mia.test_artifact_2": "ᄅ ʇɔɐɟıʇɹⱯ ʇsǝ⟘", + "item.mia.test_artifact_3": "Ɛ ʇɔɐɟıʇɹⱯ ʇsǝ⟘", + "item.minecraft.lingering_potion.effect.haste": "ǝʇsɐH ɟo uoıʇoԀ buıɹǝbuıꞀ", + "item.minecraft.lingering_potion.effect.long_haste": "ǝʇsɐH buoꞀ ɟo uoıʇoԀ buıɹǝbuıꞀ", + "item.minecraft.lingering_potion.effect.strong_haste": "ǝʇsɐH buoɹʇS ɟo uoıʇoԀ buıɹǝbuıꞀ", + "item.minecraft.potion.effect.haste": "ǝʇsɐH ɟo uoıʇoԀ", + "item.minecraft.potion.effect.long_haste": "ǝʇsɐH buoꞀ ɟo uoıʇoԀ", + "item.minecraft.potion.effect.strong_haste": "ǝʇsɐH buoɹʇS ɟo uoıʇoԀ", + "item.minecraft.splash_potion.effect.haste": "ǝʇsɐH ɟo uoıʇoԀ ɥsɐןdS", + "item.minecraft.splash_potion.effect.long_haste": "ǝʇsɐH buoꞀ ɟo uoıʇoԀ ɥsɐןdS", + "item.minecraft.splash_potion.effect.strong_haste": "ǝʇsɐH buoɹʇS ɟo uoıʇoԀ ɥsɐןdS", + "itemgroup.mia": "ssʎqⱯ uI oʇuǝɯǝW", + "itemgroup.mia.section.artifacts": "sʇɔɐɟıʇɹⱯ", + "itemgroup.mia.section.building": "sʞɔoןᗺ buıpןınᗺ", + "itemgroup.mia.section.functional": "sʞɔoןᗺ ןɐuoıʇɔunℲ", + "itemgroup.mia.section.items": "sɯǝʇI", + "itemgroup.mia.section.natural": "sʞɔoןᗺ ןɐɹnʇɐN", + "itemgroup.mia_artifact": "ʇɔɐɟıʇɹⱯ :ssʎqⱯ uI oʇuǝɯǝW", + "key.categories.mia": "ssʎqⱯ uI oʇuǝɯǝW", + "key.mia.skill_dial": "ןɐıᗡ ןןıʞS", + "mia.configuration.abyss_radius": "ǝnןɐΛ snıpɐᴚ ssʎqⱯ", + "mia.configuration.abyss_radius.tooltip": "snıpɐᴚ ssʎqⱯ ǝɥ⟘ buıʇʇǝS", + "mia.configuration.auto_hook": "ʞooH oʇnⱯ", + "mia.configuration.auto_hook.tooltip": "ʞooɥ oʇnɐ ǝןqɐuǝ oʇ ɹǝɥʇǝɥM", + "mia.configuration.cave_explorer_beacon": "uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ", + "mia.configuration.cave_explorer_beacon.tooltip": "uoıʇɐɹnbıɟuoƆ uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ", + "mia.configuration.cave_explorer_beacon_horizontal": "ǝbuɐᴚ ןɐʇuozıɹoH", + "mia.configuration.cave_explorer_beacon_horizontal.tooltip": "ǝbuɐᴚ ןɐʇuozıɹoH uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ ǝɥ⟘ buıʇʇǝS", + "mia.configuration.cave_explorer_beacon_max_vertical": "ǝbuɐᴚ ןɐɔıʇɹǝΛ xɐW", + "mia.configuration.cave_explorer_beacon_max_vertical.tooltip": "ןɐɔıʇɹǝΛ xɐW uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ ǝɥ⟘ buıʇʇǝS", + "mia.configuration.cave_explorer_beacon_vertical": "ǝbuɐᴚ ןɐɔıʇɹǝΛ", + "mia.configuration.cave_explorer_beacon_vertical.tooltip": "ǝbuɐᴚ ןɐɔıʇɹǝΛ uoɔɐǝᗺ ɹǝɹoןdxƎ ǝʌɐƆ ǝɥ⟘ buıʇʇǝS", + "mia.configuration.curse": "ǝsɹnƆ ǝןqɐuƎ", + "mia.configuration.curse.tooltip": "ǝsɹnƆ ǝɥʇ ǝןqɐuǝ oʇ ɹǝɥʇǝɥM", + "mia.configuration.curse_god": "ɹoʇɐʇɔǝdS puɐ ǝʌıʇɐǝɹƆ ǝɥʇ ǝsɹnƆ", + "mia.configuration.curse_god.tooltip": "ɹoʇɐʇɔǝdS puɐ ǝʌıʇɐǝɹƆ ǝɥʇ ǝsɹnƆ oʇ ɹǝɥʇǝɥM", + "mia.configuration.curse_icon_position": "uoıʇısoԀ uoɔI ǝsɹnƆ", + "mia.configuration.curse_icon_position.hidden": "uǝppıH", + "mia.configuration.curse_icon_position.middle": "ǝןppıW", + "mia.configuration.curse_icon_position.right": "ʇɥbıᴚ", + "mia.configuration.curse_icon_position.tooltip": "uoıʇısoԀ uoɔI ǝsɹnƆ ɥɔʇıʍS", + "mia.configuration.disconnect_button_state": "ǝʇɐʇS uoʇʇnᗺ ʇɔǝuuoɔsıᗡ", + "mia.configuration.disconnect_button_state.default": "ʇןnɐɟǝᗡ", + "mia.configuration.disconnect_button_state.disabled": "pǝןqɐsıᗡ", + "mia.configuration.disconnect_button_state.hidden": "uǝppıH", + "mia.configuration.disconnect_button_state.tooltip": "uoʇʇnᗺ ʇɔǝuuoɔsıᗡ ǝɥʇ ʇsnظpⱯ", + "mia.configuration.hook": "ʞooH", + "mia.configuration.hook.tooltip": "uoıʇɐɹnbıɟuoƆ ʞooH", + "mia.configuration.hook_jump_boost": "ɹǝıןdıʇןnW ʇsooᗺ dɯnſ", + "mia.configuration.hook_jump_boost.tooltip": "ʞooɥ buısn uǝɥʍ ɹǝıןdıʇןnɯ ʇsooq dɯnſ", + "mia.configuration.hook_max_distance": "ǝɔuɐʇsıᗡ ʞooH xɐW", + "mia.configuration.hook_max_distance.tooltip": "sʞɔoןq uı ǝɔuɐʇsıp ʞooɥ ɯnɯıxɐW", + "mia.configuration.hook_pull_velocity": "ʎʇıɔoןǝΛ ןןnԀ ʞooH", + "mia.configuration.hook_pull_velocity.tooltip": "ʎʇıɔoןǝʌ ןןnd ǝsɐᗺ", + "mia.configuration.hook_retract_distance": "ǝɔuɐʇsıᗡ ʇɔɐɹʇǝᴚ ʞooH", + "mia.configuration.hook_retract_distance.tooltip": "sʇɔɐɹʇǝɹ ʎןןɐɔıʇɐɯoʇnɐ ʞooɥ ǝɥʇ ɥɔıɥʍ ʇɐ ǝɔuɐʇsıᗡ", + "mia.configuration.hook_retract_velocity": "ʎʇıɔoןǝΛ ʇɔɐɹʇǝᴚ ʞooH", + "mia.configuration.hook_retract_velocity.tooltip": "ʎʇıɔoןǝʌ ʇɔɐɹʇǝɹ ʞooH", + "mia.configuration.hook_shoot_velocity": "ʎʇıɔoןǝΛ ʇooɥS ʞooH", + "mia.configuration.hook_shoot_velocity.tooltip": "ʎʇıɔoןǝʌ ʇooɥs ʞooH", + "mia.configuration.hook_stop_distance": "ǝɔuɐʇsıᗡ doʇS ןןnԀ ʞooH", + "mia.configuration.hook_stop_distance.tooltip": "ɹǝʎɐןd ǝɥʇ buıןןnd sdoʇs ʞooɥ ǝɥʇ ɥɔıɥʍ ʇɐ ǝɔuɐʇsıᗡ", + "mia.configuration.title": "uoıʇɐɹnbıɟuoƆ ssʎqⱯ uI oʇuǝɯǝW", + "pack.mia.music_pack.name": "ʞɔɐԀ ɔısnW :ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.abyss_map.author": "ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.abyss_map.title": "dɐW ssʎqⱯ", + "painting.mia.fortitude_flower.author": "ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.fortitude_flower.title": "ɹǝʍoןℲ ǝpnʇıʇɹoℲ", + "painting.mia.fossil_tree.author": "ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.fossil_tree.title": "ǝǝɹ⟘ ןıssoℲ", + "painting.mia.the_abyss.author": "ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.the_abyss.title": "ssʎqⱯ ǝɥ⟘", + "painting.mia.the_abyss2.author": "ssʎqⱯ uI oʇuǝɯǝW", + "painting.mia.the_abyss2.title": "ᄅssʎqⱯ ǝɥ⟘", + "skill.mia.combo_skills": "sןןıʞS oqɯoƆ", + "skill.mia.cooldown": "˙˙˙uʍopןooƆ", + "skill.mia.cooldown_time": "-⟘ uʍopןooƆ", + "skill.mia.minute": "ɯ", + "skill.mia.second": "s", + "skill.mia.unskill": "ןןıʞsu∩", + "stat.mia.interact_with_artifact_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ʇɔɐɟıʇɹⱯ ɥʇıʍ suoıʇɔɐɹǝʇuI", + "subtitle.mia.abyss_portal_ambient": "ʇuǝıqɯⱯ :ןɐʇɹoԀ ssʎqⱯ", + "subtitle.mia.abyss_portal_travel": "ןǝʌɐɹ⟘ :ןɐʇɹoԀ ssʎqⱯ", + "tag.item.curios.whistle": "ǝןʇsıɥM", + "tag.item.mia.fossilized_logs": "sboꞀ pǝzıןıssoℲ", + "tag.item.mia.skyfog_logs": "sboꞀ boɟʎʞS", + "tag.item.mia.stripped_fossilized_logs": "sboꞀ pǝzıןıssoℲ pǝddıɹʇS", + "tooltip.mia.abyss_spawner.cooldown": "%s :uʍopןooƆ", + "tooltip.mia.artifact.grade.a": "Ɐ", + "tooltip.mia.artifact.grade.b": "ᗺ", + "tooltip.mia.artifact.grade.c": "Ɔ", + "tooltip.mia.artifact.grade.d": "ᗡ", + "tooltip.mia.artifact.grade.s": "S", + "tooltip.mia.artifact.grade.unknown": "uʍouʞu∩", + "tooltip.mia.artifact.level": "%s/%s :oɥɔƎ", + "tooltip.mia.artifact.max": "XⱯW :oɥɔƎ", + "tooltip.mia.artifact.weight": "%s :ʇɥbıǝM", + "tooltip.mia.artifact_bundle.capacity": "%s :ʎʇıɔɐdɐƆ ʇɔɐɟıʇɹⱯ", + "tooltip.mia.attribute_modifier": "%s %s", + "tooltip.mia.description.abyss_compass": "˙ssʎqɐ ǝɥʇ pɹɐʍoʇ ʎɐʍ ǝɥʇ ʇuıod ןןıʍ ʇI", + "tooltip.mia.description.red_whistle": "˙ɹǝʎɐן ʇsɹıɟ s’ssʎqⱯ ǝɥʇ uı ʎןuo pǝʍoןןɐ sɹǝpıɐɹ ǝʌɐɔ ǝɔıʌou ǝɹɐ sǝןʇsıɥM pǝᴚ", + "tooltip.mia.hold_shift": "sןıɐʇǝp ʍoɥs oʇ ]%s[ pןoH", + "tooltip.mia.modifiers.artifact_material": " :ʇɔɐɟıʇɹⱯ buıʎןddⱯ uǝɥM", + "tooltip.mia.skill.cooldown_value": "%s :uʍopןooƆ", + "tooltip.mia.whistle.capacity": "%s :ʎʇıɔɐdɐƆ", + "tooltip.mia.whistle.level": "%s :ןǝʌǝꞀ ǝןʇsıɥM" +} \ No newline at end of file diff --git a/src/generated/resources/assets/mia/lang/en_us.json b/src/generated/resources/assets/mia/lang/en_us.json index 2b51f3e6..83917e0b 100644 --- a/src/generated/resources/assets/mia/lang/en_us.json +++ b/src/generated/resources/assets/mia/lang/en_us.json @@ -214,6 +214,11 @@ "item.minecraft.splash_potion.effect.long_haste": "Splash Potion of Long Haste", "item.minecraft.splash_potion.effect.strong_haste": "Splash Potion of Strong Haste", "itemgroup.mia": "Memento In Abyss", + "itemgroup.mia.section.artifacts": "Artifacts", + "itemgroup.mia.section.building": "Building Blocks", + "itemgroup.mia.section.functional": "Functional Blocks", + "itemgroup.mia.section.items": "Items", + "itemgroup.mia.section.natural": "Natural Blocks", "itemgroup.mia_artifact": "Memento In Abyss: Artifact", "key.categories.mia": "Memento In Abyss", "key.mia.skill_dial": "Skill Dial", diff --git a/src/main/java/com/altnoir/mia/MIA.java b/src/main/java/com/altnoir/mia/MIA.java index b34be87a..8622133e 100644 --- a/src/main/java/com/altnoir/mia/MIA.java +++ b/src/main/java/com/altnoir/mia/MIA.java @@ -1,11 +1,14 @@ package com.altnoir.mia; +import com.altnoir.abysslib.reginth.Reginth; import com.altnoir.mia.core.curse.CurseManager; import com.altnoir.mia.core.event.EventHandle; import com.altnoir.mia.core.spawner.AbyssTrialSpawnerManager; +import com.altnoir.mia.datagen.MiaLangData; import com.altnoir.mia.init.*; import com.altnoir.mia.init.worldgen.*; import com.mojang.logging.LogUtils; +import net.minecraft.resources.ResourceLocation; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; @@ -22,16 +25,49 @@ public class MIA { public static final String MOD_NAME = "Memento In Abyss"; public static final Logger LOGGER = LogUtils.getLogger(); + /** + * 注册框架实例(AbyssLib 的 Reginth,fork 自上游 Registrate)。 + *

+ * 1.21.1 线的 {@code Reginth.create()} 会**自行**从 {@code ModList} 找到本模组的 + * event bus 并挂上监听(26.1 线不会,那边要手调 {@code registerEventListeners}), + * 所以这里不需要额外注册。类就在 abysslib-1.21.1 的 jar 里,不要再 jarJar 上游 Registrate。 + *

+ * 方块/物品的分区归属由各自注册类用 {@code MIA.registrate().defaultCreativeSection(...)} + * 声明,所以这里**不**设全局默认标签页。 + */ + private static final Reginth REGINTH = Reginth.create(MOD_ID); + + public static Reginth registrate() { + return REGINTH; + } + + /** + * 本模组命名空间下的资源 id(与上游 Registrate 的 {@code modLoc} 等价)。 + */ + public static ResourceLocation asResource(String path) { + return ResourceLocation.fromNamespaceAndPath(MOD_ID, path); + } + public static final CurseManager CURSE_MANAGER = new CurseManager(); public static final AbyssTrialSpawnerManager SPAWNER_MANAGER = new AbyssTrialSpawnerManager(); public MIA(IEventBus modEventBus, ModContainer modContainer) { LOGGER.info("{} {}+{} initializing...", MOD_NAME, MiaBuildInfo.VERSION, MiaBuildInfo.GIT_COMMIT); + // 语言键:迁移到 Reginth 后 en_us.json 由 Reginth 独家写入,MIA 的键挂到它的 LANG provider 上。 + // 必须在这里(早于 datagen 事件)注册,否则 Reginth 的 provider 已经建好、加不进去了。 + MiaLangData.register(); + modEventBus.addListener(this::commonSetup); - MiaItems.register(modEventBus); - MiaBlocks.register(modEventBus); + // 物品也全部走 Reginth 了,MiaItems 里没有 DeferredRegister 需要注册; + // 但要和 MiaBlocks 一样在这里**显式加载**(同样因为注册表在类初始化时填充)。 + MiaItems.bootstrap(); + // MiaBlocks 不再需要注册:方块(含它们的 BlockItem)已经全部走 Reginth, + // Reginth.create(MOD_ID) 自己会把监听器挂到 mod event bus 上。 + // 但必须在这里**显式加载** MiaBlocks:它的注册表是在类初始化时(REGINTH 字段 + + // 每条 REGINTH.object(...))填充的,晚于 RegisterEvent 加载就等于方块全丢了。 + MiaBlocks.bootstrap(); MiaBlockEntities.register(modEventBus); MiaItemGroups.register(modEventBus); diff --git a/src/main/java/com/altnoir/mia/MiaItemGroups.java b/src/main/java/com/altnoir/mia/MiaItemGroups.java index d9b56bb6..1f60edd1 100644 --- a/src/main/java/com/altnoir/mia/MiaItemGroups.java +++ b/src/main/java/com/altnoir/mia/MiaItemGroups.java @@ -1,9 +1,13 @@ package com.altnoir.mia; +import com.altnoir.abysslib.creative.ALCreativeTabSection; +import com.altnoir.abysslib.creative.ALSectionedCreativeModeTab; +import com.altnoir.abysslib.creative.ALTitlePlate; import com.altnoir.mia.init.MiaBlocks; import com.altnoir.mia.init.MiaItems; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; import net.neoforged.bus.api.IEventBus; @@ -11,237 +15,324 @@ import java.util.function.Supplier; +/** + * MIA 的创造栏:**一个标签页 + 五个分区**(AbyssLib 的"分区式创造栏")。 + *

+ * 每个分区带一张 162×18 的整行横幅贴图({@code assets/mia/textures/gui/ctab/*.png},即 + * 原 {@code CTAB_*.png})。贴图里自带标题与底纹,所以渲染器不会再往横幅上叠代码文字 + * (见 {@code ALSectionedCreativeTabRenderer#drawFullRowTexture}),分区标题键因此只在无贴图时才会用到。 + *

+ * 为什么不用 {@code Reginth.defaultCreativeSection(...)} 那套自动登记:那套是在注册时 + * 往分区里塞一次条目,而 {@code ALSectionedCreativeModeTab.buildContents()} 每次重建标签页内容时 + * 都会先 {@code section.clear()},自动塞进去的条目会被清掉。所以这里统一走 populator 显式登记。 + *

+ * 旧的 {@code mia_tab_artifact} 标签页已经取消,遗物类内容并入 {@link #SECTION_ARTIFACTS}。 + */ public class MiaItemGroups { public static final DeferredRegister CREATIVE_MODE_TAB = DeferredRegister .create(Registries.CREATIVE_MODE_TAB, MIA.MOD_ID); + + /** + * 整行横幅贴图的资源路径前缀。 + */ + private static final String BANNER_DIR = "textures/gui/ctab/"; + + /** + * 分区横幅贴图 id。 + *

+ * {@code .png} 必须显式写上:{@code ALSectionedCreativeTabRenderer} 对非 {@code abysslib:} + * 命名空间的贴图走 {@code RenderSystem.setShaderTexture(0, loc)},也就是 MC 的 {@code SimpleTexture} + * 加载路径 —— 它把路径原样交给资源管理器,不会自己补 {@code .png}。 + * 少写扩展名会实测得到 + * {@code Failed to load texture: mia:textures/gui/ctab/building / FileNotFoundException}, + * 游戏里就是一块黑紫。 + *

+ * AbyssLib 侧({@code assetTexture()})现在也会补扩展名,所以两种写法都能跑; + * 这里保留 {@code .png} 是为了兼容已发布的 AbyssLib 1.0.0。 + */ + private static ResourceLocation banner(String name) { + return ResourceLocation.fromNamespaceAndPath(MIA.MOD_ID, BANNER_DIR + name + ".png"); + } + + // ---------------- 五个分区 ---------------- + // 横幅贴图是 64×18,占 4 格宽(左对齐),物品从同一行第 5 格开始排。 + + /** + * 横幅占的格数(1~9);MIA 的贴图是 64×18,这里按 4 格(72px)绘制。 + */ + private static final int BANNER_UNITS = 4; + + /** + * 分区标题底板:横幅贴图有渐变/花纹,白字直接压上去在浅色区域读不清,所以垫一层 25% 黑底。 + *

+ * AbyssLib 侧默认是 {@link ALTitlePlate#DISABLED 不启用},这里是 MIA 显式打开。 + * 想调淡/调深就改这一个值:{@code 0x33}≈20%、{@code 0x40}≈25%(当前)、{@code 0x59}≈35%; + * 要关掉整行改成 {@code ALTitlePlate.DISABLED} 即可。 + */ + private static final ALTitlePlate TITLE_PLATE = ALTitlePlate.argb(0x40000000); + + public static final ALCreativeTabSection SECTION_BUILDING = + new ALCreativeTabSection("itemgroup.mia.section.building", banner("building"), BANNER_UNITS) + .titlePlate(TITLE_PLATE); + public static final ALCreativeTabSection SECTION_NATURAL = + new ALCreativeTabSection("itemgroup.mia.section.natural", banner("natural"), BANNER_UNITS) + .titlePlate(TITLE_PLATE); + public static final ALCreativeTabSection SECTION_FUNCTIONAL = + new ALCreativeTabSection("itemgroup.mia.section.functional", banner("functional"), BANNER_UNITS) + .titlePlate(TITLE_PLATE); + public static final ALCreativeTabSection SECTION_ITEMS = + new ALCreativeTabSection("itemgroup.mia.section.items", banner("items"), BANNER_UNITS) + .titlePlate(TITLE_PLATE); + public static final ALCreativeTabSection SECTION_ARTIFACTS = + new ALCreativeTabSection("itemgroup.mia.section.artifacts", banner("artifacts"), BANNER_UNITS) + .titlePlate(TITLE_PLATE); + + // ---------------- 标签页 ---------------- + // 两个标签页都走 AbyssLib 的分区式创造栏:主标签页 4 个分区, + // 遗物标签页 1 个分区;每个分区各配一张 162×18 的整行横幅贴图。 + public static final Supplier MIA_TAB = CREATIVE_MODE_TAB.register("mia_tab", () -> - CreativeModeTab.builder() - .title(Component.translatable("itemgroup.mia")) - .icon(() -> new ItemStack(MiaItems.RED_WHISTLE.get())) - .displayItems((parameters, output) -> { - // decoration blocks - output.accept(MiaBlocks.COVERGRASS_ABYSS_ANDESITE); - output.accept(MiaBlocks.COVERGRASS_TUFF); - output.accept(MiaBlocks.ABYSS_ANDESITE); - output.accept(MiaBlocks.MARLITH); - output.accept(MiaBlocks.ABYSS_ANDESITE_STAIRS); - output.accept(MiaBlocks.ABYSS_ANDESITE_SLAB); - output.accept(MiaBlocks.ABYSS_ANDESITE_WALL); - output.accept(MiaBlocks.ABYSS_COBBLED_ANDESITE); - output.accept(MiaBlocks.ABYSS_COBBLED_ANDESITE_STAIRS); - output.accept(MiaBlocks.ABYSS_COBBLED_ANDESITE_SLAB); - output.accept(MiaBlocks.ABYSS_COBBLED_ANDESITE_WALL); - output.accept(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE); - output.accept(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_STAIRS); - output.accept(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_SLAB); - output.accept(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_WALL); - output.accept(MiaBlocks.POLISHED_ABYSS_ANDESITE); - output.accept(MiaBlocks.POLISHED_ABYSS_ANDESITE_STAIRS); - output.accept(MiaBlocks.POLISHED_ABYSS_ANDESITE_SLAB); - output.accept(MiaBlocks.POLISHED_ABYSS_ANDESITE_WALL); - output.accept(MiaBlocks.ABYSS_ANDESITE_PILLAR); - output.accept(MiaBlocks.ABYSS_ANDESITE_COLUMN); - output.accept(MiaBlocks.ABYSS_ANDESITE_BRICKS); - output.accept(MiaBlocks.CRACKED_ABYSS_ANDESITE_BRICKS); - output.accept(MiaBlocks.ABYSS_ANDESITE_BRICKS_STAIRS); - output.accept(MiaBlocks.ABYSS_ANDESITE_BRICKS_SLAB); - output.accept(MiaBlocks.ABYSS_ANDESITE_BRICKS_WALL); - output.accept(MiaBlocks.CHISLED_ABYSS_ANDESITE); - output.accept(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS); - output.accept(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_STAIRS); - output.accept(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_SLAB); - output.accept(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_WALL); - // 化石树 - output.accept(MiaBlocks.FOSSILIZED_LOG); - output.accept(MiaBlocks.FOSSILIZED_WOOD); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_LOG); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_WOOD); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_LOG); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_WOOD); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_LOG); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD); - output.accept(MiaBlocks.POLISHED_FOSSILIZED_WOOD); - output.accept(MiaBlocks.POLISHED_FOSSILIZED_WOOD_STAIRS); - output.accept(MiaBlocks.POLISHED_FOSSILIZED_WOOD_SLAB); - output.accept(MiaBlocks.POLISHED_FOSSILIZED_WOOD_WALL); - output.accept(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD); - output.accept(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_STAIRS); - output.accept(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_SLAB); - output.accept(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_WALL); - output.accept(MiaBlocks.CHISLED_STRIPPED_FOSSILIZED_WOOD); - output.accept(MiaBlocks.FOSSILIZED_WOOD_BRICKS); - output.accept(MiaBlocks.FOSSILIZED_WOOD_BRICKS_STAIRS); - output.accept(MiaBlocks.FOSSILIZED_WOOD_BRICKS_SLAB); - output.accept(MiaBlocks.FOSSILIZED_WOOD_BRICKS_WALL); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_STAIRS); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_SLAB); - output.accept(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_WALL); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_STAIRS); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_SLAB); - output.accept(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_WALL); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_STAIRS); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_SLAB); - output.accept(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_WALL); - - // 矿物 - output.accept(MiaBlocks.ABYSS_IRON_ORE); - output.accept(MiaBlocks.ABYSS_COPPER_ORE); - output.accept(MiaBlocks.ABYSS_GOLD_ORE); - output.accept(MiaBlocks.ABYSS_LAPIS_ORE); - output.accept(MiaBlocks.ABYSS_REDSTONE_ORE); - output.accept(MiaBlocks.ABYSS_DIAMOND_ORE); - output.accept(MiaBlocks.ABYSS_EMERALD_ORE); - output.accept(MiaBlocks.ABYSS_QUARTZ_ORE); - output.accept(MiaBlocks.ABYSS_CHLOROPHYTE_ORE); - output.accept(MiaBlocks.SUSPICIOUS_ABYSS_ANDESITE); - - output.accept(MiaBlocks.CHLOROPHYTE_BLOCK); - output.accept(MiaBlocks.RAW_CHLOROPHYTE_BLOCK); - output.accept(MiaItems.RAW_CHLOROPHYTE); - output.accept(MiaItems.CHLOROPHYTE_NUGGET); - output.accept(MiaItems.CHLOROPHYTE_INGOT); - // 翡翠 - output.accept(MiaBlocks.PRASIOLITE_BLOCK); - output.accept(MiaBlocks.BUDDING_PRASIOLITE); - output.accept(MiaBlocks.SMALL_PRASIOLITE_BUD); - output.accept(MiaBlocks.MEDIUM_PRASIOLITE_BUD); - output.accept(MiaBlocks.LARGE_PRASIOLITE_BUD); - output.accept(MiaBlocks.PRASIOLITE_CLUSTER); - output.accept(MiaBlocks.CAERULITE_BLOCK); - output.accept(MiaBlocks.BUDDING_CAERULITE); - output.accept(MiaBlocks.SMALL_CAERULITE_BUD); - output.accept(MiaBlocks.MEDIUM_CAERULITE_BUD); - output.accept(MiaBlocks.LARGE_CAERULITE_BUD); - output.accept(MiaBlocks.CAERULITE_CLUSTER); - output.accept(MiaItems.PRASIOLITE_SHARD); - output.accept(MiaItems.CAERULITE_SHARD); - output.accept(MiaItems.PRASIOLITE_PICKAXE); - output.accept(MiaItems.PRASIOLITE_HOE); - - - // woods - output.accept(MiaBlocks.SKYFOG_LOG); - output.accept(MiaBlocks.SKYFOG_WOOD); - output.accept(MiaBlocks.STRIPPED_SKYFOG_LOG); - output.accept(MiaBlocks.STRIPPED_SKYFOG_WOOD); - output.accept(MiaBlocks.SKYFOG_PLANKS); - output.accept(MiaBlocks.SKYFOG_STAIRS); - output.accept(MiaBlocks.SKYFOG_SLAB); - output.accept(MiaBlocks.SKYFOG_FENCE); - output.accept(MiaBlocks.SKYFOG_FENCE_GATE); - output.accept(MiaBlocks.SKYFOG_DOOR); - output.accept(MiaBlocks.SKYFOG_TRAPDOOR); - - output.accept(MiaBlocks.VERDANT_STEM); - output.accept(MiaBlocks.VERDANT_HYPHAE); - output.accept(MiaBlocks.STRIPPED_VERDANT_STEM); - output.accept(MiaBlocks.STRIPPED_VERDANT_HYPHAE); - output.accept(MiaBlocks.VERDANT_PLANKS); - output.accept(MiaBlocks.VERDANT_STAIRS); - output.accept(MiaBlocks.VERDANT_SLAB); - output.accept(MiaBlocks.VERDANT_FENCE); - output.accept(MiaBlocks.VERDANT_FENCE_GATE); - output.accept(MiaBlocks.VERDANT_DOOR); - output.accept(MiaBlocks.VERDANT_TRAPDOOR); - - output.accept(MiaBlocks.INVERTED_LOG); - output.accept(MiaBlocks.INVERTED_WOOD); - output.accept(MiaBlocks.STRIPPED_INVERTED_LOG); - output.accept(MiaBlocks.STRIPPED_INVERTED_WOOD); - output.accept(MiaBlocks.INVERTED_PLANKS); - output.accept(MiaBlocks.INVERTED_STAIRS); - output.accept(MiaBlocks.INVERTED_SLAB); - output.accept(MiaBlocks.INVERTED_FENCE); - output.accept(MiaBlocks.INVERTED_FENCE_GATE); - output.accept(MiaBlocks.INVERTED_DOOR); - output.accept(MiaBlocks.INVERTED_TRAPDOOR); - - output.accept(MiaBlocks.SKYFOG_LEAVES); - output.accept(MiaBlocks.SKYFOG_LEAVES_WITH_FRUITS); - output.accept(MiaBlocks.VERDANT_LEAVES); - output.accept(MiaBlocks.INVERTED_LEAVES); - output.accept(MiaBlocks.SKYFOG_SAPLING); - output.accept(MiaBlocks.VERDANT_FUNGUS); - output.accept(MiaBlocks.INVERTED_SAPLING); - - // 植物 - output.accept(MiaBlocks.MARGINAL_WEED); - output.accept(MiaBlocks.CRIMSON_VEILGRASS); - output.accept(MiaBlocks.SCORCHLEAF); - output.accept(MiaBlocks.FORTITUDE_FLOWER); - output.accept(MiaBlocks.REED); - output.accept(MiaBlocks.BALLOON_PLANT); - output.accept(MiaBlocks.LANTERN_PLANT); - output.accept(MiaBlocks.GREEN_PERILLA); - output.accept(MiaBlocks.KONJAC_ROOT); - output.accept(MiaBlocks.SILVEAF_FUNGUS); - - // 红石 - output.accept(MiaBlocks.SKYFOG_PRESSURE_PLATE); - output.accept(MiaBlocks.SKYFOG_BUTTON); - output.accept(MiaBlocks.VERDANT_PRESSURE_PLATE); - output.accept(MiaBlocks.VERDANT_BUTTON); - output.accept(MiaBlocks.INVERTED_PRESSURE_PLATE); - output.accept(MiaBlocks.INVERTED_BUTTON); - - // foods - output.accept(MiaItems.MISTFUZZ_PEACH); - output.accept(MiaItems.GLOOM_BERRY); - output.accept(MiaItems.DREAM_LICHEE); - - // tools - output.accept(MiaItems.RED_WHISTLE); - output.accept(MiaItems.BLUE_WHISTLE); - - output.accept(MiaItems.ROPE); - }) - .build()); + ALSectionedCreativeModeTab.configure( + CreativeModeTab.builder() + .title(Component.translatable("itemgroup.mia")) + .icon(() -> new ItemStack(MiaItems.RED_WHISTLE.get())), + MiaItemGroups::populate, + SECTION_BUILDING, SECTION_NATURAL, SECTION_FUNCTIONAL, SECTION_ITEMS + ).build()); public static final Supplier MIA_TAB_ARIFACT = CREATIVE_MODE_TAB.register("mia_tab_artifact", () -> - CreativeModeTab.builder() - .title(Component.translatable("itemgroup.mia_artifact")) - .icon(() -> new ItemStack(MiaItems.FANCY_ARTIFACT_BUNDLE.get())) - .displayItems((parameters, output) -> { - // artifacts - output.accept(MiaBlocks.ARTIFACT_SMITHING_TABLE); - output.accept(MiaBlocks.PRASIOLITE_LAMPTUBE); - output.accept(MiaBlocks.AMETHYST_LAMPTUBE); - output.accept(MiaBlocks.PEDESTAL); - output.accept(MiaBlocks.HOPPER_FARMLAND); - output.accept(MiaBlocks.SUN_STONE); - output.accept(MiaBlocks.CAVE_EXPLORER_BEACON); - output.accept(MiaBlocks.ENDLESS_CUP); - - output.accept(MiaItems.STAR_COMPASS); - output.accept(MiaBlocks.ABYSS_PORTAL_CORE); - output.accept(MiaBlocks.ABYSS_PORTAL_FRAME); - output.accept(MiaBlocks.ABYSS_SPAWNER); - - // item - output.accept(MiaItems.GRAY_ARTIFACT_BUNDLE); - output.accept(MiaItems.FANCY_ARTIFACT_BUNDLE); - output.accept(MiaItems.TEST_ARTIFACT_1); - output.accept(MiaItems.TEST_ARTIFACT_2); - output.accept(MiaItems.TEST_ARTIFACT_3); - output.accept(MiaItems.HEALTH_JUNKIE); - output.accept(MiaItems.ARTIFACT_HASTE); - output.accept(MiaItems.GRAPPLING_HOOK); - - // Weapons - output.accept(MiaItems.GROW_SWORD); - output.accept(MiaItems.BLAZE_REAP); - - // Misc - output.accept(MiaItems.PEACE_PHOBIA); - - // DEV - output.accept(MiaItems.DEBUG_ATTRIBUTE_TOOL); - output.accept(MiaBlocks.ABYSS_PORTAL); - }).build() - ); + ALSectionedCreativeModeTab.configure( + CreativeModeTab.builder() + .title(Component.translatable("itemgroup.mia_artifact")) + .icon(() -> new ItemStack(MiaItems.FANCY_ARTIFACT_BUNDLE.get())), + MiaItemGroups::populateArtifacts, + SECTION_ARTIFACTS + ).build()); + + private static void populate(CreativeModeTab.ItemDisplayParameters parameters) { + // ================= 建筑 ================= + // 深层安山岩 + SECTION_BUILDING.add(MiaBlocks.COVERGRASS_ABYSS_ANDESITE); + SECTION_BUILDING.add(MiaBlocks.COVERGRASS_TUFF); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE); + SECTION_BUILDING.add(MiaBlocks.MARLITH); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_STAIRS); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_SLAB); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_WALL); + // 圆石 + SECTION_BUILDING.add(MiaBlocks.ABYSS_COBBLED_ANDESITE); + SECTION_BUILDING.add(MiaBlocks.ABYSS_COBBLED_ANDESITE_STAIRS); + SECTION_BUILDING.add(MiaBlocks.ABYSS_COBBLED_ANDESITE_SLAB); + SECTION_BUILDING.add(MiaBlocks.ABYSS_COBBLED_ANDESITE_WALL); + // 苔石 + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_STAIRS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_SLAB); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_COBBLED_ANDESITE_WALL); + // 磨制 + SECTION_BUILDING.add(MiaBlocks.POLISHED_ABYSS_ANDESITE); + SECTION_BUILDING.add(MiaBlocks.POLISHED_ABYSS_ANDESITE_STAIRS); + SECTION_BUILDING.add(MiaBlocks.POLISHED_ABYSS_ANDESITE_SLAB); + SECTION_BUILDING.add(MiaBlocks.POLISHED_ABYSS_ANDESITE_WALL); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_PILLAR); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_COLUMN); + // 石砖 + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_BRICKS); + SECTION_BUILDING.add(MiaBlocks.CRACKED_ABYSS_ANDESITE_BRICKS); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.ABYSS_ANDESITE_BRICKS_WALL); + SECTION_BUILDING.add(MiaBlocks.CHISLED_ABYSS_ANDESITE); + // 苔石砖 + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.MOSSY_ABYSS_ANDESITE_BRICKS_WALL); + + // 化石树 + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_LOG); + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_LOG); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_LOG); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_LOG); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.POLISHED_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.POLISHED_FOSSILIZED_WOOD_STAIRS); + SECTION_BUILDING.add(MiaBlocks.POLISHED_FOSSILIZED_WOOD_SLAB); + SECTION_BUILDING.add(MiaBlocks.POLISHED_FOSSILIZED_WOOD_WALL); + SECTION_BUILDING.add(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_STAIRS); + SECTION_BUILDING.add(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_SLAB); + SECTION_BUILDING.add(MiaBlocks.POLISHED_STRIPPED_FOSSILIZED_WOOD_WALL); + SECTION_BUILDING.add(MiaBlocks.CHISLED_STRIPPED_FOSSILIZED_WOOD); + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_WOOD_BRICKS); + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_WOOD_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_WOOD_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.FOSSILIZED_WOOD_BRICKS_WALL); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_FOSSILIZED_WOOD_BRICKS_WALL); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.MOSSY_FOSSILIZED_WOOD_BRICKS_WALL); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_STAIRS); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_SLAB); + SECTION_BUILDING.add(MiaBlocks.MOSSY_STRIPPED_FOSSILIZED_WOOD_BRICKS_WALL); + + // 木材:天雾树 / 翠寂菌 / 倒悬树 + SECTION_BUILDING.add(MiaBlocks.SKYFOG_LOG); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_WOOD); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_SKYFOG_LOG); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_SKYFOG_WOOD); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_PLANKS); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_STAIRS); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_SLAB); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_FENCE); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_FENCE_GATE); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_DOOR); + SECTION_BUILDING.add(MiaBlocks.SKYFOG_TRAPDOOR); + + SECTION_BUILDING.add(MiaBlocks.VERDANT_STEM); + SECTION_BUILDING.add(MiaBlocks.VERDANT_HYPHAE); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_VERDANT_STEM); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_VERDANT_HYPHAE); + SECTION_BUILDING.add(MiaBlocks.VERDANT_PLANKS); + SECTION_BUILDING.add(MiaBlocks.VERDANT_STAIRS); + SECTION_BUILDING.add(MiaBlocks.VERDANT_SLAB); + SECTION_BUILDING.add(MiaBlocks.VERDANT_FENCE); + SECTION_BUILDING.add(MiaBlocks.VERDANT_FENCE_GATE); + SECTION_BUILDING.add(MiaBlocks.VERDANT_DOOR); + SECTION_BUILDING.add(MiaBlocks.VERDANT_TRAPDOOR); + + SECTION_BUILDING.add(MiaBlocks.INVERTED_LOG); + SECTION_BUILDING.add(MiaBlocks.INVERTED_WOOD); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_INVERTED_LOG); + SECTION_BUILDING.add(MiaBlocks.STRIPPED_INVERTED_WOOD); + SECTION_BUILDING.add(MiaBlocks.INVERTED_PLANKS); + SECTION_BUILDING.add(MiaBlocks.INVERTED_STAIRS); + SECTION_BUILDING.add(MiaBlocks.INVERTED_SLAB); + SECTION_BUILDING.add(MiaBlocks.INVERTED_FENCE); + SECTION_BUILDING.add(MiaBlocks.INVERTED_FENCE_GATE); + SECTION_BUILDING.add(MiaBlocks.INVERTED_DOOR); + SECTION_BUILDING.add(MiaBlocks.INVERTED_TRAPDOOR); + + // 矿物块 + SECTION_BUILDING.add(MiaBlocks.CHLOROPHYTE_BLOCK); + SECTION_BUILDING.add(MiaBlocks.RAW_CHLOROPHYTE_BLOCK); + SECTION_BUILDING.add(MiaBlocks.PRASIOLITE_BLOCK); + SECTION_BUILDING.add(MiaBlocks.CAERULITE_BLOCK); + SECTION_BUILDING.add(MiaBlocks.SUN_STONE); + + // ================= 自然 ================= + SECTION_NATURAL.add(MiaBlocks.ABYSS_IRON_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_COPPER_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_GOLD_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_LAPIS_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_REDSTONE_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_DIAMOND_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_EMERALD_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_QUARTZ_ORE); + SECTION_NATURAL.add(MiaBlocks.ABYSS_CHLOROPHYTE_ORE); + SECTION_NATURAL.add(MiaBlocks.SUSPICIOUS_ABYSS_ANDESITE); + + // 晶石 + SECTION_NATURAL.add(MiaBlocks.BUDDING_PRASIOLITE); + SECTION_NATURAL.add(MiaBlocks.SMALL_PRASIOLITE_BUD); + SECTION_NATURAL.add(MiaBlocks.MEDIUM_PRASIOLITE_BUD); + SECTION_NATURAL.add(MiaBlocks.LARGE_PRASIOLITE_BUD); + SECTION_NATURAL.add(MiaBlocks.PRASIOLITE_CLUSTER); + SECTION_NATURAL.add(MiaBlocks.BUDDING_CAERULITE); + SECTION_NATURAL.add(MiaBlocks.SMALL_CAERULITE_BUD); + SECTION_NATURAL.add(MiaBlocks.MEDIUM_CAERULITE_BUD); + SECTION_NATURAL.add(MiaBlocks.LARGE_CAERULITE_BUD); + SECTION_NATURAL.add(MiaBlocks.CAERULITE_CLUSTER); + + // 树叶与树苗 + SECTION_NATURAL.add(MiaBlocks.SKYFOG_LEAVES); + SECTION_NATURAL.add(MiaBlocks.SKYFOG_LEAVES_WITH_FRUITS); + SECTION_NATURAL.add(MiaBlocks.VERDANT_LEAVES); + SECTION_NATURAL.add(MiaBlocks.INVERTED_LEAVES); + SECTION_NATURAL.add(MiaBlocks.SKYFOG_SAPLING); + SECTION_NATURAL.add(MiaBlocks.VERDANT_FUNGUS); + SECTION_NATURAL.add(MiaBlocks.INVERTED_SAPLING); + + // 植物 + SECTION_NATURAL.add(MiaBlocks.MARGINAL_WEED); + SECTION_NATURAL.add(MiaBlocks.CRIMSON_VEILGRASS); + SECTION_NATURAL.add(MiaBlocks.SCORCHLEAF); + SECTION_NATURAL.add(MiaBlocks.FORTITUDE_FLOWER); + SECTION_NATURAL.add(MiaBlocks.REED); + SECTION_NATURAL.add(MiaBlocks.BALLOON_PLANT); + SECTION_NATURAL.add(MiaBlocks.LANTERN_PLANT); + SECTION_NATURAL.add(MiaBlocks.GREEN_PERILLA); + SECTION_NATURAL.add(MiaBlocks.KONJAC_ROOT); + SECTION_NATURAL.add(MiaBlocks.SILVEAF_FUNGUS); + SECTION_NATURAL.add(MiaBlocks.GLOOM_BERRY_PLANT); + SECTION_NATURAL.add(MiaBlocks.DREAM_LICHEE_PLANT); + + // ================= 功能 ================= + SECTION_FUNCTIONAL.add(MiaBlocks.ARTIFACT_SMITHING_TABLE); + SECTION_FUNCTIONAL.add(MiaBlocks.HOPPER_FARMLAND); + SECTION_FUNCTIONAL.add(MiaBlocks.PRASIOLITE_LAMPTUBE); + SECTION_FUNCTIONAL.add(MiaBlocks.AMETHYST_LAMPTUBE); + SECTION_FUNCTIONAL.add(MiaBlocks.PEDESTAL); + SECTION_FUNCTIONAL.add(MiaBlocks.CAVE_EXPLORER_BEACON); + SECTION_FUNCTIONAL.add(MiaBlocks.ENDLESS_CUP); + SECTION_FUNCTIONAL.add(MiaBlocks.ROPE); + + // 红石 + SECTION_FUNCTIONAL.add(MiaBlocks.SKYFOG_PRESSURE_PLATE); + SECTION_FUNCTIONAL.add(MiaBlocks.SKYFOG_BUTTON); + SECTION_FUNCTIONAL.add(MiaBlocks.VERDANT_PRESSURE_PLATE); + SECTION_FUNCTIONAL.add(MiaBlocks.VERDANT_BUTTON); + SECTION_FUNCTIONAL.add(MiaBlocks.INVERTED_PRESSURE_PLATE); + SECTION_FUNCTIONAL.add(MiaBlocks.INVERTED_BUTTON); + + // 深渊结构相关 + SECTION_FUNCTIONAL.add(MiaBlocks.ABYSS_PORTAL_CORE); + SECTION_FUNCTIONAL.add(MiaBlocks.ABYSS_PORTAL_FRAME); + SECTION_FUNCTIONAL.add(MiaBlocks.ABYSS_SPAWNER); + + // ================= 物品 ================= + SECTION_ITEMS.add(MiaItems.RAW_CHLOROPHYTE); + SECTION_ITEMS.add(MiaItems.CHLOROPHYTE_NUGGET); + SECTION_ITEMS.add(MiaItems.CHLOROPHYTE_INGOT); + SECTION_ITEMS.add(MiaItems.PRASIOLITE_SHARD); + SECTION_ITEMS.add(MiaItems.CAERULITE_SHARD); + SECTION_ITEMS.add(MiaItems.PRASIOLITE_PICKAXE); + SECTION_ITEMS.add(MiaItems.PRASIOLITE_HOE); + // 食物 + SECTION_ITEMS.add(MiaItems.MISTFUZZ_PEACH); + SECTION_ITEMS.add(MiaItems.GLOOM_BERRY); + SECTION_ITEMS.add(MiaItems.DREAM_LICHEE); + // 工具/杂项 + SECTION_ITEMS.add(MiaItems.RED_WHISTLE); + SECTION_ITEMS.add(MiaItems.BLUE_WHISTLE); + SECTION_ITEMS.add(MiaItems.STAR_COMPASS); + SECTION_ITEMS.add(MiaItems.PEACE_PHOBIA); + } + + private static void populateArtifacts(CreativeModeTab.ItemDisplayParameters parameters) { + // ================= 遗物 ================= + SECTION_ARTIFACTS.add(MiaItems.GRAY_ARTIFACT_BUNDLE); + SECTION_ARTIFACTS.add(MiaItems.FANCY_ARTIFACT_BUNDLE); + SECTION_ARTIFACTS.add(MiaItems.TEST_ARTIFACT_1); + SECTION_ARTIFACTS.add(MiaItems.TEST_ARTIFACT_2); + SECTION_ARTIFACTS.add(MiaItems.TEST_ARTIFACT_3); + SECTION_ARTIFACTS.add(MiaItems.HEALTH_JUNKIE); + SECTION_ARTIFACTS.add(MiaItems.ARTIFACT_HASTE); + SECTION_ARTIFACTS.add(MiaItems.GRAPPLING_HOOK); + SECTION_ARTIFACTS.add(MiaItems.GROW_SWORD); + SECTION_ARTIFACTS.add(MiaItems.BLAZE_REAP); + // DEV + SECTION_ARTIFACTS.add(MiaItems.DEBUG_ATTRIBUTE_TOOL); + SECTION_ARTIFACTS.add(MiaBlocks.ABYSS_PORTAL); + } public static void register(IEventBus eventBus) { CREATIVE_MODE_TAB.register(eventBus); diff --git a/src/main/java/com/altnoir/mia/datagen/BlockStateGen.java b/src/main/java/com/altnoir/mia/datagen/BlockStateGen.java new file mode 100644 index 00000000..4961fa17 --- /dev/null +++ b/src/main/java/com/altnoir/mia/datagen/BlockStateGen.java @@ -0,0 +1,695 @@ +package com.altnoir.mia.datagen; + +import com.altnoir.abysslib.reginth.providers.DataGenContext; +import com.altnoir.abysslib.reginth.providers.ReginthBlockstateProvider; +import com.altnoir.abysslib.reginth.providers.ReginthItemModelProvider; +import com.altnoir.mia.common.block.ColumnBlock; +import com.altnoir.mia.common.block.DoubleBerryblock; +import com.altnoir.mia.datagen.blockstate.MiaModelProvider; +import com.altnoir.mia.util.MiaUtil; +import net.minecraft.core.Direction; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.*; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.neoforged.neoforge.client.model.generators.ConfiguredModel; +import net.neoforged.neoforge.client.model.generators.ModelFile; +import net.neoforged.neoforge.client.model.generators.VariantBlockStateBuilder; + +import java.util.Map; +import java.util.function.Function; + +/** + * MIA 的方块模型/方块状态 datagen 助手(Reginth 版)。 + *

+ * 签名与 Reginth 的 {@code .blockstate(...)} 回调一致,所以用法是: + *

{@code
+ * REGINTH.object("skyfog_stairs")
+ *         .block(p -> new StairBlock(SKYFOG_PLANKS.get().defaultBlockState(), p))
+ *         .properties(p -> BlockBehaviour.Properties.ofFullCopy(SKYFOG_PLANKS.get()))
+ *         .blockstate((ctx, prov) -> BlockStateGen.stairs(ctx, prov, SKYFOG_PLANKS.get()))
+ *         .simpleItem()
+ *         .register();
+ * }
+ *

+ * 为什么要显式传"基准方块":楼梯/台阶/栅栏/墙/按钮/压力板这些的贴图来自**它们所属的那个方块** + * (例如 {@code skyfog_stairs} 用的是 {@code mia:block/skyfog_planks} 的贴图,而不是 + * {@code mia:block/skyfog_stairs})。旧的 {@code MiaBlockStateProvider} 里是靠 + * {@code stairsBlockWithItem(block, textureBlock)} 的第二个参数传的,这里保持同样做法, + * 避免用命名约定去猜({@code verdant_hyphae} 的对应物是 {@code verdant_stem},猜不出来)。 + *

+ * 物品模型:Reginth 的 {@code .simpleItem()} 会自动把物品模型 parent 指向该方块默认状态的模型, + * 所以 cubeAll / 楼梯 / 台阶 / 栅栏门 / 活板门 / 树叶 / 压力板**都不用管**; + * 只有栅栏、墙、按钮、门、树苗/植物这几类需要 {@link #fenceItem} / {@link #wallItem} / + * {@link #buttonItem} / {@link #doorItem} / {@link #bushItem} 显式覆盖。 + *

+ * 本类分成两半:上半是"简单 helper"(旧的 {@code stairsBlockWithItem} 那一批), + * 下半是 D 级 helper 的移植({@code mirroredBlock} / {@code columnBlock} / + * {@code variantPillarBlockWithItem} / {@code clusterBlock} / {@code createFlowerBed} …)。 + * D 级这批的模型部分直接复用原来的 {@link MiaModelProvider}(它的方法本来就收 + * {@code BlockStateProvider},而 {@code ReginthBlockstateProvider} 就是它的子类), + * 只有方块状态部分需要在这里用 {@code prov.} 重写一遍。 + */ +public final class BlockStateGen { + + /** + * 原 {@code MiaBlockStateProvider} / {@code columnBlock} 里那份模型的持有者。 + */ + private static final MiaModelProvider MODELS = new MiaModelProvider(); + + // The old provider emitted its two generated *template* models once, at the top of + // registerStatesAndModels(). Here they are emitted from their first consumer instead, + // so these flags make sure each is written exactly once per datagen run: calling + // ModelBuilder.withExistingParent twice for the same path APPENDS a second element. + private static boolean tsbTemplateEmitted = false; + private static boolean hopperTemplateEmitted = false; + + private BlockStateGen() { + } + + // ------------------------------------------------------------------ + // 简单 helper:方块状态 / 方块模型 + // ------------------------------------------------------------------ + + /** + * 原木/菌柄:轴向贴图,模型名 = 方块名。 + */ + public static void log(DataGenContext ctx, ReginthBlockstateProvider prov) { + prov.logBlock((RotatedPillarBlock) ctx.getEntry()); + } + + /** + * 木头/菌核:六面都用对应原木的侧面贴图。 + */ + public static void wood(DataGenContext ctx, ReginthBlockstateProvider prov, Block log) { + ResourceLocation texture = prov.blockTexture(log); + prov.axisBlock((RotatedPillarBlock) ctx.getEntry(), texture, texture); + } + + public static void stairs(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + ResourceLocation texture = prov.blockTexture(base); + prov.stairsBlock((StairBlock) ctx.getEntry(), texture, texture, texture); + } + + public static void slab(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + ResourceLocation texture = prov.blockTexture(base); + prov.slabBlock((SlabBlock) ctx.getEntry(), texture, texture, texture, texture); + } + + public static void fence(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + prov.fenceBlock((FenceBlock) ctx.getEntry(), prov.blockTexture(base)); + } + + public static void fenceGate(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + prov.fenceGateBlock((FenceGateBlock) ctx.getEntry(), prov.blockTexture(base)); + } + + public static void wall(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + prov.wallBlock((WallBlock) ctx.getEntry(), prov.blockTexture(base)); + } + + public static void pressurePlate(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + prov.pressurePlateBlock((PressurePlateBlock) ctx.getEntry(), prov.blockTexture(base)); + } + + public static void button(DataGenContext ctx, ReginthBlockstateProvider prov, Block base) { + prov.buttonBlock((ButtonBlock) ctx.getEntry(), prov.blockTexture(base)); + } + + /** + * 门:贴图取自身({@code _bottom} / {@code _top}),cutout 渲染层。 + */ + public static void door(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + ResourceLocation texture = prov.blockTexture(block); + prov.doorBlockWithRenderType((DoorBlock) block, extend(texture, "_bottom"), extend(texture, "_top"), "cutout"); + } + + /** + * 活板门:贴图取自身,cutout 渲染层。 + */ + public static void trapdoor(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + prov.trapdoorBlockWithRenderType((TrapDoorBlock) block, prov.blockTexture(block), true, "cutout"); + } + + /** + * 树叶:单贴图套原版 {@code block/leaves} 模板,cutout 渲染层。 + */ + public static void leaves(DataGenContext ctx, ReginthBlockstateProvider prov) { + leaves(ctx, prov, "cutout"); + } + + public static void leaves(DataGenContext ctx, ReginthBlockstateProvider prov, String renderType) { + Block block = ctx.getEntry(); + prov.simpleBlock(block, prov.models() + .singleTexture(ctx.getName(), prov.mcLoc("block/leaves"), "all", prov.blockTexture(block)) + .renderType(renderType)); + } + + /** + * 交叉模型(树苗、矮草、花等):贴图取自身,cutout 渲染层。 + */ + public static void bush(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + prov.simpleBlock(block, prov.models() + .cross(ctx.getName(), prov.blockTexture(block)) + .renderType("cutout")); + } + + private static ResourceLocation extend(ResourceLocation rl, String suffix) { + return ResourceLocation.fromNamespaceAndPath(rl.getNamespace(), rl.getPath() + suffix); + } + + // ------------------------------------------------------------------ + // D 级 helper 移植:方块状态 + // ------------------------------------------------------------------ + + /** + * 旧 {@code mirroredBlock}:cube_all + cube_mirrored_all 两个模型,方块状态里各出 0°/180°。 + */ + public static void mirrored(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + MODELS.mirroredBlockModel(prov, block); + prov.getVariantBuilder(block) + .partialState().addModels( + configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block))), + configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block) + "_mirrored")), + configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block)), 180), + configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block) + "_mirrored"), 180) + ); + } + + /** + * 旧 {@code pillarBlock}:轴向贴图,顶面用 {@code _top}。 + */ + public static void pillar(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + prov.axisBlock((RotatedPillarBlock) block, prov.blockTexture(block), extend(prov.blockTexture(block), "_top")); + } + + /** + * 旧 {@code columnBlock}:按 {@code COLUMN} 状态切 none/top/bottom/middle 四个模型。 + */ + public static void column(DataGenContext ctx, ReginthBlockstateProvider prov, + Block pillar, Block decoration) { + Block block = ctx.getEntry(); + MODELS.columnBlockModel(prov, block, pillar, decoration); + String blockPath = MiaUtil.getBlockPath(block); + prov.getVariantBuilder(block).forAllStates(state -> { + String suffix = switch (state.getValue(ColumnBlock.COLUMN)) { + case NONE -> ""; + case TOP -> "_top"; + case BOTTOM -> "_bottom"; + case MIDDLE -> "_middle"; + }; + return ConfiguredModel.builder() + .modelFile(prov.models().getExistingFile(prov.modLoc("block/" + blockPath + suffix))) + .build(); + }); + } + + /** + * 旧 {@code variantPillarBlockWithItem}:多个随机变体(贴图 {@code 0..n-1})。 + */ + public static void variantPillar(DataGenContext ctx, ReginthBlockstateProvider prov, + int variants) { + variantPillar(ctx, prov, variants, null); + } + + public static void variantPillar(DataGenContext ctx, ReginthBlockstateProvider prov, + int variants, int[] weights) { + Block block = ctx.getEntry(); + variantAxis(prov, (RotatedPillarBlock) block, block, extend(prov.blockTexture(block), "_top"), variants, weights); + } + + /** + * 旧 {@code variantAxisBlockWithItem}:轴向变体,侧面贴图取自 {@code variant}。 + */ + public static void variantAxis(DataGenContext ctx, ReginthBlockstateProvider prov, + Block variant, int variants) { + variantAxis(ctx, prov, variant, variants, null); + } + + public static void variantAxis(DataGenContext ctx, ReginthBlockstateProvider prov, + Block variant, int variants, int[] weights) { + variantAxis(prov, (RotatedPillarBlock) ctx.getEntry(), variant, null, variants, weights); + } + + private static void variantAxis(ReginthBlockstateProvider prov, RotatedPillarBlock block, Block side, + ResourceLocation end, int variants, int[] weights) { + ConfiguredModel[] yModels = new ConfiguredModel[variants]; + ConfiguredModel[] zModels = new ConfiguredModel[variants]; + ConfiguredModel[] xModels = new ConfiguredModel[variants]; + + for (int i = 0; i < variants; i++) { + ResourceLocation variantSide = MiaUtil.miaId("block/" + MiaUtil.getBlockPath(side) + i); + ResourceLocation topTexture = end != null ? end : variantSide; + + ModelFile model = prov.models().cubeColumn(MiaUtil.getBlockPath(block) + i, variantSide, topTexture); + ModelFile horizontalModel = prov.models() + .cubeColumnHorizontal(MiaUtil.getBlockPath(block) + "_horizontal" + i, variantSide, topTexture); + + int weight = weights != null ? weights[i] : 1; + + yModels[i] = new ConfiguredModel(model, 0, 0, false, weight); + zModels[i] = new ConfiguredModel(horizontalModel, 90, 0, false, weight); + xModels[i] = new ConfiguredModel(horizontalModel, 90, 90, false, weight); + } + + prov.getVariantBuilder(block) + .partialState().with(RotatedPillarBlock.AXIS, Direction.Axis.Y) + .setModels(yModels) + .partialState().with(RotatedPillarBlock.AXIS, Direction.Axis.Z) + .setModels(zModels) + .partialState().with(RotatedPillarBlock.AXIS, Direction.Axis.X) + .setModels(xModels); + } + + /** + * 旧 {@code clusterBlock}:交叉模型 + 六向 {@code FACING} 方块状态。 + */ + public static void cluster(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + ResourceLocation model = MODELS.crossModel(prov, block); + facing(prov, block, model); + } + + /** + * 旧 {@code lampTubeBlock}:模板模型 + 六向 {@code FACING}。 + */ + public static void lampTube(DataGenContext ctx, ReginthBlockstateProvider prov, + Block particle) { + Block block = ctx.getEntry(); + facing(prov, block, MODELS.lampTubeBlockModel(prov, block, particle)); + } + + /** + * 旧 {@code templateAllBlock(block)}:模板名 = 方块名。 + */ + public static void templateAll(DataGenContext ctx, ReginthBlockstateProvider prov) { + templateAll(ctx, prov, MiaUtil.getBlockPath(ctx.getEntry())); + } + + /** + * 旧 {@code templateAllBlock(block, templateModel)}。 + */ + public static void templateAll(DataGenContext ctx, ReginthBlockstateProvider prov, + String templateModel) { + Block block = ctx.getEntry(); + MODELS.customBlockModel(prov, block, templateModel); + base(prov, block); + } + + /** + * 旧 {@code coverGrassBlock(modelBlock, DeferredBlock)}:底面用 MIA 命名空间。 + */ + public static void coverGrass(DataGenContext ctx, ReginthBlockstateProvider prov, + Block bottom) { + coverGrass(ctx, prov, prov.modLoc("block/" + MiaUtil.getBlockPath(bottom))); + } + + /** + * 旧 {@code coverGrassBlock(modelBlock, Block)}:底面用原版命名空间。 + */ + public static void coverGrassVanilla(DataGenContext ctx, ReginthBlockstateProvider prov, + Block bottom) { + coverGrass(ctx, prov, prov.mcLoc("block/" + MiaUtil.getBlockPath(bottom))); + } + + private static void coverGrass(DataGenContext ctx, ReginthBlockstateProvider prov, + ResourceLocation bottomTexture) { + Block block = ctx.getEntry(); + // The old provider emitted this template once at the top of registerStatesAndModels(); + // now it is emitted from its only consumer, guarded to run once. + if (!tsbTemplateEmitted) { + tsbTemplateEmitted = true; + MODELS.templateTSBModel(prov); + } + String blockPath = MiaUtil.getBlockPath(block); + prov.models().withExistingParent(blockPath, prov.modLoc("block/template/cube_tsb")) + .texture("top", prov.modLoc("block/abyss_grass_block_top")) + .texture("side", prov.modLoc("block/" + blockPath + "_side")) + .texture("bottom", bottomTexture); + rotationY(prov, block); + } + + /** + * 旧 {@code baseBlockState}:单模型、无旋转。 + */ + public static void base(DataGenContext ctx, ReginthBlockstateProvider prov) { + base(prov, ctx.getEntry()); + } + + private static void base(ReginthBlockstateProvider prov, Block block) { + prov.getVariantBuilder(block).partialState() + .addModels(configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block)))); + } + + /** + * 旧 {@code rotationYBlockState}:0/90/180/270 四个变体。 + */ + public static void rotationY(DataGenContext ctx, ReginthBlockstateProvider prov) { + rotationY(prov, ctx.getEntry()); + } + + private static void rotationY(ReginthBlockstateProvider prov, Block block) { + ResourceLocation model = prov.modLoc("block/" + MiaUtil.getBlockPath(block)); + prov.getVariantBuilder(block).partialState().addModels( + configuredModel(prov, model), + configuredModel(prov, model, 90), + configuredModel(prov, model, 180), + configuredModel(prov, model, 270) + ); + } + + /** + * 旧 {@code moistureBlockState}:{@code MOISTURE} 0-6 用干模型、7 用 {@code _moist}。 + */ + public static void moisture(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + // see coverGrass(): the old provider emitted this template once, up front + if (!hopperTemplateEmitted) { + hopperTemplateEmitted = true; + MODELS.templateHopperFarmland(prov); + } + MODELS.hopperFarmBlockModel(prov, block); + VariantBlockStateBuilder builder = prov.getVariantBuilder(block); + IntegerProperty moisture = BlockStateProperties.MOISTURE; + for (int i = 0; i < 7; i++) { + builder.partialState().with(moisture, i) + .addModels(configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block)))); + } + builder.partialState().with(moisture, 7) + .addModels(configuredModel(prov, prov.modLoc("block/" + MiaUtil.getBlockPath(block) + "_moist"))); + } + + /** + * 旧 {@code abyssSpawnerBlockState}:按 {@code TRIAL_SPAWNER_STATE} 切模型。 + */ + public static void abyssSpawner(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + MODELS.abyssSpawnerBlockModel(prov, block); + String blockPath = MiaUtil.getBlockPath(block); + VariantBlockStateBuilder builder = prov.getVariantBuilder(block); + + Map suffixes = Map.of( + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.ACTIVE, "_active", + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.COOLDOWN, "", + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.EJECTING_REWARD, "_ejecting_reward", + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.INACTIVE, "", + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.WAITING_FOR_PLAYERS, "_active", + net.minecraft.world.level.block.entity.trialspawner.TrialSpawnerState.WAITING_FOR_REWARD_EJECTION, "_ejecting_reward" + ); + + for (var state : suffixes.keySet()) { + builder.partialState() + .with(BlockStateProperties.TRIAL_SPAWNER_STATE, state) + .modelForState() + .modelFile(prov.models().getExistingFile(prov.modLoc("block/" + blockPath + suffixes.get(state)))) + .addModel(); + } + } + + /** + * 旧 {@code ropeBlock}。 + */ + public static void rope(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + MODELS.ropeBlockModel(prov, block); + base(prov, block); + } + + /** + * 旧 {@code abyssPortalBlock}。 + */ + public static void abyssPortal(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + MODELS.abyssPortalBlockModel(prov, block); + base(prov, block); + } + + /** + * 旧 {@code abyssPortalCoreBlock}。 + */ + public static void abyssPortalCore(DataGenContext ctx, ReginthBlockstateProvider prov, + Block frame) { + Block block = ctx.getEntry(); + MODELS.abyssPortalCoreModel(prov, block, frame); + base(prov, block); + } + + /** + * 旧 {@code artifactSmithingTableBlock}。 + */ + public static void artifactSmithingTable(DataGenContext ctx, + ReginthBlockstateProvider prov, Block bottom) { + Block block = ctx.getEntry(); + MODELS.artifactSmithingTableBlockModel(prov, block, bottom); + base(prov, block); + } + + /** + * 旧 {@code pedestalBlock}。 + */ + public static void pedestal(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + MODELS.pedestalBlockModel(prov, block); + base(prov, block); + } + + /** + * 旧 {@code createDoublePlant}:上下半格各一个交叉模型。 + */ + public static void doublePlant(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + ResourceLocation topModel = MODELS.crossModel(prov, block, "_top"); + ResourceLocation bottomModel = MODELS.crossModel(prov, block, "_bottom"); + prov.getVariantBuilder(block) + .partialState().with(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.LOWER) + .modelForState().modelFile(prov.models().getExistingFile(bottomModel)).addModel() + .partialState().with(BlockStateProperties.DOUBLE_BLOCK_HALF, DoubleBlockHalf.UPPER) + .modelForState().modelFile(prov.models().getExistingFile(topModel)).addModel(); + } + + /** + * 旧 {@code createDoubleBerry}:按半格 + {@code AGE} 选模型。 + */ + public static void doubleBerry(DataGenContext ctx, ReginthBlockstateProvider prov, + int maxAge) { + Block block = ctx.getEntry(); + for (int age = 0; age <= maxAge; age++) { + MODELS.crossModel(prov, block, "_bottom" + age); + } + for (int age = 2; age <= maxAge; age++) { + MODELS.crossModel(prov, block, "_top" + age); + } + prov.getVariantBuilder(block).forAllStates(state -> { + DoubleBlockHalf half = state.getValue(BlockStateProperties.DOUBLE_BLOCK_HALF); + int age = state.getValue(DoubleBerryblock.AGE); + String modelName = half == DoubleBlockHalf.UPPER && age >= 2 + ? MiaUtil.getBlockPath(block) + "_top" + age + : MiaUtil.getBlockPath(block) + "_bottom" + age; + return new ConfiguredModel[]{new ConfiguredModel(prov.models().getExistingFile(prov.modLoc("block/" + modelName)))}; + }); + } + + /** + * 旧 {@code createFlowerBed}:{@code FLOWER_AMOUNT} × {@code HORIZONTAL_FACING} 的 multipart。 + */ + public static void flowerBed(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + ResourceLocation[] bedModels = MODELS.flowerbedModels(prov, block); + var builder = prov.getMultipartBuilder(block); + Integer[][] amounts = {{1, 2, 3, 4}, {2, 3, 4}, {3, 4}, {4}}; + Direction[] facings = {Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; + int[] rotations = {0, 90, 180, 270}; + for (int model = 0; model < 4; model++) { + for (int f = 0; f < 4; f++) { + builder.part().modelFile(prov.models().getExistingFile(bedModels[model])) + .rotationY(rotations[f]).addModel() + .condition(BlockStateProperties.FLOWER_AMOUNT, amounts[model]) + .condition(BlockStateProperties.HORIZONTAL_FACING, facings[f]) + .end(); + } + } + } + + /** + * 旧 {@code createBrushableBlock}:按 {@code DUSTED} 切 {@code cubeAll} 模型。 + */ + public static void brushable(DataGenContext ctx, ReginthBlockstateProvider prov) { + Block block = ctx.getEntry(); + prov.getVariantBuilder(block).forAllStates(state -> { + String suffix = "_" + state.getValue(BlockStateProperties.DUSTED); + ModelFile model = prov.models().cubeAll( + MiaUtil.getBlockPath(block) + suffix, + prov.modLoc("block/" + MiaUtil.getBlockPath(block) + suffix)); + return ConfiguredModel.builder().modelFile(model).build(); + }); + } + + /** + * 旧 {@code makeCropBlock} / {@code states}:按 {@code AGE} 切 {@code block/crop} 模型。 + */ + public static void crop(DataGenContext ctx, ReginthBlockstateProvider prov, String texture) { + CropBlock cropBlock = ctx.getEntry(); + Function function = state -> new ConfiguredModel[]{ + new ConfiguredModel(prov.models() + .crop(ctx.getName() + state.getValue(CropBlock.AGE), + MiaUtil.miaId("block/" + texture + state.getValue(CropBlock.AGE))) + .renderType("cutout")) + }; + prov.getVariantBuilder(cropBlock).forAllStates(function); + } + + private static void facing(ReginthBlockstateProvider prov, Block block, ResourceLocation model) { + ModelFile file = prov.models().getExistingFile(model); + prov.getVariantBuilder(block) + .partialState().with(BlockStateProperties.FACING, Direction.DOWN) + .modelForState().modelFile(file).rotationX(180).addModel() + .partialState().with(BlockStateProperties.FACING, Direction.UP) + .modelForState().modelFile(file).addModel() + .partialState().with(BlockStateProperties.FACING, Direction.NORTH) + .modelForState().modelFile(file).rotationX(90).addModel() + .partialState().with(BlockStateProperties.FACING, Direction.SOUTH) + .modelForState().modelFile(file).rotationX(90).rotationY(180).addModel() + .partialState().with(BlockStateProperties.FACING, Direction.WEST) + .modelForState().modelFile(file).rotationX(90).rotationY(270).addModel() + .partialState().with(BlockStateProperties.FACING, Direction.EAST) + .modelForState().modelFile(file).rotationX(90).rotationY(90).addModel(); + } + + private static ConfiguredModel configuredModel(ReginthBlockstateProvider prov, ResourceLocation model) { + return configuredModel(prov, model, 0); + } + + private static ConfiguredModel configuredModel(ReginthBlockstateProvider prov, ResourceLocation model, int rotationY) { + return new ConfiguredModel(prov.models().getExistingFile(model), 0, rotationY, false); + } + + // ------------------------------------------------------------------ + // 物品模型(只有这几类不能靠 .simpleItem() 自动生成) + // ------------------------------------------------------------------ + + /** + * 栅栏物品:{@code minecraft:block/fence_inventory} + texture。 + */ + public static void fenceItem(DataGenContext ctx, ReginthItemModelProvider prov, Block base) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("block/fence_inventory")) + .texture("texture", blockTexture(prov, base)); + } + + /** + * 墙物品:{@code minecraft:block/wall_inventory} + wall 贴图槽。 + */ + public static void wallItem(DataGenContext ctx, ReginthItemModelProvider prov, Block base) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("block/wall_inventory")) + .texture("wall", blockTexture(prov, base)); + } + + /** + * 按钮物品:{@code minecraft:block/button_inventory} + texture。 + */ + public static void buttonItem(DataGenContext ctx, ReginthItemModelProvider prov, Block base) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("block/button_inventory")) + .texture("texture", blockTexture(prov, base)); + } + + /** + * 门物品:平面贴图({@code mia:item/}),不是方块模型。 + */ + public static void doorItem(DataGenContext ctx, ReginthItemModelProvider prov) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("item/generated")) + .texture("layer0", prov.modLoc("item/" + ctx.getName())); + } + + /** + * ItemModelProvider 没有 {@code blockTexture(Block)}(那是 BlockStateProvider 的),自己按注册名拼。 + */ + private static ResourceLocation blockTexture(ReginthItemModelProvider prov, Block block) { + return prov.modLoc("block/" + BuiltInRegistries.BLOCK.getKey(block).getPath()); + } + + /** + * 树苗/植物/晶簇物品:平面贴图,但用的是**方块**贴图 {@code mia:block/}。 + */ + public static void bushItem(DataGenContext ctx, ReginthItemModelProvider prov) { + bushItem(ctx, prov, ""); + } + + /** + * 同上,但贴图带后缀(双格植物用 {@code _top})。 + */ + public static void bushItem(DataGenContext ctx, ReginthItemModelProvider prov, + String suffix) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("item/generated")) + .texture("layer0", prov.modLoc("block/" + ctx.getName() + suffix)); + } + + /** + * 等价于旧 {@code blockItem(block)}:parent 指向同名方块模型。 + */ + public static void itemParent(DataGenContext ctx, ReginthItemModelProvider prov) { + itemParent(ctx, prov, ""); + } + + /** + * 等价于旧 {@code blockItem(block, suffix)}:parent 指向 {@code mia:block/}。 + */ + public static void itemParent(DataGenContext ctx, ReginthItemModelProvider prov, + String suffix) { + prov.withExistingParent(ctx.getName(), prov.modLoc("block/" + ctx.getName() + suffix)); + } + + /** + * 等价于旧 {@code aloneItem(block)}:平面贴图 {@code mia:item/}。 + */ + public static void aloneItem(DataGenContext ctx, ReginthItemModelProvider prov) { + // parent is minecraft:item/generated -- the old code used MiaUtil.id(), which is the + // vanilla namespace, NOT modLoc(). + prov.withExistingParent(ctx.getName(), prov.mcLoc("item/generated")) + .texture("layer0", prov.modLoc("item/" + ctx.getName())); + } + + /** + * 技能物品:{@code minecraft:item/generated} + {@code mia:item/skill/}。 + */ + public static void skillItem(DataGenContext ctx, ReginthItemModelProvider prov) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("item/generated")) + .texture("layer0", prov.modLoc("item/skill/" + ctx.getName())); + } + + /** + * 手持物品(剑/镐/锄等):parent 用 {@code minecraft:item/handheld}(不是 item/generated)。 + */ + public static void handheldItem(DataGenContext ctx, ReginthItemModelProvider prov) { + prov.withExistingParent(ctx.getName(), prov.mcLoc("item/handheld")) + .texture("layer0", prov.modLoc("item/" + ctx.getName())); + } + + /** + * 用 {@code mia:item/template/