From f3af08639afbfb86200d30ac9d5ca7482b4c2050 Mon Sep 17 00:00:00 2001 From: HongweiYang <761807812@qq.com> Date: Sat, 3 Oct 2026 01:28:59 -0700 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E6=8E=A5=E7=AE=A1LSO=E6=B8=A9?= =?UTF-8?q?=E5=BA=A6=E6=9C=BA=E5=88=B6=EF=BC=8C=E8=BF=9B=E4=B8=80=E6=AD=A5?= =?UTF-8?q?=E5=AE=8C=E5=96=84Astral=E7=8E=AF=E5=A2=83=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/assets/ctnhcore/lang/en_ud.json | 12 ++ .../resources/assets/ctnhcore/lang/en_us.json | 12 ++ .../resources/assets/ctnhcore/lang/zh_cn.json | 12 ++ .../cpearl0/ctnhcore/common/CommonProxy.java | 3 +- .../multiblock/UnderfloorHeatingMachine.java | 45 ++--- .../multiblock/electric/BioMachine.java | 9 +- .../electric/FermentingTankMachine.java | 9 +- ...ndustrialPrimitiveBlastFurnaceMachine.java | 7 +- .../machine/trait/UnderfloorHeatingTrait.java | 107 +++++++++++ .../event/ForgeClientEventHandler.java | 13 ++ .../ctnhcore/event/ForgeEventHandler.java | 8 - .../integration/legendary/ArmorModifier.java | 32 ---- .../EnvironmentTemperatureIntegration.java | 62 +++++++ .../PlayerTemperatureIntegration.java | 70 ++++++++ .../ThermometerEnvironmentIntegration.java | 168 ++++++++++++++++++ .../UnderfloorHeatingSystemTempModifier.java | 32 ---- .../AltitudeModifierMixin.java | 21 --- .../ClientTemperatureEffectsMixin.java | 27 +++ .../ModCapabilitiesMixin.java | 27 +++ .../TemperatureCommandMixin.java | 28 +++ .../TemperatureItemCapabilityMixin.java | 43 +++++ .../ThermometerItemMixin.java | 47 +++++ .../CTNHTemperatureModifierRegister.java | 22 --- .../registry/machines/GTMachineModify.java | 20 +-- .../machines/multiblock/MultiblocksA.java | 45 +---- src/main/resources/ctnhcore.mixins.json | 6 +- 26 files changed, 677 insertions(+), 210 deletions(-) create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java delete mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ArmorModifier.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/PlayerTemperatureIntegration.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java delete mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/UnderfloorHeatingSystemTempModifier.java delete mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/AltitudeModifierMixin.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ClientTemperatureEffectsMixin.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ModCapabilitiesMixin.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureCommandMixin.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java delete mode 100644 src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTemperatureModifierRegister.java diff --git a/src/generated/resources/assets/ctnhcore/lang/en_ud.json b/src/generated/resources/assets/ctnhcore/lang/en_ud.json index 1a64dd1db..cc41e32cf 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_ud.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_ud.json @@ -1195,6 +1195,7 @@ "item.ctnhcore.enriched_thorium_nugget": "ʇǝbbnN ɯnıɹoɥ⟘ pǝɥɔıɹuƎ", "item.ctnhcore.enriched_uranium": "ɯnıuɐɹ∩ pǝɥɔıɹuƎ", "item.ctnhcore.enriched_uranium_nugget": "ʇǝbbnN ɯnıuɐɹ∩ pǝɥɔıɹuƎ", + "item.ctnhcore.environment_detector": "ɹoʇɔǝʇǝᗡ ʇuǝɯuoɹıʌuƎ", "item.ctnhcore.galaxy_meatball": "ןןɐqʇɐǝW ʎxɐןɐ⅁", "item.ctnhcore.general_circuit_ev": "ΛƎ ʇınɔɹıƆ ןɐɹǝuǝ⅁", "item.ctnhcore.general_circuit_hv": "ΛH ʇınɔɹıƆ ןɐɹǝuǝ⅁", @@ -2000,6 +2001,15 @@ "material.ctnhcore.zr_hf_chloride": "ǝpıɹoןɥƆ ɟH ɹZ", "material.ctnhcore.zr_hf_oxy_chloride": "ǝpıɹoןɥƆ ʎxO ɟH ɹZ", "material.ctnhcore.zr_hf_separation_mix": "xıW uoıʇɐɹɐdǝS ɟH ɹZ", + "message.ctnhcore.thermometer.composition": ":)ǝɹɐɥs / ǝɹnssǝɹd ןɐıʇɹɐd( uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇⱯ", + "message.ctnhcore.thermometer.gas": "%3$s%% / ɯʇɐ %2$s :%1$s ", + "message.ctnhcore.thermometer.header": "sbuıpɐǝɹ ʇuǝɯuoɹıʌuƎ", + "message.ctnhcore.thermometer.location": "]%4$s '%3$s '%2$s[ %1$s :uoıʇɐɔoꞀ", + "message.ctnhcore.thermometer.pressure": "ɯʇɐ %s :ǝɹnssǝɹd ןɐʇo⟘", + "message.ctnhcore.thermometer.temperature": "Ɔ° %s :ǝɹnʇɐɹǝdɯǝʇ ʇuǝıqɯⱯ", + "message.ctnhcore.thermometer.thermal_status": "%2$s%% ɐıɯɹǝɥʇɹǝdʎɥ / %1$s%% ɐıɯɹǝɥʇodʎɥ :ǝɹnsodxǝ ןɐɯɹǝɥʇ ɹǝʎɐןԀ", + "message.ctnhcore.thermometer.unlisted": "sǝsɐb pǝıɟıɔǝdsu∩", + "message.ctnhcore.thermometer.vacuum": "sǝsɐb ou :ɯnnɔɐΛ", "multiblock.ctnh.nuclear_reactor.consume_amount": "s/ᗺɯ %s :ǝʇɐɹ uoıʇdɯnsuoɔ ʇuɐןooƆ", "multiblock.ctnh.nuclear_reactor.coolant": "%s :ʇuɐןooƆ", "multiblock.ctnh.nuclear_reactor.coolant_amount": "ᗺɯ %s :ʇunoɯɐ ʇuɐןooƆ", @@ -2044,5 +2054,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": "ʎןןɐuoıʇıpuoɔun ʇɥbıןɟ ǝʌıʇɐǝɹɔ pǝʇuɐɹb ǝɹɐ sɹǝʎɐןԀ - ", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": "ʇıɯıן ǝɔuɐʇsıp ou ǝʌɐɥ sʇuıoԀ ssǝɔɔⱯ ssǝןǝɹıM ƎW - ", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": "uoıʇɔunɟ ʇou op sɹoʇɐɹǝuǝb puıʍ puɐ sןǝuɐd ɹɐןoS - ", + "tooltip.ctnhcore.thermometer.environment": "snʇɐʇs ןɐɯɹǝɥʇ puɐ uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇɐ ɹoɟ ʞɐǝus ؛ǝɹnʇɐɹǝdɯǝʇ ɹoɟ ɹıɐ ǝɥʇ uı ʞɔıןɔ-ʇɥbıᴚ", + "tooltip.ctnhcore.thermometer.readings": "puoɔǝs ɹǝd uɐɔs ǝuo ؛ʇɐɥɔ uı ɹɐǝddɐ sbuıpɐǝᴚ", "zenith_machine_sp": "¡buıpןǝıʎu∩ spuɐʇS uoɔɐǝᗺ ɔıuoısԀ ǝɥ⟘ϛ§" } \ No newline at end of file diff --git a/src/generated/resources/assets/ctnhcore/lang/en_us.json b/src/generated/resources/assets/ctnhcore/lang/en_us.json index f2d7efe35..220e0ab29 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_us.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_us.json @@ -1195,6 +1195,7 @@ "item.ctnhcore.enriched_thorium_nugget": "Enriched Thorium Nugget", "item.ctnhcore.enriched_uranium": "Enriched Uranium", "item.ctnhcore.enriched_uranium_nugget": "Enriched Uranium Nugget", + "item.ctnhcore.environment_detector": "Environment Detector", "item.ctnhcore.galaxy_meatball": "Galaxy Meatball", "item.ctnhcore.general_circuit_ev": "General Circuit EV", "item.ctnhcore.general_circuit_hv": "General Circuit HV", @@ -2000,6 +2001,15 @@ "material.ctnhcore.zr_hf_chloride": "Zr Hf Chloride", "material.ctnhcore.zr_hf_oxy_chloride": "Zr Hf Oxy Chloride", "material.ctnhcore.zr_hf_separation_mix": "Zr Hf Separation Mix", + "message.ctnhcore.thermometer.composition": "Atmospheric composition (partial pressure / share):", + "message.ctnhcore.thermometer.gas": " %1$s: %2$s atm / %3$s%%", + "message.ctnhcore.thermometer.header": "Environment readings", + "message.ctnhcore.thermometer.location": "Location: %1$s [%2$s, %3$s, %4$s]", + "message.ctnhcore.thermometer.pressure": "Total pressure: %s atm", + "message.ctnhcore.thermometer.temperature": "Ambient temperature: %s °C", + "message.ctnhcore.thermometer.thermal_status": "Player thermal exposure: hypothermia %1$s%% / hyperthermia %2$s%%", + "message.ctnhcore.thermometer.unlisted": "Unspecified gases", + "message.ctnhcore.thermometer.vacuum": "Vacuum: no gases", "multiblock.ctnh.nuclear_reactor.consume_amount": "Coolant consumption rate: %s mB/s", "multiblock.ctnh.nuclear_reactor.coolant": "Coolant: %s", "multiblock.ctnh.nuclear_reactor.coolant_amount": "Coolant amount: %s mB", @@ -2044,5 +2054,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": " - Players are granted creative flight unconditionally", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": " - ME Wireless Access Points have no distance limit", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": " - Solar panels and wind generators do not function", + "tooltip.ctnhcore.thermometer.environment": "Right-click in the air for temperature; sneak for atmospheric composition and thermal status", + "tooltip.ctnhcore.thermometer.readings": "Readings appear in chat; one scan per second", "zenith_machine_sp": "§5The Psionic Beacon Stands Unyielding!" } \ No newline at end of file diff --git a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json index d3314ea89..167316e58 100644 --- a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json +++ b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json @@ -1266,6 +1266,7 @@ "item.ctnhcore.enriched_thorium_nugget": "浓缩钍粒", "item.ctnhcore.enriched_uranium": "浓缩铀", "item.ctnhcore.enriched_uranium_nugget": "浓缩铀粒", + "item.ctnhcore.environment_detector": "环境检测器", "item.ctnhcore.galaxy_meatball": "银河肉丸", "item.ctnhcore.general_circuit_ev": "EV级电路板", "item.ctnhcore.general_circuit_hv": "HV级电路板", @@ -2068,6 +2069,15 @@ "material.ctnhcore.zr_hf_chloride": "锆-铪氯化物", "material.ctnhcore.zr_hf_oxy_chloride": "锆-铪氯氧化物", "material.ctnhcore.zr_hf_separation_mix": "锆-铪混合物分离液", + "message.ctnhcore.thermometer.composition": "大气成分(分压 / 占比):", + "message.ctnhcore.thermometer.gas": " %1$s:%2$s atm / %3$s%%", + "message.ctnhcore.thermometer.header": "环境检测读数", + "message.ctnhcore.thermometer.location": "位置:%1$s [%2$s, %3$s, %4$s]", + "message.ctnhcore.thermometer.pressure": "总压:%s atm", + "message.ctnhcore.thermometer.temperature": "环境温度:%s ℃", + "message.ctnhcore.thermometer.thermal_status": "玩家冷热累积:失温 %1$s%% / 热射病 %2$s%%", + "message.ctnhcore.thermometer.unlisted": "未描述气体", + "message.ctnhcore.thermometer.vacuum": "真空:无气体", "multiblock.ctnh.nuclear_reactor.consume_amount": "冷却液消耗率:%s mB/s", "multiblock.ctnh.nuclear_reactor.coolant": "冷却液:%s", "multiblock.ctnh.nuclear_reactor.coolant_amount": "冷却液量:%s mB", @@ -2118,5 +2128,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": " - 玩家无条件获得创造飞行", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": " - ME无线访问点无距离限制", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": " - 光伏、风力发电机无法工作", + "tooltip.ctnhcore.thermometer.environment": "对空气右键测温;潜行右键查询大气成分与冷热状态", + "tooltip.ctnhcore.thermometer.readings": "读数显示在聊天栏,每秒可检测一次", "zenith_machine_sp": "§5灵能灯塔屹立不倒!" } \ No newline at end of file diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/CommonProxy.java b/src/main/java/io/github/cpearl0/ctnhcore/common/CommonProxy.java index 7d00294b3..d70ebf0f5 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/CommonProxy.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/CommonProxy.java @@ -11,6 +11,7 @@ import io.github.cpearl0.ctnhcore.data.recipe.RecipeRemoval; import io.github.cpearl0.ctnhcore.data.tags.*; import io.github.cpearl0.ctnhcore.data.worldgen.CTNHBiomeModifiers; +import io.github.cpearl0.ctnhcore.integration.legendary.EnvironmentTemperatureIntegration; import io.github.cpearl0.ctnhcore.registry.*; import io.github.cpearl0.ctnhcore.registry.adventure.CTNHEnchantments; import io.github.cpearl0.ctnhcore.registry.jade.CTNHJadePlugin; @@ -74,7 +75,6 @@ public static void init() { CTNHRegistration.REGISTRATE.registerRegistrate(); CTNHEnchantments.Enchantments.register(modEventBus); CTNHRecipes.init(modEventBus); - CTNHTemperatureModifierRegister.init(); CTNHCoreDatagen.init(); CTNHConfig.init(); CTNHDamageTypes.init(); @@ -106,6 +106,7 @@ public static void registerRecipeConditions(GTCEuAPI.RegisterEvent GTToolType.KNIFE.itemTags.addAll(List.of( diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/UnderfloorHeatingMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/UnderfloorHeatingMachine.java index e71c43b8f..a0a87f064 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/UnderfloorHeatingMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/UnderfloorHeatingMachine.java @@ -1,5 +1,7 @@ package io.github.cpearl0.ctnhcore.common.machine.multiblock; +import io.github.cpearl0.ctnhcore.common.machine.trait.UnderfloorHeatingTrait; + import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; import com.gregtechceu.gtceu.api.machine.feature.multiblock.IDisplayUIMachine; import com.gregtechceu.gtceu.api.machine.multiblock.RecipeMultiblockMachine; @@ -8,11 +10,9 @@ import com.lowdragmc.lowdraglib.gui.widget.ComponentPanelWidget; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.Style; -import net.minecraft.util.Mth; import net.minecraft.world.level.block.WeatheringCopper; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.levelgen.structure.BoundingBox; @@ -22,8 +22,6 @@ import com.ctnhlang.EN; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.CopperBlockSet; -import lombok.Getter; -import org.jetbrains.annotations.NotNull; import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; import java.util.List; @@ -50,14 +48,9 @@ public class UnderfloorHeatingMachine extends RecipeMultiblockMachine implements @EN("Steam consumption rate: %d") public static Lang underfloorHeatingSystemInfoSteamConsumption; - @Getter - public int rate = 100; - public double steam_consumption_default = 8; - - public static final String RATE = "rate"; - public UnderfloorHeatingMachine(IMachineBlockEntity holder) { super(holder); + attachPersistentTrait("heating", new UnderfloorHeatingTrait(this)); } public double getEfficiency() { @@ -107,14 +100,17 @@ public double getEfficiency() { .get().getName()); return b1 || b; }).count(); - return (copper_shingles + exposed_copper_shingles * 0.8 + weathered_copper_shingles * 0.75 + + int total = copper_shingles + exposed_copper_shingles + weathered_copper_shingles + oxidized_copper_shingles; + return total == 0 ? 0.0 : (copper_shingles + exposed_copper_shingles * 0.8 + weathered_copper_shingles * 0.75 + oxidized_copper_shingles * 0.6) / - (copper_shingles + exposed_copper_shingles + weathered_copper_shingles + oxidized_copper_shingles); + total; } public void addDisplayText(List textList) { IDisplayUIMachine.super.addDisplayText(textList); if (isFormed()) { + var heating = getTraitOrThrow(UnderfloorHeatingTrait.class); + int rate = heating.getRate(); if (!isWorkingEnabled()) { textList.add(Component.translatable("gtceu.multiblock.work_paused")); @@ -135,7 +131,7 @@ public void addDisplayText(List textList) { .setStyle(Style.EMPTY.withColor(ChatFormatting.RED))); } textList.add(underfloorHeatingSystemInfoSteamConsumption.translate( - String.format("%.1f", steam_consumption_default * rate / 100))); + String.format("%.1f", 8.0 * rate / 100))); var rateText = underfloorHeatingSystemInfoRate.translate( ChatFormatting.AQUA.toString() + rate + "%") .withStyle(Style.EMPTY.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, @@ -148,33 +144,16 @@ public void addDisplayText(List textList) { buttonText.append(" "); buttonText.append(ComponentPanelWidget.withButton(Component.literal("[+]"), "add")); textList.add(buttonText); - var efficiency = self().holder.self().getPersistentData().getDouble("efficiency"); - if (efficiency == 0) { - efficiency = getEfficiency(); - } textList.add(underfloorHeatingSystemInfoEfficiency.translate( - String.format("%.1f", efficiency * 100))); + String.format("%.1f", heating.getEfficiency() * 100))); } } public void handleDisplayClick(String componentData, ClickData clickData) { if (!clickData.isRemote) { int result = componentData.equals("add") ? 5 : -5; - this.rate = Mth.clamp(rate + result, 25, 100); + var heating = getTraitOrThrow(UnderfloorHeatingTrait.class); + heating.setRate(heating.getRate() + result); } } - - @Override - public void saveCustomPersistedData(@NotNull CompoundTag tag, boolean forDrop) { - super.saveCustomPersistedData(tag, forDrop); - if (!forDrop) { - tag.putInt(RATE, rate); - } - } - - @Override - public void loadCustomPersistedData(@NotNull CompoundTag tag) { - super.loadCustomPersistedData(tag); - rate = tag.contains(RATE) ? tag.getInt(RATE) : 100; - } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java index ea023d900..9a05569c0 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java @@ -13,6 +13,8 @@ import net.minecraft.server.TickTask; import net.minecraft.server.level.ServerLevel; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Temperature; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Prefix; @@ -21,8 +23,6 @@ import java.util.List; -import static sfiomn.legendarysurvivaloverhaul.api.temperature.TemperatureUtil.getWorldTemperature; - @Prefix("bio_machine") public class BioMachine extends RecipeElectricMultiblockMachine { @@ -88,8 +88,9 @@ protected void updateTempSubscription() { } protected void updateCurrentTemperature() { - if (getOffsetTimer() % 10 == 0) { - machineTemperature = (int) getWorldTemperature(getLevel(), getPos()); + if (getOffsetTimer() % 10 == 0 && getLevel() instanceof ServerLevel level) { + machineTemperature = PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + .celsius(); } } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java index 8319bbc4c..6920763db 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java @@ -21,6 +21,8 @@ import net.minecraft.server.TickTask; import net.minecraft.server.level.ServerLevel; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Temperature; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Prefix; @@ -30,8 +32,6 @@ import java.util.List; -import static sfiomn.legendarysurvivaloverhaul.api.temperature.TemperatureUtil.getWorldTemperature; - @Prefix("fermenting_tank_machine") public class FermentingTankMachine extends CoilWorkableElectricMultiblockMachine { @@ -110,8 +110,9 @@ protected void updateTempSubscription() { } protected void updateCurrentTemperature() { - if (getOffsetTimer() % 10 == 0) { - Machine_Temperature = (int) getWorldTemperature(getLevel(), getPos()); + if (getOffsetTimer() % 10 == 0 && getLevel() instanceof ServerLevel level) { + Machine_Temperature = PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + .celsius(); } } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java index 476bbc8a9..1c38eecdd 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java @@ -16,12 +16,13 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Temperature; import com.ctnhlang.CN; import com.ctnhlang.EN; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import sfiomn.legendarysurvivaloverhaul.api.temperature.TemperatureUtil; import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; import java.util.List; @@ -96,7 +97,9 @@ protected void updateTempSubscription() { } protected void updateCurrentTemperature() { - basicTemperature = (int) TemperatureUtil.getWorldTemperature(getLevel(), getPos()) + 273; + if (!(getLevel() instanceof ServerLevel level)) return; + basicTemperature = (int) PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + .kelvin(); if (recipeLogic.isWorking()) { if (getOffsetTimer() % 10 == 0) { if (currentTemperature < getMaxTemperature()) { diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java new file mode 100644 index 000000000..037381502 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java @@ -0,0 +1,107 @@ +package io.github.cpearl0.ctnhcore.common.machine.trait; + +import io.github.cpearl0.ctnhcore.common.machine.multiblock.UnderfloorHeatingMachine; + +import com.gregtechceu.gtceu.api.machine.trait.MachineTrait; +import com.gregtechceu.gtceu.api.machine.trait.feature.IMultiblockMachineTrait; + +import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; +import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.phys.AABB; + +import com.ctnh.ctnhastral.common.environment.EnvironmentArea; +import com.ctnh.ctnhastral.common.environment.EnvironmentDelta; +import com.ctnh.ctnhastral.common.environment.EnvironmentEmission; +import com.ctnh.ctnhastral.common.environment.Temperature; +import lombok.Getter; + +/** 地暖功率、效率与排放生命周期的唯一所有者。 */ +public class UnderfloorHeatingTrait extends MachineTrait implements IMultiblockMachineTrait { + + @Getter + @Persisted + @DescSynced + private int rate = 100; + + @Getter + @DescSynced + private double efficiency; + + private long lastSampleTick = Long.MIN_VALUE; + + public UnderfloorHeatingTrait(UnderfloorHeatingMachine machine) { + super(machine); + } + + @Override + public UnderfloorHeatingMachine getMachine() { + return (UnderfloorHeatingMachine) super.getMachine(); + } + + public void setRate(int rate) { + this.rate = Mth.clamp(rate, 25, 100); + onChanged(); + } + + public void refreshEfficiency() { + if (machine.getLevel() instanceof ServerLevel level) { + efficiency = getMachine().getEfficiency(); + lastSampleTick = level.getGameTime(); + } + } + + public boolean emitHeat() { + if (!(machine.getLevel() instanceof ServerLevel level)) return true; + if (lastSampleTick == Long.MIN_VALUE || level.getGameTime() - lastSampleTick >= 20) refreshEfficiency(); + var pos = machine.getPos(); + AABB bounds = switch (machine.getFrontFacing()) { + case NORTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-39, 0, -32), pos.offset(40, 16, 47))); + case SOUTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-40, 0, -47), pos.offset(39, 16, 32))); + case WEST -> AABB.of(BoundingBox.fromCorners(pos.offset(-32, 0, -40), pos.offset(47, 16, 39))); + case EAST -> AABB.of(BoundingBox.fromCorners(pos.offset(-47, 0, -39), pos.offset(32, 16, 40))); + default -> throw new IllegalStateException("Invalid floor heating orientation"); + }; + new EnvironmentEmission(pos, new EnvironmentArea.Box(bounds), + EnvironmentDelta.of(Temperature.TYPE, (float) (30.0 * efficiency * rate / 100.0))).emit(level, 2); + return true; + } + + public void stopHeating() { + if (machine.getLevel() instanceof ServerLevel level) EnvironmentEmission.cease(level, machine.getPos()); + } + + @Override + public void onStructureFormed() { + refreshEfficiency(); + } + + @Override + public void onStructureInvalid() { + efficiency = 0.0; + stopHeating(); + } + + @Override + public void onPartUnload() { + stopHeating(); + } + + @Override + public void onMachineUnload() { + stopHeating(); + } + + @Override + public void onMachineDestroyed() { + stopHeating(); + } + + @Override + public void onWorkAllowedChanged(boolean allowed) { + if (!allowed) stopHeating(); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeClientEventHandler.java b/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeClientEventHandler.java index 13fd6122c..a79bc0374 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeClientEventHandler.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeClientEventHandler.java @@ -8,6 +8,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderGuiOverlayEvent; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -24,6 +25,18 @@ @Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT) public class ForgeClientEventHandler { + @SubscribeEvent + public static void onRenderOverlay(RenderGuiOverlayEvent.Pre event) { + ResourceLocation id = event.getOverlay().id(); + if (id.getNamespace().equals("legendarysurvivaloverhaul") && + switch (id.getPath()) { + case "temperature", "temperature_overlay", "cold_hunger", "wetness" -> true; + default -> false; + }) { + event.setCanceled(true); + } + } + @CN({ "虚空维度具有如下特性:", " - 不会自然生成生物", diff --git a/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeEventHandler.java b/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeEventHandler.java index dca4e57bf..35b5df8a7 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeEventHandler.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/event/ForgeEventHandler.java @@ -3,7 +3,6 @@ import io.github.cpearl0.ctnhcore.CTNHConfig; import io.github.cpearl0.ctnhcore.CTNHCore; import io.github.cpearl0.ctnhcore.common.capability.EIOCapacitorProvider; -import io.github.cpearl0.ctnhcore.integration.legendary.UnderfloorHeatingSystemTempModifier; import io.github.cpearl0.ctnhcore.registry.CTNHItems; import io.github.cpearl0.ctnhcore.registry.sound.CTNHSoundEvents; @@ -51,13 +50,6 @@ @Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public class ForgeEventHandler { - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void tickBus(TickEvent.ServerTickEvent event) { - if (event.getServer().getTickCount() % 40 == 0) { - UnderfloorHeatingSystemTempModifier.UNDERFLOOR_HEATING_SYSTEM_RANGE.clear(); - } - } - @SubscribeEvent(priority = EventPriority.LOW) public static void postLevelTickBus(TickEvent.LevelTickEvent event) { ProvidableNetEventHandler.onPostTick(event); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ArmorModifier.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ArmorModifier.java deleted file mode 100644 index 64f697682..000000000 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ArmorModifier.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.cpearl0.ctnhcore.integration.legendary; - -import io.github.cpearl0.ctnhcore.registry.adventure.CTNHEnchantments; - -import net.minecraft.world.entity.player.Player; - -import sfiomn.legendarysurvivaloverhaul.api.temperature.DynamicModifierBase; - -public class ArmorModifier extends DynamicModifierBase { - - public ArmorModifier() {} - - @Override - public float applyDynamicPlayerInfluence(Player player, float currentTemperature, float currentResistance) { - float sumWarming = 0; - float sumCooling = 0; - for (var armor : player.getArmorSlots()) { - if (armor.getEnchantmentLevel(CTNHEnchantments.WARMING.get()) != 0) { - sumWarming += armor.getEnchantmentLevel(CTNHEnchantments.WARMING.get()); - } - if (armor.getEnchantmentLevel(CTNHEnchantments.COOLING.get()) != 0) { - sumCooling += armor.getEnchantmentLevel(CTNHEnchantments.COOLING.get()); - } - } - float tempDiff = currentTemperature - currentResistance; - if (tempDiff >= 0) { - return -tempDiff * Math.min(1, sumCooling / 20); - } else { - return -tempDiff * Math.min(1, sumWarming / 20); - } - } -} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java new file mode 100644 index 000000000..9dd6a32e2 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java @@ -0,0 +1,62 @@ +package io.github.cpearl0.ctnhcore.integration.legendary; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; + +import com.ctnh.ctnhastral.common.environment.BlockTemperature; +import com.ctnh.ctnhastral.common.environment.TemperatureClimate; +import com.teamtea.eclipticseasons.api.EclipticSeasonsApi; +import com.teamtea.eclipticseasons.api.constant.solar.SolarTerm; +import com.teamtea.eclipticseasons.api.util.EclipticUtil; +import sfiomn.legendarysurvivaloverhaul.registry.BlockRegistry; + +/** 跨模组来源只在 Core 登记;LSO 不再计算环境温度。 */ +public final class EnvironmentTemperatureIntegration { + + // LSO 1.20.1-2.3.20.1 的二十四节气默认偏移,独立于其运行时配置。 + private static final float[] SEASON_OFFSETS = { + -10, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 10, + 9, 7, 5, 3, 1, 0, -1, -3, -5, -7, -10, -12 + }; + + private EnvironmentTemperatureIntegration() {} + + public static void init() { + TemperatureClimate.register(Level.OVERWORLD, EnvironmentTemperatureIntegration::overworldClimate); + BlockTemperature.register(BlockRegistry.HEATER.get(), + state -> state.getValue(BlockStateProperties.LIT) ? 15.0F : 0.0F); + BlockTemperature.register(BlockRegistry.COOLER.get(), + state -> state.getValue(BlockStateProperties.LIT) ? -15.0F : 0.0F); + BlockTemperature.register(BlockRegistry.SUN_FERN_CROP.get(), + state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? 1.5F : 0.0F); + BlockTemperature.register(BlockRegistry.SUN_FERN_GOLD.get(), + state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? 1.5F : 0.0F); + BlockTemperature.register(BlockRegistry.ICE_FERN_CROP.get(), + state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? -1.5F : 0.0F); + BlockTemperature.register(BlockRegistry.ICE_FERN_GOLD.get(), + state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? -1.5F : 0.0F); + } + + private static TemperatureClimate overworldClimate(ServerLevel level, BlockPos pos) { + var vanilla = TemperatureClimate.vanilla(level, pos); + var seasons = EclipticSeasonsApi.getInstance(); + var precipitation = seasons.hasLocalWeather(level) ? seasons.getCurrentPrecipitationAt(level, pos) : + vanilla.precipitation(); + SolarTerm term = seasons.getSolarTerm(level); + if (!seasons.isSeasonEnabled(level) || term == SolarTerm.NONE) { + return new TemperatureClimate(0.0F, 12000, precipitation); + } + double day = Math.floorMod(level.getDayTime(), 24000L) / 24000.0; + float progress = Mth.clamp((float) ((EclipticUtil.getTimeInSolarTerm(level) + day) / + seasons.getLastingDaysOfEachTerm(level)), 0.0F, 1.0F); + int current = term.ordinal(); + int from = progress < 0.5F ? Math.floorMod(current - 1, 24) : current; + int to = progress < 0.5F ? current : (current + 1) % 24; + float blend = progress < 0.5F ? progress + 0.5F : progress - 0.5F; + float offset = Mth.lerp(blend, SEASON_OFFSETS[from], SEASON_OFFSETS[to]); + return new TemperatureClimate(offset, term.getDayTime(), precipitation); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/PlayerTemperatureIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/PlayerTemperatureIntegration.java new file mode 100644 index 000000000..406f984ed --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/PlayerTemperatureIntegration.java @@ -0,0 +1,70 @@ +package io.github.cpearl0.ctnhcore.integration.legendary; + +import io.github.cpearl0.ctnhcore.CTNHCore; +import io.github.cpearl0.ctnhcore.registry.adventure.CTNHEnchantments; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.living.MobEffectEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import com.ctnh.ctnhastral.common.medical.PlayerThermalProtectionEvent; +import sfiomn.legendarysurvivaloverhaul.registry.AttributeRegistry; +import sfiomn.legendarysurvivaloverhaul.registry.MobEffectRegistry; + +/** 外部装备和药水只提供防护数据,玩家温度状态和医疗判定归 Astral 所有。 */ +@Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) +public final class PlayerTemperatureIntegration { + + @SubscribeEvent + public static void onThermalProtection(PlayerThermalProtectionEvent event) { + Player player = event.getEntity(); + float thermal = (float) player.getAttributeValue(AttributeRegistry.THERMAL_RESISTANCE.get()); + event.addResistanceK( + thermal + (float) player.getAttributeValue(AttributeRegistry.COLD_RESISTANCE.get()), + thermal + (float) player.getAttributeValue(AttributeRegistry.HEAT_RESISTANCE.get())); + event.addTemperatureOffsetK( + (float) (player.getAttributeValue(AttributeRegistry.HEATING_TEMPERATURE.get()) + + player.getAttributeValue(AttributeRegistry.COOLING_TEMPERATURE.get()))); + + int warming = 0, cooling = 0; + for (var armor : player.getArmorSlots()) { + warming += armor.getEnchantmentLevel(CTNHEnchantments.WARMING.get()); + cooling += armor.getEnchantmentLevel(CTNHEnchantments.COOLING.get()); + } + // 每级抵消 5% 的对应暴露温差,全身合计 20 级完全防护。 + boolean immune = player.hasEffect(MobEffectRegistry.TEMPERATURE_IMMUNITY.get()); + event.addProtection( + immune || player.hasEffect(MobEffectRegistry.COLD_IMMUNITY.get()) ? 1.0F : warming / 20.0F, + immune || player.hasEffect(MobEffectRegistry.HEAT_IMMUNITY.get()) ? 1.0F : cooling / 20.0F); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onThermalEffect(MobEffectEvent.Applicable event) { + if (event.getEntity() instanceof Player && isRetiredEffect(event.getEffectInstance().getEffect())) { + event.setResult(Event.Result.DENY); + } + } + + /** 活动效果也不能绕过单一医疗判定,包括命令或存档中的效果。 */ + @SubscribeEvent + public static void onPlayerTick(TickEvent.PlayerTickEvent event) { + if (event.phase != TickEvent.Phase.START || event.player.level().isClientSide) return; + Player player = event.player; + player.removeEffect(MobEffectRegistry.FROSTBITE.get()); + player.removeEffect(MobEffectRegistry.HEAT_STROKE.get()); + player.removeEffect(MobEffectRegistry.COLD_HUNGER.get()); + player.removeEffect(MobEffectRegistry.HEAT_THIRST.get()); + } + + private static boolean isRetiredEffect(MobEffect effect) { + return effect == MobEffectRegistry.FROSTBITE.get() || effect == MobEffectRegistry.HEAT_STROKE.get() || + effect == MobEffectRegistry.COLD_HUNGER.get() || effect == MobEffectRegistry.HEAT_THIRST.get(); + } + + private PlayerTemperatureIntegration() {} +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java new file mode 100644 index 000000000..764302466 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java @@ -0,0 +1,168 @@ +package io.github.cpearl0.ctnhcore.integration.legendary; + +import io.github.cpearl0.ctnhcore.CTNHCore; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.config.ConfigHolder; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import com.ctnh.ctnhastral.common.environment.Atmosphere; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.data.CAMedicalConditions; +import com.ctnhlang.CN; +import com.ctnhlang.EN; +import com.ctnhlang.Key; +import sfiomn.legendarysurvivaloverhaul.registry.ItemRegistry; +import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; + +import java.util.Locale; +import java.util.TreeMap; + +/** 复用温度计外观,普通读温和详细环境查询均消费 Astral 服务端快照。 */ +@Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) +public final class ThermometerEnvironmentIntegration { + + @Key("tooltip.ctnhcore.thermometer.environment") + @CN("对空气右键测温;潜行右键查询大气成分与冷热状态") + @EN("Right-click in the air for temperature; sneak for atmospheric composition and thermal status") + private static Lang usage; + + @Key("tooltip.ctnhcore.thermometer.readings") + @CN("读数显示在聊天栏,每秒可检测一次") + @EN("Readings appear in chat; one scan per second") + private static Lang readings; + + @Key("message.ctnhcore.thermometer.header") + @CN("环境检测读数") + @EN("Environment readings") + private static Lang header; + + @Key("message.ctnhcore.thermometer.location") + @CN("位置:%1$s [%2$s, %3$s, %4$s]") + @EN("Location: %1$s [%2$s, %3$s, %4$s]") + private static Lang location; + + @Key("message.ctnhcore.thermometer.temperature") + @CN("环境温度:%s ℃") + @EN("Ambient temperature: %s °C") + private static Lang temperature; + + @Key("message.ctnhcore.thermometer.thermal_status") + @CN("玩家冷热累积:失温 %1$s%% / 热射病 %2$s%%") + @EN("Player thermal exposure: hypothermia %1$s%% / hyperthermia %2$s%%") + private static Lang thermalStatus; + + @Key("message.ctnhcore.thermometer.pressure") + @CN("总压:%s atm") + @EN("Total pressure: %s atm") + private static Lang totalPressure; + + @Key("message.ctnhcore.thermometer.vacuum") + @CN("真空:无气体") + @EN("Vacuum: no gases") + private static Lang vacuum; + + @Key("message.ctnhcore.thermometer.composition") + @CN("大气成分(分压 / 占比):") + @EN("Atmospheric composition (partial pressure / share):") + private static Lang composition; + + @Key("message.ctnhcore.thermometer.gas") + @CN(" %1$s:%2$s atm / %3$s%%") + @EN(" %1$s: %2$s atm / %3$s%%") + private static Lang gasReading; + + @Key("message.ctnhcore.thermometer.unlisted") + @CN("未描述气体") + @EN("Unspecified gases") + private static Lang unlisted; + + @SubscribeEvent + public static void onRightClickItem(PlayerInteractEvent.RightClickItem event) { + Player player = event.getEntity(); + if (!event.getItemStack().is(ItemRegistry.THERMOMETER.get())) return; + + // 两侧均消费本次使用,避免继续处理另一只手;测量和冷却只由服务端执行。 + event.setCanceled(true); + event.setCancellationResult(InteractionResult.sidedSuccess(event.getLevel().isClientSide)); + if (event.getLevel() instanceof ServerLevel level && + !player.getCooldowns().isOnCooldown(ItemRegistry.THERMOMETER.get())) { + if (player.isShiftKeyDown()) { + report(level, player); + } else { + float celsius = PlanetEnvironmentService.getEnvironment(level, player.blockPosition()) + .get(Temperature.TYPE).celsius(); + player.displayClientMessage(temperature.translate(String.format(Locale.ROOT, "%.1f", celsius)), true); + } + player.getCooldowns().addCooldown(ItemRegistry.THERMOMETER.get(), 20); + } + } + + @SubscribeEvent + public static void onItemTooltip(ItemTooltipEvent event) { + if (!event.getItemStack().is(ItemRegistry.THERMOMETER.get())) return; + event.getToolTip().add(usage.translate().withStyle(ChatFormatting.GRAY)); + event.getToolTip().add(readings.translate().withStyle(ChatFormatting.DARK_GRAY)); + } + + private static void report(ServerLevel level, Player player) { + var pos = player.blockPosition(); + var environment = PlanetEnvironmentService.getEnvironment(level, pos); + Atmosphere atmosphere = environment.get(Atmosphere.TYPE); + MutableComponent message = header.translate().withStyle(ChatFormatting.AQUA); + line(message, location, level.dimension().location().toString(), pos.getX(), pos.getY(), pos.getZ()); + line(message, temperature, String.format(Locale.ROOT, "%.1f", environment.get(Temperature.TYPE).celsius())); + var tracker = GTCapabilityHelper.getMedicalConditionTracker(player); + if (tracker != null && ConfigHolder.INSTANCE.gameplay.hazardsEnabled) { + var conditions = tracker.getMedicalConditions(); + line(message, thermalStatus, + String.format(Locale.ROOT, "%.1f", Math.max(0.0F, + conditions.getFloat(CAMedicalConditions.HYPOTHERMIA)) * 100.0F / + CAMedicalConditions.HYPOTHERMIA.maxProgression), + String.format(Locale.ROOT, "%.1f", Math.max(0.0F, + conditions.getFloat(CAMedicalConditions.HYPERTHERMIA)) * 100.0F / + CAMedicalConditions.HYPERTHERMIA.maxProgression)); + } + float pressure = atmosphere.pressure(); + line(message, totalPressure, number(pressure)); + if (pressure == 0.0F) { + line(message, vacuum); + } else { + line(message, composition); + new TreeMap<>(atmosphere.partialPressures()).forEach((gas, partialPressure) -> { + Component name = Component.translatableWithFallback( + "gas." + gas.getNamespace() + "." + gas.getPath().replace('/', '.'), gas.toString()); + line(message, gasReading, name, number(partialPressure), number(100.0 * partialPressure / pressure)); + }); + double described = atmosphere.partialPressures().values().stream().mapToDouble(Float::doubleValue).sum(); + double remainder = pressure - described; + // 忽略浮点归一化的一位舍入误差,不把已描述完整的成分报为额外背景。 + if (remainder > Math.ulp(pressure)) { + line(message, gasReading, unlisted.translate(), number(remainder), + number(100.0 * remainder / pressure)); + } + } + player.sendSystemMessage(message); + } + + private static void line(MutableComponent message, Lang key, Object... args) { + message.append("\n").append(key.translate(args).withStyle(ChatFormatting.GRAY)); + } + + private static String number(double value) { + return String.format(Locale.ROOT, "%.4g", value); + } + + private ThermometerEnvironmentIntegration() {} +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/UnderfloorHeatingSystemTempModifier.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/UnderfloorHeatingSystemTempModifier.java deleted file mode 100644 index 58e04e3f4..000000000 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/UnderfloorHeatingSystemTempModifier.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.cpearl0.ctnhcore.integration.legendary; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; - -import org.jetbrains.annotations.Nullable; -import sfiomn.legendarysurvivaloverhaul.api.temperature.ModifierBase; - -import java.util.HashMap; -import java.util.Map; - -public class UnderfloorHeatingSystemTempModifier extends ModifierBase { - - public static final Map UNDERFLOOR_HEATING_SYSTEM_RANGE = new HashMap<>(); - - public UnderfloorHeatingSystemTempModifier() { - super(); - } - - @Override - public float getWorldInfluence(@Nullable Player player, Level level, BlockPos pos) { - // if (!(entity instanceof Player)) - // return temp -> temp; - double heat = 30 * UNDERFLOOR_HEATING_SYSTEM_RANGE.entrySet().stream() - .filter(range -> range.getKey().contains(pos.getCenter())) - .map(Map.Entry::getValue) - .reduce(0.0, Double::sum); - return (float) heat; - } -} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/AltitudeModifierMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/AltitudeModifierMixin.java deleted file mode 100644 index 51abfd479..000000000 --- a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/AltitudeModifierMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import sfiomn.legendarysurvivaloverhaul.common.temperature.AltitudeModifier; -import sfiomn.legendarysurvivaloverhaul.config.Config; - -@Mixin(AltitudeModifier.class) -public class AltitudeModifierMixin { - - @Inject(method = "getWorldInfluence", at = @At(value = "RETURN", ordinal = 2), remap = false, cancellable = true) - public void getWorldInfluence(Player player, Level level, BlockPos pos, CallbackInfoReturnable cir) { - cir.setReturnValue(((pos.getY() - 64.0f) / 64.0f * ((float) Config.Baked.altitudeModifier))); - } -} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ClientTemperatureEffectsMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ClientTemperatureEffectsMixin.java new file mode 100644 index 000000000..ea2ce8069 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ClientTemperatureEffectsMixin.java @@ -0,0 +1,27 @@ +package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import sfiomn.legendarysurvivaloverhaul.client.events.ClientForgeEvents; + +/** LSO 的体温视觉与声音不再更新;环境检测器仍按服务端快照显示。 */ +@Mixin(value = ClientForgeEvents.class, remap = false) +public abstract class ClientTemperatureEffectsMixin { + + @Redirect(method = "onClientTick", + at = @At(value = "FIELD", + target = "Lsfiomn/legendarysurvivaloverhaul/config/Config$Baked;temperatureEnabled:Z"), + require = 1) + private static boolean ctnh$disableLsoTemperatureEffects() { + return false; + } + + @Redirect(method = "onClientTick", + at = @At(value = "FIELD", + target = "Lsfiomn/legendarysurvivaloverhaul/config/Config$Baked;wetnessEnabled:Z"), + require = 1) + private static boolean ctnh$disableLsoWetnessEffects() { + return false; + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ModCapabilitiesMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ModCapabilitiesMixin.java new file mode 100644 index 000000000..0072397a2 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ModCapabilitiesMixin.java @@ -0,0 +1,27 @@ +package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import sfiomn.legendarysurvivaloverhaul.common.capabilities.ModCapabilities; + +/** 停用 LSO 玩家体温、湿度的更新与同步;其装备数据、口渴和肢体健康仍独立工作。 */ +@Mixin(value = ModCapabilities.class, remap = false) +public abstract class ModCapabilitiesMixin { + + @Redirect(method = { "onPlayerTick", "deathHandler", "syncCapsOnDimensionChange", "syncCapsOnLogin" }, + at = @At(value = "FIELD", + target = "Lsfiomn/legendarysurvivaloverhaul/config/Config$Baked;temperatureEnabled:Z"), + require = 6) + private static boolean ctnh$astralPlayerTemperature() { + return false; + } + + @Redirect(method = { "onPlayerTick", "deathHandler", "syncCapsOnDimensionChange", "syncCapsOnLogin" }, + at = @At(value = "FIELD", + target = "Lsfiomn/legendarysurvivaloverhaul/config/Config$Baked;wetnessEnabled:Z"), + require = 4) + private static boolean ctnh$disableLsoWetness() { + return false; + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureCommandMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureCommandMixin.java new file mode 100644 index 000000000..ebd7bf3d2 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureCommandMixin.java @@ -0,0 +1,28 @@ +package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; + +import net.minecraft.commands.CommandSourceStack; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import sfiomn.legendarysurvivaloverhaul.registry.CommandRegistry; + +/** 旧体温已停用,不能再注册读取旧环境或修改旧体温的命令。 */ +@Mixin(value = CommandRegistry.class, remap = false) +public abstract class TemperatureCommandMixin { + + // LSO 2.3.20.1 依次注册温度、肢体损伤、生命值;首个返回值直接丢弃。 + @Redirect(method = "registerCommandsEvent", + at = @At(value = "INVOKE", + target = "Lcom/mojang/brigadier/CommandDispatcher;register(Lcom/mojang/brigadier/builder/LiteralArgumentBuilder;)Lcom/mojang/brigadier/tree/LiteralCommandNode;", + ordinal = 0), + require = 1) + private static LiteralCommandNode ctnh$retireTemperatureCommand( + CommandDispatcher dispatcher, + LiteralArgumentBuilder builder) { + return null; + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java new file mode 100644 index 000000000..caf70899a --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java @@ -0,0 +1,43 @@ +package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +import com.ctnh.ctnhastral.client.ClientEnvironmentTemperature; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Temperature; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import sfiomn.legendarysurvivaloverhaul.common.capabilities.temperature.TemperatureItemCapability; +import sfiomn.legendarysurvivaloverhaul.util.WorldUtil; + +/** 温度计等待服务端快照;请求期间保留最后有效读数,不写入未同步的 NaN。 */ +@Mixin(value = TemperatureItemCapability.class, remap = false) +public abstract class TemperatureItemCapabilityMixin { + + @Shadow + private long updateTick; + + @Shadow + public abstract void setWorldTemperatureLevel(float temperature); + + @Inject(method = "updateWorldTemperature", at = @At("HEAD"), cancellable = true, require = 1) + private void ctnh$serverReading(Level level, Entity entity, long tick, CallbackInfo ci) { + var pos = WorldUtil.getSidedBlockPos(level, entity); + float temperature = level instanceof ServerLevel serverLevel ? + PlanetEnvironmentService.getEnvironment(serverLevel, pos).get(Temperature.TYPE).celsius() : + DistExecutor.unsafeCallWhenOn(Dist.CLIENT, + () -> () -> ClientEnvironmentTemperature.celsius(level, pos)); + if (Float.isFinite(temperature)) { + setWorldTemperatureLevel(temperature); + updateTick = tick; + } + ci.cancel(); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java new file mode 100644 index 000000000..bfb737424 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java @@ -0,0 +1,47 @@ +package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import com.ctnhlang.CN; +import com.ctnhlang.EN; +import com.ctnhlang.Key; +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.CallbackInfo; +import sfiomn.legendarysurvivaloverhaul.common.items.ThermometerItem; +import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; + +import java.util.List; + +/** 为 LSO 温度计使用 Core 的名称翻译键,避免跨命名空间的语言覆盖顺序影响显示。 */ +@Mixin(ThermometerItem.class) +public abstract class ThermometerItemMixin extends Item { + + @Unique + @Key("item.ctnhcore.environment_detector") + @CN("环境检测器") + @EN("Environment Detector") + private static Lang ctnhcore$environmentDetectorName; + + protected ThermometerItemMixin(Properties properties) { + super(properties); + } + + @Override + public String getDescriptionId() { + return ctnhcore$environmentDetectorName.key(); + } + + /** 使用说明由 Core 的物品提示事件提供,移除原有体温/饰品 HUD 说明。 */ + @Inject(method = "appendHoverText", at = @At("HEAD"), cancellable = true, require = 1) + private void ctnhcore$environmentTooltip(ItemStack stack, Level level, List tooltip, + TooltipFlag flag, CallbackInfo ci) { + ci.cancel(); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTemperatureModifierRegister.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTemperatureModifierRegister.java deleted file mode 100644 index 231312894..000000000 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTemperatureModifierRegister.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.cpearl0.ctnhcore.registry; - -import io.github.cpearl0.ctnhcore.integration.legendary.ArmorModifier; -import io.github.cpearl0.ctnhcore.integration.legendary.UnderfloorHeatingSystemTempModifier; - -import net.minecraftforge.registries.RegistryObject; - -import sfiomn.legendarysurvivaloverhaul.api.temperature.DynamicModifierBase; -import sfiomn.legendarysurvivaloverhaul.api.temperature.ModifierBase; - -import static sfiomn.legendarysurvivaloverhaul.registry.TemperatureModifierRegistry.DYNAMIC_MODIFIERS; -import static sfiomn.legendarysurvivaloverhaul.registry.TemperatureModifierRegistry.MODIFIERS; - -public class CTNHTemperatureModifierRegister { - - public static void init() {} - - public static final RegistryObject UNDERFLOOR_HEATING_SYSTEM = MODIFIERS - .register("underfloor_heating_system", UnderfloorHeatingSystemTempModifier::new); - public static final RegistryObject ARMOR_MODIFIER = DYNAMIC_MODIFIERS - .register("armor_modifier", ArmorModifier::new); -} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/GTMachineModify.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/GTMachineModify.java index 13269453d..7af50a856 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/GTMachineModify.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/GTMachineModify.java @@ -24,6 +24,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; +import com.ctnh.ctnhastral.common.recipe.OxygenCondition; import com.ctnh.ctnhastral.registry.CARecipeModifiers; import com.ctnhlang.CN; import com.ctnhlang.EN; @@ -94,20 +95,19 @@ public static void init() { })); modifyGTAssembly(); modifyCleanroom(); - modifyOxygenGenerators(); + modifyGeneratorEnvironments(); PRIMITIVE_BLAST_FURNACE.setRecipeTypes(new GTRecipeType[] { GTRecipeTypes.DUMMY_RECIPES }); } - private static void modifyOxygenGenerators() { - appendRecipeModifier(GTMachines.COMBUSTION, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(GTMachines.GAS_TURBINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(GTMachines.STEAM_TURBINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(LARGE_COMBUSTION_ENGINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(EXTREME_COMBUSTION_ENGINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(LARGE_GAS_TURBINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(LARGE_STEAM_TURBINE, CARecipeModifiers::oxygenRequirement); - appendRecipeModifier(MultiblocksA.ULTIMATE_COMBUSTION_ENGINE, CARecipeModifiers::oxygenRequirement); + private static void modifyGeneratorEnvironments() { + RecipeModifier environmentModifier = CARecipeModifiers.environmentRequirements(OxygenCondition::new); + appendRecipeModifier(GTMachines.COMBUSTION, environmentModifier); + appendRecipeModifier(GTMachines.GAS_TURBINE, environmentModifier); + appendRecipeModifier(LARGE_COMBUSTION_ENGINE, environmentModifier); + appendRecipeModifier(EXTREME_COMBUSTION_ENGINE, environmentModifier); + appendRecipeModifier(LARGE_GAS_TURBINE, environmentModifier); + appendRecipeModifier(MultiblocksA.ULTIMATE_COMBUSTION_ENGINE, environmentModifier); } private static void appendRecipeModifier(MachineDefinition[] machines, RecipeModifier recipeModifier) { diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/multiblock/MultiblocksA.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/multiblock/MultiblocksA.java index a85dbed29..7377678e4 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/multiblock/MultiblocksA.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/machines/multiblock/MultiblocksA.java @@ -16,7 +16,7 @@ import io.github.cpearl0.ctnhcore.common.machine.multiblock.kinetic.IndustrialPrimitiveBlastFurnaceMachine; import io.github.cpearl0.ctnhcore.common.machine.multiblock.kinetic.MeadowMachine; import io.github.cpearl0.ctnhcore.common.machine.multiblock.part.CTNHPartAbility; -import io.github.cpearl0.ctnhcore.integration.legendary.UnderfloorHeatingSystemTempModifier; +import io.github.cpearl0.ctnhcore.common.machine.trait.UnderfloorHeatingTrait; import io.github.cpearl0.ctnhcore.registry.CTNHBlocks; import io.github.cpearl0.ctnhcore.registry.CTNHRecipeModifiers; import io.github.cpearl0.ctnhcore.registry.CTNHRecipeTypes; @@ -50,8 +50,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.WeatheringCopper; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.phys.AABB; import com.ctnhlang.CN; import com.ctnhlang.EN; @@ -1279,48 +1277,15 @@ public static void init(){} .workableCasingModel(Create.asResource("block/copper/copper_shingles"), GTCEu.id("block/multiblock/multiblock_tank")) .beforeWorking((machine, recipe) -> { - var efficiency = ((UnderfloorHeatingMachine) machine).getEfficiency(); - machine.self().getHolder().self().getPersistentData().putDouble("efficiency", efficiency); + machine.self().getTraitOrThrow(UnderfloorHeatingTrait.class).refreshEfficiency(); return null; }) .recipeModifier((machine, group, recipe) -> { - if (machine instanceof UnderfloorHeatingMachine underfloorHeatingMachine) { - recipe.multiplyInputs(underfloorHeatingMachine.rate / 100); - } + recipe.inputs.multiply(machine.getTraitOrThrow(UnderfloorHeatingTrait.class).getRate() / 100.0); return null; }) - .onWorking(machine -> { - if (machine instanceof UnderfloorHeatingMachine) { - var pos = machine.self().getPos(); - var facing = machine.self().getFrontFacing(); - double efficiency = machine.self().getHolder().self().getPersistentData().getDouble("efficiency"); - if (machine.self().getOffsetTimer() % 20 == 0) { - efficiency = ((UnderfloorHeatingMachine) machine).getEfficiency(); - machine.self().getHolder().self().getPersistentData().putDouble("efficiency", efficiency); - } - AABB range = switch (facing) { - case NORTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-39, 0, -32), pos.offset(40, 16, 47))); - case SOUTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-40, 0, -47), pos.offset(39, 16, 32))); - case WEST -> AABB.of(BoundingBox.fromCorners(pos.offset(-32, 0, -40), pos.offset(47, 16, 39))); - case EAST -> AABB.of(BoundingBox.fromCorners(pos.offset(-47, 0, -39), pos.offset(32, 16, 40))); - default -> throw new IllegalStateException("Unexpected value: " + facing); - }; - UnderfloorHeatingSystemTempModifier.UNDERFLOOR_HEATING_SYSTEM_RANGE.put(range, efficiency * ((UnderfloorHeatingMachine) machine).rate / 100); - } - return true; - }) - .afterWorking(machine -> { - var pos = machine.self().getPos(); - var facing = machine.self().getFrontFacing(); - AABB range = switch (facing) { - case NORTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-39, 0, -32), pos.offset(40, 16, 47))); - case SOUTH -> AABB.of(BoundingBox.fromCorners(pos.offset(-40, 0, -47), pos.offset(39, 16, 32))); - case WEST -> AABB.of(BoundingBox.fromCorners(pos.offset(-32, 0, -40), pos.offset(47, 16, 39))); - case EAST -> AABB.of(BoundingBox.fromCorners(pos.offset(-47, 0, -39), pos.offset(32, 16, 40))); - default -> throw new IllegalStateException("Unexpected value: " + facing); - }; - UnderfloorHeatingSystemTempModifier.UNDERFLOOR_HEATING_SYSTEM_RANGE.remove(range); - }) + .onWorking(machine -> machine.self().getTraitOrThrow(UnderfloorHeatingTrait.class).emitHeat()) + .afterWorking(machine -> machine.self().getTraitOrThrow(UnderfloorHeatingTrait.class).stopHeating()) .register(); diff --git a/src/main/resources/ctnhcore.mixins.json b/src/main/resources/ctnhcore.mixins.json index a84575f24..b30b80d21 100644 --- a/src/main/resources/ctnhcore.mixins.json +++ b/src/main/resources/ctnhcore.mixins.json @@ -32,7 +32,10 @@ "gtceu.ItemMaterialDataMixin", "gtceu.orevein.ClientProxyAccessor", "javd.PortalBlockMixin", - "legendarysurvival.AltitudeModifierMixin", + "legendarysurvival.ModCapabilitiesMixin", + "legendarysurvival.TemperatureCommandMixin", + "legendarysurvival.TemperatureItemCapabilityMixin", + "legendarysurvival.ThermometerItemMixin", "mc.MonsterMixin", "mc.NaturalSpawnerMixin", "mc.ServerChunkCacheMixin", @@ -41,6 +44,7 @@ "vintageimprovements.LatheMovingBlockMixin" ], "client": [ + "legendarysurvival.ClientTemperatureEffectsMixin", "creatediesel.DistillationCategoryMixin", "emi.JemiRecipeMixin", "emi.JemiStackSerializerMixin", From c936e5ed4c49d8dc7cbc06114a680e3c3f5e6888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=8F=E4=BC=9F?= <16601765+daijugui@user.noreply.gitee.com> Date: Sat, 3 Oct 2026 21:24:30 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E6=A3=80=E6=B5=8B=E9=9D=A2=E6=9D=BF=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=AF=BB=E6=95=B0=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/assets/ctnhcore/lang/en_ud.json | 24 +- .../resources/assets/ctnhcore/lang/en_us.json | 24 +- .../resources/assets/ctnhcore/lang/zh_cn.json | 24 +- .../ThermometerEnvironmentIntegration.java | 276 +++++++++++++++--- .../ThermometerItemMixin.java | 15 +- 5 files changed, 291 insertions(+), 72 deletions(-) diff --git a/src/generated/resources/assets/ctnhcore/lang/en_ud.json b/src/generated/resources/assets/ctnhcore/lang/en_ud.json index cc41e32cf..a5da1b9a7 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_ud.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_ud.json @@ -1077,6 +1077,14 @@ "gtceu.underfloor_heating_system": "buıʇɐǝH ɹooןɟɹǝpu∩", "gui.ctnh.neutron_sensor.invert.disabled": "˙ǝnןɐʌ ɯnɯıuıɯ ǝɥʇ uɐɥʇ ssǝן sı ʇı uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ buıʇʇıɯǝ doʇs puɐ 'sǝnןɐʌ ɯnɯıxɐɯ puɐ ɯnɯıuıɯ ʇǝs ǝɥʇ uǝǝʍʇǝq sı ʎbɹǝuǝ ɔıʇǝuıʞ uoɹʇnǝu ǝɥʇ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ ʇıɯǝ ןןıʍ ɹosuǝs ǝɥʇ 'ʇןnɐɟǝp ʎᗺ\nɔıboן ǝuoʇspǝɹ ǝsɹǝʌǝɹ oʇ ɥɔʇıʍS\n\nןɐɯɹoN :ʇndʇnO", "gui.ctnh.neutron_sensor.invert.enabled": "˙ǝnןɐʌ ɯnɯıuıɯ ǝɥʇ uɐɥʇ ssǝן sı ʇı uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ buıʇʇıɯǝ doʇs puɐ 'sǝnןɐʌ ɯnɯıxɐɯ puɐ ɯnɯıuıɯ ʇǝs ǝɥʇ uǝǝʍʇǝq sı ʎbɹǝuǝ ɔıʇǝuıʞ uoɹʇnǝu ǝɥʇ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ ʇıɯǝ ןןıʍ ɹosuǝs ǝɥʇ 'ʇןnɐɟǝp ʎᗺ\nɔıboן ǝuoʇspǝɹ ǝsɹǝʌǝɹ oʇ ɥɔʇıʍS\n\nǝsɹǝʌǝᴚ :ʇndʇnO", + "gui.ctnhcore.environment_detector.close": "ǝsoןƆ", + "gui.ctnhcore.environment_detector.conditions": "suoıʇıpuoɔ ʇuǝɯuoɹıʌuƎ", + "gui.ctnhcore.environment_detector.coordinates": "%3$s Z · %2$s ʎ · %1$s X uoıʇısoԀ", + "gui.ctnhcore.environment_detector.corrosion": "ǝʇɐɹ uoısoɹɹoƆ", + "gui.ctnhcore.environment_detector.hyperthermia": "ɐıɯɹǝɥʇɹǝdʎH", + "gui.ctnhcore.environment_detector.hypothermia": "ɐıɯɹǝɥʇodʎH", + "gui.ctnhcore.environment_detector.no_thermal_data": "ǝןqɐןıɐʌɐu∩", + "gui.ctnhcore.environment_detector.radiation": "ǝʇɐɹ ǝsop uoıʇɐıpɐᴚ", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": ":ǝbuɐᴚ ןɐʇuozıɹoH", "gui.digital_miner.ctnhcore.digitalminer.max_height": ":ʇɥbıǝH xɐW", "gui.digital_miner.ctnhcore.digitalminer.min_height": ":ʇɥbıǝH uıW", @@ -2001,13 +2009,13 @@ "material.ctnhcore.zr_hf_chloride": "ǝpıɹoןɥƆ ɟH ɹZ", "material.ctnhcore.zr_hf_oxy_chloride": "ǝpıɹoןɥƆ ʎxO ɟH ɹZ", "material.ctnhcore.zr_hf_separation_mix": "xıW uoıʇɐɹɐdǝS ɟH ɹZ", - "message.ctnhcore.thermometer.composition": ":)ǝɹɐɥs / ǝɹnssǝɹd ןɐıʇɹɐd( uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇⱯ", - "message.ctnhcore.thermometer.gas": "%3$s%% / ɯʇɐ %2$s :%1$s ", + "message.ctnhcore.thermometer.composition": "uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇⱯ", + "message.ctnhcore.thermometer.gas": "%2$s ǝɹɐɥS · %1$s ǝɹnssǝɹԀ", "message.ctnhcore.thermometer.header": "sbuıpɐǝɹ ʇuǝɯuoɹıʌuƎ", - "message.ctnhcore.thermometer.location": "]%4$s '%3$s '%2$s[ %1$s :uoıʇɐɔoꞀ", - "message.ctnhcore.thermometer.pressure": "ɯʇɐ %s :ǝɹnssǝɹd ןɐʇo⟘", - "message.ctnhcore.thermometer.temperature": "Ɔ° %s :ǝɹnʇɐɹǝdɯǝʇ ʇuǝıqɯⱯ", - "message.ctnhcore.thermometer.thermal_status": "%2$s%% ɐıɯɹǝɥʇɹǝdʎɥ / %1$s%% ɐıɯɹǝɥʇodʎɥ :ǝɹnsodxǝ ןɐɯɹǝɥʇ ɹǝʎɐןԀ", + "message.ctnhcore.thermometer.location": "%s uoısuǝɯıᗡ", + "message.ctnhcore.thermometer.pressure": "ǝɹnssǝɹd ןɐʇo⟘", + "message.ctnhcore.thermometer.temperature": "ǝɹnʇɐɹǝdɯǝʇ ʇuǝıqɯⱯ", + "message.ctnhcore.thermometer.thermal_status": "ǝɹnsodxǝ ןɐɯɹǝɥʇ ɹǝʎɐןԀ", "message.ctnhcore.thermometer.unlisted": "sǝsɐb pǝıɟıɔǝdsu∩", "message.ctnhcore.thermometer.vacuum": "sǝsɐb ou :ɯnnɔɐΛ", "multiblock.ctnh.nuclear_reactor.consume_amount": "s/ᗺɯ %s :ǝʇɐɹ uoıʇdɯnsuoɔ ʇuɐןooƆ", @@ -2054,7 +2062,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": "ʎןןɐuoıʇıpuoɔun ʇɥbıןɟ ǝʌıʇɐǝɹɔ pǝʇuɐɹb ǝɹɐ sɹǝʎɐןԀ - ", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": "ʇıɯıן ǝɔuɐʇsıp ou ǝʌɐɥ sʇuıoԀ ssǝɔɔⱯ ssǝןǝɹıM ƎW - ", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": "uoıʇɔunɟ ʇou op sɹoʇɐɹǝuǝb puıʍ puɐ sןǝuɐd ɹɐןoS - ", - "tooltip.ctnhcore.thermometer.environment": "snʇɐʇs ןɐɯɹǝɥʇ puɐ uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇɐ ɹoɟ ʞɐǝus ؛ǝɹnʇɐɹǝdɯǝʇ ɹoɟ ɹıɐ ǝɥʇ uı ʞɔıןɔ-ʇɥbıᴚ", - "tooltip.ctnhcore.thermometer.readings": "puoɔǝs ɹǝd uɐɔs ǝuo ؛ʇɐɥɔ uı ɹɐǝddɐ sbuıpɐǝᴚ", + "tooltip.ctnhcore.thermometer.environment": "ןǝuɐd ʇuǝɯuoɹıʌuǝ ǝɥʇ uǝdo oʇ ɹıɐ ǝɥʇ uı ʞɔıןɔ-ʇɥbıᴚ", + "tooltip.ctnhcore.thermometer.readings": "ǝsoןɔ oʇ ɔsƎ ssǝɹd ؛puoɔǝs ʎɹǝʌǝ sǝʇɐpd∩", "zenith_machine_sp": "¡buıpןǝıʎu∩ spuɐʇS uoɔɐǝᗺ ɔıuoısԀ ǝɥ⟘ϛ§" } \ No newline at end of file diff --git a/src/generated/resources/assets/ctnhcore/lang/en_us.json b/src/generated/resources/assets/ctnhcore/lang/en_us.json index 220e0ab29..be8e0be50 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_us.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_us.json @@ -1077,6 +1077,14 @@ "gtceu.underfloor_heating_system": "Underfloor Heating", "gui.ctnh.neutron_sensor.invert.disabled": "Output: Normal\n\nSwitch to reverse redstone logic\nBy default, the sensor will emit a redstone signal when the neutron kinetic energy is between the set minimum and maximum values, and stop emitting a redstone signal when it is less than the minimum value.", "gui.ctnh.neutron_sensor.invert.enabled": "Output: Reverse\n\nSwitch to reverse redstone logic\nBy default, the sensor will emit a redstone signal when the neutron kinetic energy is between the set minimum and maximum values, and stop emitting a redstone signal when it is less than the minimum value.", + "gui.ctnhcore.environment_detector.close": "Close", + "gui.ctnhcore.environment_detector.conditions": "Environment conditions", + "gui.ctnhcore.environment_detector.coordinates": "Position X %1$s · Y %2$s · Z %3$s", + "gui.ctnhcore.environment_detector.corrosion": "Corrosion rate", + "gui.ctnhcore.environment_detector.hyperthermia": "Hyperthermia", + "gui.ctnhcore.environment_detector.hypothermia": "Hypothermia", + "gui.ctnhcore.environment_detector.no_thermal_data": "Unavailable", + "gui.ctnhcore.environment_detector.radiation": "Radiation dose rate", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": "Horizontal Range:", "gui.digital_miner.ctnhcore.digitalminer.max_height": "Max Height:", "gui.digital_miner.ctnhcore.digitalminer.min_height": "Min Height:", @@ -2001,13 +2009,13 @@ "material.ctnhcore.zr_hf_chloride": "Zr Hf Chloride", "material.ctnhcore.zr_hf_oxy_chloride": "Zr Hf Oxy Chloride", "material.ctnhcore.zr_hf_separation_mix": "Zr Hf Separation Mix", - "message.ctnhcore.thermometer.composition": "Atmospheric composition (partial pressure / share):", - "message.ctnhcore.thermometer.gas": " %1$s: %2$s atm / %3$s%%", + "message.ctnhcore.thermometer.composition": "Atmospheric composition", + "message.ctnhcore.thermometer.gas": "Pressure %1$s · Share %2$s", "message.ctnhcore.thermometer.header": "Environment readings", - "message.ctnhcore.thermometer.location": "Location: %1$s [%2$s, %3$s, %4$s]", - "message.ctnhcore.thermometer.pressure": "Total pressure: %s atm", - "message.ctnhcore.thermometer.temperature": "Ambient temperature: %s °C", - "message.ctnhcore.thermometer.thermal_status": "Player thermal exposure: hypothermia %1$s%% / hyperthermia %2$s%%", + "message.ctnhcore.thermometer.location": "Dimension %s", + "message.ctnhcore.thermometer.pressure": "Total pressure", + "message.ctnhcore.thermometer.temperature": "Ambient temperature", + "message.ctnhcore.thermometer.thermal_status": "Player thermal exposure", "message.ctnhcore.thermometer.unlisted": "Unspecified gases", "message.ctnhcore.thermometer.vacuum": "Vacuum: no gases", "multiblock.ctnh.nuclear_reactor.consume_amount": "Coolant consumption rate: %s mB/s", @@ -2054,7 +2062,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": " - Players are granted creative flight unconditionally", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": " - ME Wireless Access Points have no distance limit", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": " - Solar panels and wind generators do not function", - "tooltip.ctnhcore.thermometer.environment": "Right-click in the air for temperature; sneak for atmospheric composition and thermal status", - "tooltip.ctnhcore.thermometer.readings": "Readings appear in chat; one scan per second", + "tooltip.ctnhcore.thermometer.environment": "Right-click in the air to open the environment panel", + "tooltip.ctnhcore.thermometer.readings": "Updates every second; press Esc to close", "zenith_machine_sp": "§5The Psionic Beacon Stands Unyielding!" } \ No newline at end of file diff --git a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json index 167316e58..260fad09c 100644 --- a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json +++ b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json @@ -1148,6 +1148,14 @@ "gtceu.underfloor_heating_system": "地暖", "gui.ctnh.neutron_sensor.invert.disabled": "输出:正常\n\n切换以反转红石逻辑\n默认情况下,中子动能介于所设定的最小值和最大值之间时传感器将发出红石信号,小于最小值时则停止发出红石信号", "gui.ctnh.neutron_sensor.invert.enabled": "输出:反转\n\n切换以反转红石逻辑\n默认情况下,中子动能介于所设定的最小值和最大值之间时传感器将发出红石信号,小于最小值时则停止发出红石信号", + "gui.ctnhcore.environment_detector.close": "关闭", + "gui.ctnhcore.environment_detector.conditions": "环境条件", + "gui.ctnhcore.environment_detector.coordinates": "坐标 X %1$s · Y %2$s · Z %3$s", + "gui.ctnhcore.environment_detector.corrosion": "腐蚀速率", + "gui.ctnhcore.environment_detector.hyperthermia": "热射病累积", + "gui.ctnhcore.environment_detector.hypothermia": "失温累积", + "gui.ctnhcore.environment_detector.no_thermal_data": "暂无读数", + "gui.ctnhcore.environment_detector.radiation": "辐射剂量率", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": "水平范围:", "gui.digital_miner.ctnhcore.digitalminer.max_height": "最大高度:", "gui.digital_miner.ctnhcore.digitalminer.min_height": "最小高度:", @@ -2069,13 +2077,13 @@ "material.ctnhcore.zr_hf_chloride": "锆-铪氯化物", "material.ctnhcore.zr_hf_oxy_chloride": "锆-铪氯氧化物", "material.ctnhcore.zr_hf_separation_mix": "锆-铪混合物分离液", - "message.ctnhcore.thermometer.composition": "大气成分(分压 / 占比):", - "message.ctnhcore.thermometer.gas": " %1$s:%2$s atm / %3$s%%", + "message.ctnhcore.thermometer.composition": "大气成分", + "message.ctnhcore.thermometer.gas": "分压 %1$s · 占比 %2$s", "message.ctnhcore.thermometer.header": "环境检测读数", - "message.ctnhcore.thermometer.location": "位置:%1$s [%2$s, %3$s, %4$s]", - "message.ctnhcore.thermometer.pressure": "总压:%s atm", - "message.ctnhcore.thermometer.temperature": "环境温度:%s ℃", - "message.ctnhcore.thermometer.thermal_status": "玩家冷热累积:失温 %1$s%% / 热射病 %2$s%%", + "message.ctnhcore.thermometer.location": "维度 %s", + "message.ctnhcore.thermometer.pressure": "总气压", + "message.ctnhcore.thermometer.temperature": "环境温度", + "message.ctnhcore.thermometer.thermal_status": "玩家冷热累积", "message.ctnhcore.thermometer.unlisted": "未描述气体", "message.ctnhcore.thermometer.vacuum": "真空:无气体", "multiblock.ctnh.nuclear_reactor.consume_amount": "冷却液消耗率:%s mB/s", @@ -2128,7 +2136,7 @@ "tooltip.ctnhcore.forgeclienteventhandler.void_feature.2": " - 玩家无条件获得创造飞行", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.3": " - ME无线访问点无距离限制", "tooltip.ctnhcore.forgeclienteventhandler.void_feature.4": " - 光伏、风力发电机无法工作", - "tooltip.ctnhcore.thermometer.environment": "对空气右键测温;潜行右键查询大气成分与冷热状态", - "tooltip.ctnhcore.thermometer.readings": "读数显示在聊天栏,每秒可检测一次", + "tooltip.ctnhcore.thermometer.environment": "对空气右键打开环境检测面板", + "tooltip.ctnhcore.thermometer.readings": "每秒刷新读数,按 Esc 关闭", "zenith_machine_sp": "§5灵能灯塔屹立不倒!" } \ No newline at end of file diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java index 764302466..101714e9d 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java @@ -3,12 +3,27 @@ import io.github.cpearl0.ctnhcore.CTNHCore; import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.gui.GuiTextures; import com.gregtechceu.gtceu.config.ConfigHolder; +import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; +import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; +import com.lowdragmc.lowdraglib.gui.modular.ModularUI; +import com.lowdragmc.lowdraglib.gui.texture.ColorRectTexture; +import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; +import com.lowdragmc.lowdraglib.gui.widget.ComponentPanelWidget; +import com.lowdragmc.lowdraglib.gui.widget.DraggableScrollableWidgetGroup; +import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; +import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; +import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; +import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; +import com.lowdragmc.lowdraglib.gui.widget.layout.Layout; + import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraftforge.event.entity.player.ItemTooltipEvent; @@ -17,7 +32,9 @@ import net.minecraftforge.fml.common.Mod; import com.ctnh.ctnhastral.common.environment.Atmosphere; +import com.ctnh.ctnhastral.common.environment.Corrosion; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.common.environment.Radiation; import com.ctnh.ctnhastral.common.environment.Temperature; import com.ctnh.ctnhastral.data.CAMedicalConditions; import com.ctnhlang.CN; @@ -26,61 +43,115 @@ import sfiomn.legendarysurvivaloverhaul.registry.ItemRegistry; import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.TreeMap; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; -/** 复用温度计外观,普通读温和详细环境查询均消费 Astral 服务端快照。 */ +/** 复用温度计外观,在物品面板中显示并同步 Astral 服务端环境读数。 */ @Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public final class ThermometerEnvironmentIntegration { + private static final int TEXT_COLOR = 0xE4EDF2; + private static final int MUTED_COLOR = 0x9FAFB8; + // 颜色区分读数类别,不代表玩家防护后的危险等级。 + private static final int TEMPERATURE_COLOR = 0xFFC66D; + private static final int PRESSURE_COLOR = 0x6DD5ED; + private static final int RADIATION_COLOR = 0xC8A2FF; + private static final int CORROSION_COLOR = 0xA9D879; + private static final int COLD_COLOR = 0x77BFFF; + private static final int HEAT_COLOR = 0xFF997D; + @Key("tooltip.ctnhcore.thermometer.environment") - @CN("对空气右键测温;潜行右键查询大气成分与冷热状态") - @EN("Right-click in the air for temperature; sneak for atmospheric composition and thermal status") + @CN("对空气右键打开环境检测面板") + @EN("Right-click in the air to open the environment panel") private static Lang usage; @Key("tooltip.ctnhcore.thermometer.readings") - @CN("读数显示在聊天栏,每秒可检测一次") - @EN("Readings appear in chat; one scan per second") + @CN("每秒刷新读数,按 Esc 关闭") + @EN("Updates every second; press Esc to close") private static Lang readings; + @Key("gui.ctnhcore.environment_detector.close") + @CN("关闭") + @EN("Close") + private static Lang close; + @Key("message.ctnhcore.thermometer.header") @CN("环境检测读数") @EN("Environment readings") private static Lang header; @Key("message.ctnhcore.thermometer.location") - @CN("位置:%1$s [%2$s, %3$s, %4$s]") - @EN("Location: %1$s [%2$s, %3$s, %4$s]") + @CN("维度 %s") + @EN("Dimension %s") private static Lang location; + @Key("gui.ctnhcore.environment_detector.coordinates") + @CN("坐标 X %1$s · Y %2$s · Z %3$s") + @EN("Position X %1$s · Y %2$s · Z %3$s") + private static Lang coordinates; + + @Key("gui.ctnhcore.environment_detector.conditions") + @CN("环境条件") + @EN("Environment conditions") + private static Lang environmentConditions; + @Key("message.ctnhcore.thermometer.temperature") - @CN("环境温度:%s ℃") - @EN("Ambient temperature: %s °C") + @CN("环境温度") + @EN("Ambient temperature") private static Lang temperature; @Key("message.ctnhcore.thermometer.thermal_status") - @CN("玩家冷热累积:失温 %1$s%% / 热射病 %2$s%%") - @EN("Player thermal exposure: hypothermia %1$s%% / hyperthermia %2$s%%") + @CN("玩家冷热累积") + @EN("Player thermal exposure") private static Lang thermalStatus; + @Key("gui.ctnhcore.environment_detector.hypothermia") + @CN("失温累积") + @EN("Hypothermia") + private static Lang hypothermia; + + @Key("gui.ctnhcore.environment_detector.hyperthermia") + @CN("热射病累积") + @EN("Hyperthermia") + private static Lang hyperthermia; + + @Key("gui.ctnhcore.environment_detector.no_thermal_data") + @CN("暂无读数") + @EN("Unavailable") + private static Lang noThermalData; + @Key("message.ctnhcore.thermometer.pressure") - @CN("总压:%s atm") - @EN("Total pressure: %s atm") + @CN("总气压") + @EN("Total pressure") private static Lang totalPressure; + @Key("gui.ctnhcore.environment_detector.radiation") + @CN("辐射剂量率") + @EN("Radiation dose rate") + private static Lang radiation; + + @Key("gui.ctnhcore.environment_detector.corrosion") + @CN("腐蚀速率") + @EN("Corrosion rate") + private static Lang corrosion; + @Key("message.ctnhcore.thermometer.vacuum") @CN("真空:无气体") @EN("Vacuum: no gases") private static Lang vacuum; @Key("message.ctnhcore.thermometer.composition") - @CN("大气成分(分压 / 占比):") - @EN("Atmospheric composition (partial pressure / share):") + @CN("大气成分") + @EN("Atmospheric composition") private static Lang composition; @Key("message.ctnhcore.thermometer.gas") - @CN(" %1$s:%2$s atm / %3$s%%") - @EN(" %1$s: %2$s atm / %3$s%%") + @CN("分压 %1$s · 占比 %2$s") + @EN("Pressure %1$s · Share %2$s") private static Lang gasReading; @Key("message.ctnhcore.thermometer.unlisted") @@ -93,18 +164,12 @@ public static void onRightClickItem(PlayerInteractEvent.RightClickItem event) { Player player = event.getEntity(); if (!event.getItemStack().is(ItemRegistry.THERMOMETER.get())) return; - // 两侧均消费本次使用,避免继续处理另一只手;测量和冷却只由服务端执行。 + // 两侧均消费本次使用,避免继续处理另一只手;由服务端打开并同步面板。 event.setCanceled(true); event.setCancellationResult(InteractionResult.sidedSuccess(event.getLevel().isClientSide)); - if (event.getLevel() instanceof ServerLevel level && + if (player instanceof ServerPlayer serverPlayer && !player.getCooldowns().isOnCooldown(ItemRegistry.THERMOMETER.get())) { - if (player.isShiftKeyDown()) { - report(level, player); - } else { - float celsius = PlanetEnvironmentService.getEnvironment(level, player.blockPosition()) - .get(Temperature.TYPE).celsius(); - player.displayClientMessage(temperature.translate(String.format(Locale.ROOT, "%.1f", celsius)), true); - } + HeldItemUIFactory.INSTANCE.openUI(serverPlayer, event.getHand()); player.getCooldowns().addCooldown(ItemRegistry.THERMOMETER.get(), 20); } } @@ -116,53 +181,172 @@ public static void onItemTooltip(ItemTooltipEvent event) { event.getToolTip().add(readings.translate().withStyle(ChatFormatting.DARK_GRAY)); } - private static void report(ServerLevel level, Player player) { + public static ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { + var data = new PanelReadings(); + updateReadings(player, data); + var content = new WidgetGroup(8, 0, 264, 0) { + + @Override + public void detectAndSendChanges() { + if (gui.getTickCount() % 20 == 0) { + updateReadings(player, data); + super.detectAndSendChanges(); + } + } + }; + content.setLayout(Layout.VERTICAL_LEFT); + content.setLayoutPadding(6); + content.setDynamicSized(true); + content.addWidget(new ComponentPanelWidget(0, 0, text -> text.addAll(data.location)) + .setMaxWidthLimit(264).setSpace(3)); + content.addWidget(section(environmentConditions)); + content.addWidget(new WidgetGroup(0, 0, 264, 32) + .addWidget(readingCard(0, temperature, TEMPERATURE_COLOR, () -> data.temperature)) + .addWidget(readingCard(136, totalPressure, PRESSURE_COLOR, () -> data.pressure))); + content.addWidget(new WidgetGroup(0, 0, 264, 32) + .addWidget(readingCard(0, radiation, RADIATION_COLOR, () -> data.radiation)) + .addWidget(readingCard(136, corrosion, CORROSION_COLOR, () -> data.corrosion))); + content.addWidget(section(thermalStatus)); + content.addWidget(new WidgetGroup(0, 0, 264, 38) + .addWidget(thermalCard(0, hypothermia, COLD_COLOR, () -> data.coldValue, () -> data.coldProgress)) + .addWidget(thermalCard(136, hyperthermia, HEAT_COLOR, () -> data.heatValue, () -> data.heatProgress))); + content.addWidget(section(composition)); + content.addWidget(new ComponentPanelWidget(0, 0, text -> text.addAll(data.gases)) + .setMaxWidthLimit(264).setSpace(3)); + + var scroll = new DraggableScrollableWidgetGroup(8, 30, 284, 180) + .setBackground(GuiTextures.DISPLAY) + .setYScrollBarWidth(4) + .setYBarStyle(null, ColorPattern.T_WHITE.rectTexture().setRadius(2)); + scroll.addWidget(content); + + return new ModularUI(300, 238, holder, player) + .background(GuiTextures.BACKGROUND) + .widget(new LabelWidget(12, 12, header.translate()).setTextColor(0xFF404040).setDropShadow(false)) + .widget(scroll) + .widget(new LabelWidget(12, 221, readings.translate()).setTextColor(0xFF404040).setDropShadow(false)) + .widget(new ButtonWidget(270, 7, 18, 18, click -> { + if (player instanceof ServerPlayer serverPlayer) { + serverPlayer.closeContainer(); + } + }).setButtonTexture(GuiTextures.BUTTON, GuiTextures.CLOSE_ICON) + .setHoverTooltips(close.translate())); + } + + private static WidgetGroup section(Lang title) { + return new WidgetGroup(0, 0, 264, 14) + .addWidget(new LabelWidget(0, 0, title.translate().withStyle(ChatFormatting.BOLD)) + .setTextColor(0xFF000000 | TEXT_COLOR).setDropShadow(false)) + .addWidget(new ImageWidget(0, 12, 264, 1, new ColorRectTexture(0xFF42545F))); + } + + private static WidgetGroup readingCard(int x, Lang title, int color, Supplier value) { + var card = new WidgetGroup(x, 0, 128, 32); + card.setBackground(new ColorRectTexture(0xFF20313B)); + card.addWidget(new ImageWidget(0, 0, 2, 32, new ColorRectTexture(0xFF000000 | color))); + card.addWidget(new LabelWidget(8, 5, title.translate()) + .setTextColor(0xFF000000 | MUTED_COLOR).setDropShadow(false)); + card.addWidget(new ComponentPanelWidget(8, 18, text -> text.add(value.get())).setMaxWidthLimit(112)); + return card; + } + + private static WidgetGroup thermalCard(int x, Lang title, int color, Supplier value, + DoubleSupplier progress) { + var card = readingCard(x, title, color, value); + card.setSizeHeight(38); + card.addWidget(new ProgressWidget(() -> Math.min(1.0, progress.getAsDouble()), 8, 31, 112, 3) + .setProgressTexture(new ColorRectTexture(0xFF101C24), new ColorRectTexture(0xFF000000 | color))); + return card; + } + + private static void updateReadings(Player player, PanelReadings data) { + // 客户端只展示同步后的文本,不自行计算环境或读取服务端医疗状态。 + if (!(player.level() instanceof ServerLevel level)) return; var pos = player.blockPosition(); var environment = PlanetEnvironmentService.getEnvironment(level, pos); Atmosphere atmosphere = environment.get(Atmosphere.TYPE); - MutableComponent message = header.translate().withStyle(ChatFormatting.AQUA); - line(message, location, level.dimension().location().toString(), pos.getX(), pos.getY(), pos.getZ()); - line(message, temperature, String.format(Locale.ROOT, "%.1f", environment.get(Temperature.TYPE).celsius())); + data.location = List.of( + location.translate(value(level.dimension().location().toString(), TEXT_COLOR)) + .withStyle(style -> style.withColor(MUTED_COLOR)), + coordinates.translate(value(Integer.toString(pos.getX()), TEXT_COLOR), + value(Integer.toString(pos.getY()), TEXT_COLOR), + value(Integer.toString(pos.getZ()), TEXT_COLOR)) + .withStyle(style -> style.withColor(MUTED_COLOR))); + data.temperature = quantity(String.format(Locale.ROOT, "%.1f", environment.get(Temperature.TYPE).celsius()), + "°C", TEMPERATURE_COLOR); + data.pressure = quantity(number(atmosphere.pressure()), "atm", PRESSURE_COLOR); + data.radiation = quantity(number(environment.get(Radiation.TYPE).rate()), "rad/s", RADIATION_COLOR); + data.corrosion = quantity(number(environment.get(Corrosion.TYPE).rate()), "mm/a", CORROSION_COLOR); + + data.coldProgress = 0.0; + data.heatProgress = 0.0; + data.coldValue = noThermalData.translate().withStyle(style -> style.withColor(MUTED_COLOR)); + data.heatValue = data.coldValue; var tracker = GTCapabilityHelper.getMedicalConditionTracker(player); if (tracker != null && ConfigHolder.INSTANCE.gameplay.hazardsEnabled) { var conditions = tracker.getMedicalConditions(); - line(message, thermalStatus, - String.format(Locale.ROOT, "%.1f", Math.max(0.0F, - conditions.getFloat(CAMedicalConditions.HYPOTHERMIA)) * 100.0F / - CAMedicalConditions.HYPOTHERMIA.maxProgression), - String.format(Locale.ROOT, "%.1f", Math.max(0.0F, - conditions.getFloat(CAMedicalConditions.HYPERTHERMIA)) * 100.0F / - CAMedicalConditions.HYPERTHERMIA.maxProgression)); + data.coldProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPOTHERMIA)) / + CAMedicalConditions.HYPOTHERMIA.maxProgression; + data.heatProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPERTHERMIA)) / + CAMedicalConditions.HYPERTHERMIA.maxProgression; + data.coldValue = quantity(String.format(Locale.ROOT, "%.1f", data.coldProgress * 100.0), "%", COLD_COLOR); + data.heatValue = quantity(String.format(Locale.ROOT, "%.1f", data.heatProgress * 100.0), "%", HEAT_COLOR); } + + data.gases = new ArrayList<>(); float pressure = atmosphere.pressure(); - line(message, totalPressure, number(pressure)); if (pressure == 0.0F) { - line(message, vacuum); + data.gases.add(vacuum.translate().withStyle(ChatFormatting.GOLD)); } else { - line(message, composition); new TreeMap<>(atmosphere.partialPressures()).forEach((gas, partialPressure) -> { Component name = Component.translatableWithFallback( "gas." + gas.getNamespace() + "." + gas.getPath().replace('/', '.'), gas.toString()); - line(message, gasReading, name, number(partialPressure), number(100.0 * partialPressure / pressure)); + gasReadings(data.gases, name, partialPressure, 100.0 * partialPressure / pressure); }); double described = atmosphere.partialPressures().values().stream().mapToDouble(Float::doubleValue).sum(); double remainder = pressure - described; // 忽略浮点归一化的一位舍入误差,不把已描述完整的成分报为额外背景。 if (remainder > Math.ulp(pressure)) { - line(message, gasReading, unlisted.translate(), number(remainder), - number(100.0 * remainder / pressure)); + gasReadings(data.gases, unlisted.translate(), remainder, 100.0 * remainder / pressure); } } - player.sendSystemMessage(message); } - private static void line(MutableComponent message, Lang key, Object... args) { - message.append("\n").append(key.translate(args).withStyle(ChatFormatting.GRAY)); + private static void gasReadings(List text, Component name, double partialPressure, double share) { + if (!text.isEmpty()) text.add(Component.empty()); + text.add(name.copy().withStyle(style -> style.withColor(TEXT_COLOR).withBold(true))); + text.add(gasReading.translate(quantity(number(partialPressure), "atm", PRESSURE_COLOR), + quantity(String.format(Locale.ROOT, "%.1f", share), "%", TEMPERATURE_COLOR)) + .withStyle(style -> style.withColor(MUTED_COLOR))); + } + + private static MutableComponent value(String value, int color) { + return Component.literal(value).withStyle(style -> style.withColor(color).withBold(true)); + } + + private static Component quantity(String value, String unit, int color) { + return value(value, color) + .append(Component.literal(" " + unit).withStyle(style -> style.withColor(MUTED_COLOR).withBold(false))); } private static String number(double value) { return String.format(Locale.ROOT, "%.4g", value); } + /** 每个打开的面板各自持有显示值;所有读数在同一次服务端采样中更新。 */ + private static final class PanelReadings { + + private List location = List.of(); + private Component temperature = Component.empty(); + private Component pressure = Component.empty(); + private Component radiation = Component.empty(); + private Component corrosion = Component.empty(); + private Component coldValue = Component.empty(); + private Component heatValue = Component.empty(); + private double coldProgress; + private double heatProgress; + private List gases = List.of(); + } + private ThermometerEnvironmentIntegration() {} } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java index bfb737424..819d1a1b5 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java @@ -1,6 +1,12 @@ package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; +import io.github.cpearl0.ctnhcore.integration.legendary.ThermometerEnvironmentIntegration; + +import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; +import com.lowdragmc.lowdraglib.gui.modular.ModularUI; + import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; @@ -19,9 +25,9 @@ import java.util.List; -/** 为 LSO 温度计使用 Core 的名称翻译键,避免跨命名空间的语言覆盖顺序影响显示。 */ +/** 为 LSO 温度计提供 Core 的名称翻译键和环境检测物品面板。 */ @Mixin(ThermometerItem.class) -public abstract class ThermometerItemMixin extends Item { +public abstract class ThermometerItemMixin extends Item implements HeldItemUIFactory.IHeldItemUIHolder { @Unique @Key("item.ctnhcore.environment_detector") @@ -38,6 +44,11 @@ public String getDescriptionId() { return ctnhcore$environmentDetectorName.key(); } + @Override + public ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { + return ThermometerEnvironmentIntegration.createUI(player, holder); + } + /** 使用说明由 Core 的物品提示事件提供,移除原有体温/饰品 HUD 说明。 */ @Inject(method = "appendHoverText", at = @At("HEAD"), cancellable = true, require = 1) private void ctnhcore$environmentTooltip(ItemStack stack, Level level, List tooltip, From 6137d0eb3eb51363addd9236e838571234c504af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=8F=E4=BC=9F?= <16601765+daijugui@user.noreply.gitee.com> Date: Sun, 4 Oct 2026 16:32:35 +0800 Subject: [PATCH 3/6] =?UTF-8?q?chore:=20=E8=BF=81=E7=A7=BB=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E6=B3=A8=E5=86=8C=E4=B8=8E=E6=8E=92=E6=94=BE=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multiblock/electric/BioMachine.java | 5 ++-- .../electric/FermentingTankMachine.java | 5 ++-- ...ndustrialPrimitiveBlastFurnaceMachine.java | 5 ++-- .../machine/trait/UnderfloorHeatingTrait.java | 14 +++++----- .../EnvironmentTemperatureIntegration.java | 27 ++++++++++--------- .../ThermometerEnvironmentIntegration.java | 13 +++++---- .../TemperatureItemCapabilityMixin.java | 4 +-- 7 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java index 9a05569c0..caa47688b 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/BioMachine.java @@ -14,7 +14,7 @@ import net.minecraft.server.level.ServerLevel; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.registry.CAEnvironments; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Prefix; @@ -89,7 +89,8 @@ protected void updateTempSubscription() { protected void updateCurrentTemperature() { if (getOffsetTimer() % 10 == 0 && getLevel() instanceof ServerLevel level) { - machineTemperature = PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + machineTemperature = PlanetEnvironmentService.getEnvironment(level, getPos()) + .get(CAEnvironments.TEMPERATURE) .celsius(); } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java index 6920763db..83fe749e7 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/FermentingTankMachine.java @@ -22,7 +22,7 @@ import net.minecraft.server.level.ServerLevel; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.registry.CAEnvironments; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Prefix; @@ -111,7 +111,8 @@ protected void updateTempSubscription() { protected void updateCurrentTemperature() { if (getOffsetTimer() % 10 == 0 && getLevel() instanceof ServerLevel level) { - Machine_Temperature = PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + Machine_Temperature = PlanetEnvironmentService.getEnvironment(level, getPos()) + .get(CAEnvironments.TEMPERATURE) .celsius(); } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java index 1c38eecdd..7060e8b80 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/kinetic/IndustrialPrimitiveBlastFurnaceMachine.java @@ -17,7 +17,7 @@ import net.minecraft.util.Mth; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.registry.CAEnvironments; import com.ctnhlang.CN; import com.ctnhlang.EN; import lombok.Getter; @@ -98,7 +98,8 @@ protected void updateTempSubscription() { protected void updateCurrentTemperature() { if (!(getLevel() instanceof ServerLevel level)) return; - basicTemperature = (int) PlanetEnvironmentService.getEnvironment(level, getPos()).get(Temperature.TYPE) + basicTemperature = (int) PlanetEnvironmentService.getEnvironment(level, getPos()) + .get(CAEnvironments.TEMPERATURE) .kelvin(); if (recipeLogic.isWorking()) { if (getOffsetTimer() % 10 == 0) { diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java index 037381502..c581e9e84 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/trait/UnderfloorHeatingTrait.java @@ -13,10 +13,10 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.phys.AABB; -import com.ctnh.ctnhastral.common.environment.EnvironmentArea; -import com.ctnh.ctnhastral.common.environment.EnvironmentDelta; +import com.ctnh.ctnhastral.common.environment.Environment; import com.ctnh.ctnhastral.common.environment.EnvironmentEmission; -import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.registry.CAEnvironments; import lombok.Getter; /** 地暖功率、效率与排放生命周期的唯一所有者。 */ @@ -65,13 +65,15 @@ public boolean emitHeat() { case EAST -> AABB.of(BoundingBox.fromCorners(pos.offset(-47, 0, -39), pos.offset(32, 16, 40))); default -> throw new IllegalStateException("Invalid floor heating orientation"); }; - new EnvironmentEmission(pos, new EnvironmentArea.Box(bounds), - EnvironmentDelta.of(Temperature.TYPE, (float) (30.0 * efficiency * rate / 100.0))).emit(level, 2); + PlanetEnvironmentService.emit(level, + new EnvironmentEmission(pos, new EnvironmentEmission.Box(bounds), + Environment.Delta.of(CAEnvironments.TEMPERATURE, (float) (30.0 * efficiency * rate / 100.0))), + 2); return true; } public void stopHeating() { - if (machine.getLevel() instanceof ServerLevel level) EnvironmentEmission.cease(level, machine.getPos()); + if (machine.getLevel() instanceof ServerLevel level) PlanetEnvironmentService.cease(level, machine.getPos()); } @Override diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java index 9dd6a32e2..4987c7136 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/EnvironmentTemperatureIntegration.java @@ -6,8 +6,9 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import com.ctnh.ctnhastral.common.environment.BlockTemperature; -import com.ctnh.ctnhastral.common.environment.TemperatureClimate; +import com.ctnh.ctnhastral.common.environment.NaturalTemperature; +import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.registry.CAEnvironments; import com.teamtea.eclipticseasons.api.EclipticSeasonsApi; import com.teamtea.eclipticseasons.api.constant.solar.SolarTerm; import com.teamtea.eclipticseasons.api.util.EclipticUtil; @@ -25,29 +26,29 @@ public final class EnvironmentTemperatureIntegration { private EnvironmentTemperatureIntegration() {} public static void init() { - TemperatureClimate.register(Level.OVERWORLD, EnvironmentTemperatureIntegration::overworldClimate); - BlockTemperature.register(BlockRegistry.HEATER.get(), + CAEnvironments.registerClimateSource(Level.OVERWORLD, EnvironmentTemperatureIntegration::overworldClimate); + CAEnvironments.registerBlockTemperature(BlockRegistry.HEATER.get(), state -> state.getValue(BlockStateProperties.LIT) ? 15.0F : 0.0F); - BlockTemperature.register(BlockRegistry.COOLER.get(), + CAEnvironments.registerBlockTemperature(BlockRegistry.COOLER.get(), state -> state.getValue(BlockStateProperties.LIT) ? -15.0F : 0.0F); - BlockTemperature.register(BlockRegistry.SUN_FERN_CROP.get(), + CAEnvironments.registerBlockTemperature(BlockRegistry.SUN_FERN_CROP.get(), state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? 1.5F : 0.0F); - BlockTemperature.register(BlockRegistry.SUN_FERN_GOLD.get(), + CAEnvironments.registerBlockTemperature(BlockRegistry.SUN_FERN_GOLD.get(), state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? 1.5F : 0.0F); - BlockTemperature.register(BlockRegistry.ICE_FERN_CROP.get(), + CAEnvironments.registerBlockTemperature(BlockRegistry.ICE_FERN_CROP.get(), state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? -1.5F : 0.0F); - BlockTemperature.register(BlockRegistry.ICE_FERN_GOLD.get(), + CAEnvironments.registerBlockTemperature(BlockRegistry.ICE_FERN_GOLD.get(), state -> state.getValue(BlockStateProperties.AGE_3) == 3 ? -1.5F : 0.0F); } - private static TemperatureClimate overworldClimate(ServerLevel level, BlockPos pos) { - var vanilla = TemperatureClimate.vanilla(level, pos); + private static Temperature.Climate overworldClimate(ServerLevel level, BlockPos pos) { + var vanilla = NaturalTemperature.vanillaClimate(level, pos); var seasons = EclipticSeasonsApi.getInstance(); var precipitation = seasons.hasLocalWeather(level) ? seasons.getCurrentPrecipitationAt(level, pos) : vanilla.precipitation(); SolarTerm term = seasons.getSolarTerm(level); if (!seasons.isSeasonEnabled(level) || term == SolarTerm.NONE) { - return new TemperatureClimate(0.0F, 12000, precipitation); + return new Temperature.Climate(0.0F, 12000, precipitation); } double day = Math.floorMod(level.getDayTime(), 24000L) / 24000.0; float progress = Mth.clamp((float) ((EclipticUtil.getTimeInSolarTerm(level) + day) / @@ -57,6 +58,6 @@ private static TemperatureClimate overworldClimate(ServerLevel level, BlockPos p int to = progress < 0.5F ? current : (current + 1) % 24; float blend = progress < 0.5F ? progress + 0.5F : progress - 0.5F; float offset = Mth.lerp(blend, SEASON_OFFSETS[from], SEASON_OFFSETS[to]); - return new TemperatureClimate(offset, term.getDayTime(), precipitation); + return new Temperature.Climate(offset, term.getDayTime(), precipitation); } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java index 101714e9d..d247fe166 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java @@ -32,11 +32,9 @@ import net.minecraftforge.fml.common.Mod; import com.ctnh.ctnhastral.common.environment.Atmosphere; -import com.ctnh.ctnhastral.common.environment.Corrosion; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.common.environment.Radiation; -import com.ctnh.ctnhastral.common.environment.Temperature; import com.ctnh.ctnhastral.data.CAMedicalConditions; +import com.ctnh.ctnhastral.registry.CAEnvironments; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Key; @@ -264,7 +262,7 @@ private static void updateReadings(Player player, PanelReadings data) { if (!(player.level() instanceof ServerLevel level)) return; var pos = player.blockPosition(); var environment = PlanetEnvironmentService.getEnvironment(level, pos); - Atmosphere atmosphere = environment.get(Atmosphere.TYPE); + Atmosphere atmosphere = environment.get(CAEnvironments.ATMOSPHERE); data.location = List.of( location.translate(value(level.dimension().location().toString(), TEXT_COLOR)) .withStyle(style -> style.withColor(MUTED_COLOR)), @@ -272,11 +270,12 @@ private static void updateReadings(Player player, PanelReadings data) { value(Integer.toString(pos.getY()), TEXT_COLOR), value(Integer.toString(pos.getZ()), TEXT_COLOR)) .withStyle(style -> style.withColor(MUTED_COLOR))); - data.temperature = quantity(String.format(Locale.ROOT, "%.1f", environment.get(Temperature.TYPE).celsius()), + data.temperature = quantity( + String.format(Locale.ROOT, "%.1f", environment.get(CAEnvironments.TEMPERATURE).celsius()), "°C", TEMPERATURE_COLOR); data.pressure = quantity(number(atmosphere.pressure()), "atm", PRESSURE_COLOR); - data.radiation = quantity(number(environment.get(Radiation.TYPE).rate()), "rad/s", RADIATION_COLOR); - data.corrosion = quantity(number(environment.get(Corrosion.TYPE).rate()), "mm/a", CORROSION_COLOR); + data.radiation = quantity(number(environment.get(CAEnvironments.RADIATION).rate()), "rad/s", RADIATION_COLOR); + data.corrosion = quantity(number(environment.get(CAEnvironments.CORROSION).rate()), "mm/a", CORROSION_COLOR); data.coldProgress = 0.0; data.heatProgress = 0.0; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java index caf70899a..f60ca00f1 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/TemperatureItemCapabilityMixin.java @@ -8,7 +8,7 @@ import com.ctnh.ctnhastral.client.ClientEnvironmentTemperature; import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.common.environment.Temperature; +import com.ctnh.ctnhastral.registry.CAEnvironments; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -31,7 +31,7 @@ public abstract class TemperatureItemCapabilityMixin { private void ctnh$serverReading(Level level, Entity entity, long tick, CallbackInfo ci) { var pos = WorldUtil.getSidedBlockPos(level, entity); float temperature = level instanceof ServerLevel serverLevel ? - PlanetEnvironmentService.getEnvironment(serverLevel, pos).get(Temperature.TYPE).celsius() : + PlanetEnvironmentService.getEnvironment(serverLevel, pos).get(CAEnvironments.TEMPERATURE).celsius() : DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> () -> ClientEnvironmentTemperature.celsius(level, pos)); if (Float.isFinite(temperature)) { From 5f2340a4b3eb14de83259d0cd7fa6002deb9e0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=8F=E4=BC=9F?= <16601765+daijugui@user.noreply.gitee.com> Date: Mon, 5 Oct 2026 18:30:22 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E6=9C=88=E7=90=83=E7=BE=A4?= =?UTF-8?q?=E7=B3=BB=E7=9A=84=E8=BF=9B=E4=B8=80=E6=AD=A5=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=8F=8A=E8=87=AA=E5=AE=9A=E4=B9=89=E6=9D=90=E6=96=99=E7=9A=84?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/assets/ctnhcore/lang/en_ud.json | 25 +- .../resources/assets/ctnhcore/lang/en_us.json | 25 +- .../resources/assets/ctnhcore/lang/zh_cn.json | 15 +- .../tags/blocks/moon_ore_replaceables.json | 10 + .../forge/tags/blocks/ad_astra_stones.json | 4 - .../common/gui/EnvironmentDetectorUI.java | 487 ++++++++++++++++++ .../common/item/AstronomyCircuitItem.java | 2 +- .../SpacePhotovoltaicBaseStation.java | 3 +- .../generator/PhotoVoltaicDroneStation.java | 3 +- .../PhotovoltaicPowerStationMachine.java | 4 +- .../ctnhcore/data/recipe/AdAstraRecipes.java | 16 +- .../data/recipe/CTNHCoreRecipeAddition.java | 1 + .../data/recipe/MoonMaterialRecipes.java | 80 +++ .../ctnhcore/data/recipe/NanoRecipes.java | 5 +- .../recipe/migrated/GtceuScriptRecipes.java | 3 +- .../cpearl0/ctnhcore/data/tags/StoneTags.java | 6 +- .../ThermometerEnvironmentIntegration.java | 294 +---------- .../ThermometerItemMixin.java | 4 +- .../registry/CTNHDimensionMarkers.java | 5 +- .../cpearl0/ctnhcore/registry/CTNHOres.java | 2 + .../cpearl0/ctnhcore/registry/CTNHTags.java | 2 + .../ctnhcore/registry/CTNHWorldgenLayers.java | 12 +- .../cpearl0/ctnhcore/registry/CTNHWorlds.java | 4 +- .../ctnhcore/registry/ores/AdAstraOres.java | 101 +--- .../ctnhcore/registry/ores/MoonOres.java | 212 ++++++++ 25 files changed, 891 insertions(+), 434 deletions(-) create mode 100644 src/generated/resources/data/ctnhcore/tags/blocks/moon_ore_replaceables.json create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/common/gui/EnvironmentDetectorUI.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java diff --git a/src/generated/resources/assets/ctnhcore/lang/en_ud.json b/src/generated/resources/assets/ctnhcore/lang/en_ud.json index a5da1b9a7..adda6e208 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_ud.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_ud.json @@ -812,6 +812,7 @@ "ctnhcore.ore_vein.borax_vein_ed": "uıǝΛ xɐɹoᗺ puƎ", "ctnhcore.ore_vein.calorite_vein_ad": "uıǝΛ ǝʇıɹoןɐƆ ǝɔɐdS", "ctnhcore.ore_vein.cassiterite_vein_ad": "uıǝΛ ǝʇıɹǝʇıssɐƆ ǝɔɐdS", + "ctnhcore.ore_vein.cassiterite_vein_moon": "uıǝΛ ǝʇıɹǝʇıssɐƆ uooW", "ctnhcore.ore_vein.cassiterite_vein_ow": "uıǝΛ ǝʇıɹǝʇıssɐƆ pןɹoʍɹǝʌO", "ctnhcore.ore_vein.certus_quartz_nt": "zʇɹɐnὉ snʇɹǝƆ ɹǝɥʇǝN", "ctnhcore.ore_vein.chromite_vein_ed": "uıǝΛ ǝʇıɯoɹɥƆ puƎ", @@ -819,6 +820,7 @@ "ctnhcore.ore_vein.coal_vein_ow": "uıǝΛ ןɐoƆ pןɹoʍɹǝʌO", "ctnhcore.ore_vein.copper_tin_vein_ow": "uıǝΛ uı⟘ ɹǝddoƆ pןɹoʍɹǝʌO", "ctnhcore.ore_vein.copper_vein_ad": "uıǝΛ ɹǝddoƆ ǝɔɐdS", + "ctnhcore.ore_vein.copper_vein_moon": "uıǝΛ ɹǝddoƆ uooW", "ctnhcore.ore_vein.copper_vein_ow": "uıǝΛ ɹǝddoƆ pןɹoʍɹǝʌO", "ctnhcore.ore_vein.cryolite_vein_ed": "uıǝΛ ǝʇıןoʎɹƆ puƎ", "ctnhcore.ore_vein.cryolite_vein_tf": "uıǝΛ ǝʇıןoʎɹƆ ʇsǝɹoℲ ʇɥbıןıʍ⟘", @@ -831,6 +833,7 @@ "ctnhcore.ore_vein.emerald_vein_at": "uıǝΛ pןɐɹǝɯƎ ɹǝɥʇǝⱯ", "ctnhcore.ore_vein.europium_vein": "uıǝΛ ǝʇıɹonןℲ ɯnıdoɹnƎ", "ctnhcore.ore_vein.galena_vein_ad": "uıǝΛ ɐuǝןɐ⅁ ǝɔɐdS", + "ctnhcore.ore_vein.galena_vein_moon": "uıǝΛ ɐuǝןɐ⅁ uooW", "ctnhcore.ore_vein.galena_vein_tf": "uıǝΛ ɐuǝןɐ⅁ ʇsǝɹoℲ ʇɥbıןıʍ⟘", "ctnhcore.ore_vein.illusion_iron_vein_tf": "uıǝΛ uoɹI uoısnןןI ʇsǝɹoℲ ʇɥbıןıʍ⟘", "ctnhcore.ore_vein.ilmenite_vein": "uıǝΛ ǝʇıuǝɯןI", @@ -851,7 +854,9 @@ "ctnhcore.ore_vein.manganese_vein_nt": "uıǝΛ ǝsǝuɐbuɐW ɹǝɥʇǝN", "ctnhcore.ore_vein.manganese_vein_ow": "uıǝΛ ǝsǝuɐbuɐW pןɹoʍɹǝʌO", "ctnhcore.ore_vein.molybdenum_vein_ad": "uıǝΛ ǝʇıuǝpqʎןoW ǝɔɐdS", + "ctnhcore.ore_vein.molybdenum_vein_moon": "uıǝΛ ǝʇıuǝpqʎןoW uooW", "ctnhcore.ore_vein.molybdenum_vein_nt": "uıǝΛ ɯnuǝpqʎןoW ɹǝɥʇǝN", + "ctnhcore.ore_vein.monazite_vein_moon": "uıǝΛ ǝʇızɐuoW uooW", "ctnhcore.ore_vein.monazite_vein_n": "uıǝΛ ǝʇızɐuoW uooW", "ctnhcore.ore_vein.monazite_vein_nt": "uıǝΛ ǝʇızɐuoW ɹǝɥʇǝN", "ctnhcore.ore_vein.naquadah_vein_ad": "uıǝΛ ɥɐpɐnbɐN snuǝΛ", @@ -874,6 +879,7 @@ "ctnhcore.ore_vein.precious_alloy_vein_ow": "uıǝΛ ʎoןןⱯ snoıɔǝɹԀ pןɹoʍɹǝʌO", "ctnhcore.ore_vein.pyrolusite_vein_ad": "uıǝΛ ǝʇısnןoɹʎԀ snuǝΛ", "ctnhcore.ore_vein.quartzite_vein": "uıǝΛ ǝʇızʇɹɐnὉ", + "ctnhcore.ore_vein.quartzite_vein_moon": "uıǝΛ ǝʇızʇɹɐnὉ uooW", "ctnhcore.ore_vein.redstone_vein_ad": "uıǝΛ ǝuoʇspǝᴚ ǝɔɐdS", "ctnhcore.ore_vein.redstone_vein_at": "uıǝΛ ǝuoʇspǝᴚ ɹǝɥʇǝⱯ", "ctnhcore.ore_vein.redstone_vein_nt": "uıǝΛ ǝuoʇspǝᴚ ɹǝɥʇǝN", @@ -1078,13 +1084,17 @@ "gui.ctnh.neutron_sensor.invert.disabled": "˙ǝnןɐʌ ɯnɯıuıɯ ǝɥʇ uɐɥʇ ssǝן sı ʇı uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ buıʇʇıɯǝ doʇs puɐ 'sǝnןɐʌ ɯnɯıxɐɯ puɐ ɯnɯıuıɯ ʇǝs ǝɥʇ uǝǝʍʇǝq sı ʎbɹǝuǝ ɔıʇǝuıʞ uoɹʇnǝu ǝɥʇ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ ʇıɯǝ ןןıʍ ɹosuǝs ǝɥʇ 'ʇןnɐɟǝp ʎᗺ\nɔıboן ǝuoʇspǝɹ ǝsɹǝʌǝɹ oʇ ɥɔʇıʍS\n\nןɐɯɹoN :ʇndʇnO", "gui.ctnh.neutron_sensor.invert.enabled": "˙ǝnןɐʌ ɯnɯıuıɯ ǝɥʇ uɐɥʇ ssǝן sı ʇı uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ buıʇʇıɯǝ doʇs puɐ 'sǝnןɐʌ ɯnɯıxɐɯ puɐ ɯnɯıuıɯ ʇǝs ǝɥʇ uǝǝʍʇǝq sı ʎbɹǝuǝ ɔıʇǝuıʞ uoɹʇnǝu ǝɥʇ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ ʇıɯǝ ןןıʍ ɹosuǝs ǝɥʇ 'ʇןnɐɟǝp ʎᗺ\nɔıboן ǝuoʇspǝɹ ǝsɹǝʌǝɹ oʇ ɥɔʇıʍS\n\nǝsɹǝʌǝᴚ :ʇndʇnO", "gui.ctnhcore.environment_detector.close": "ǝsoןƆ", + "gui.ctnhcore.environment_detector.close_hint": "ǝsoןɔ oʇ ɔsƎ", "gui.ctnhcore.environment_detector.conditions": "suoıʇıpuoɔ ʇuǝɯuoɹıʌuƎ", "gui.ctnhcore.environment_detector.coordinates": "%3$s Z · %2$s ʎ · %1$s X uoıʇısoԀ", - "gui.ctnhcore.environment_detector.corrosion": "ǝʇɐɹ uoısoɹɹoƆ", + "gui.ctnhcore.environment_detector.corrosion": "uoısoɹɹoƆ", "gui.ctnhcore.environment_detector.hyperthermia": "ɐıɯɹǝɥʇɹǝdʎH", "gui.ctnhcore.environment_detector.hypothermia": "ɐıɯɹǝɥʇodʎH", "gui.ctnhcore.environment_detector.no_thermal_data": "ǝןqɐןıɐʌɐu∩", - "gui.ctnhcore.environment_detector.radiation": "ǝʇɐɹ ǝsop uoıʇɐıpɐᴚ", + "gui.ctnhcore.environment_detector.partial_pressure": ")ɯʇɐ( ǝɹnssǝɹԀ", + "gui.ctnhcore.environment_detector.radiation": "uoıʇɐıpɐᴚ", + "gui.ctnhcore.environment_detector.refresh": "puoɔǝs ʎɹǝʌǝ sǝʇɐpd∩", + "gui.ctnhcore.environment_detector.share": "ǝɹɐɥS", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": ":ǝbuɐᴚ ןɐʇuozıɹoH", "gui.digital_miner.ctnhcore.digitalminer.max_height": ":ʇɥbıǝH xɐW", "gui.digital_miner.ctnhcore.digitalminer.min_height": ":ʇɥbıǝH uıW", @@ -2009,13 +2019,12 @@ "material.ctnhcore.zr_hf_chloride": "ǝpıɹoןɥƆ ɟH ɹZ", "material.ctnhcore.zr_hf_oxy_chloride": "ǝpıɹoןɥƆ ʎxO ɟH ɹZ", "material.ctnhcore.zr_hf_separation_mix": "xıW uoıʇɐɹɐdǝS ɟH ɹZ", - "message.ctnhcore.thermometer.composition": "uoıʇısodɯoɔ ɔıɹǝɥdsoɯʇⱯ", - "message.ctnhcore.thermometer.gas": "%2$s ǝɹɐɥS · %1$s ǝɹnssǝɹԀ", - "message.ctnhcore.thermometer.header": "sbuıpɐǝɹ ʇuǝɯuoɹıʌuƎ", + "message.ctnhcore.thermometer.composition": "ǝɹǝɥdsoɯʇⱯ", + "message.ctnhcore.thermometer.header": "ɹoʇɔǝʇǝᗡ ʇuǝɯuoɹıʌuƎ", "message.ctnhcore.thermometer.location": "%s uoısuǝɯıᗡ", - "message.ctnhcore.thermometer.pressure": "ǝɹnssǝɹd ןɐʇo⟘", - "message.ctnhcore.thermometer.temperature": "ǝɹnʇɐɹǝdɯǝʇ ʇuǝıqɯⱯ", - "message.ctnhcore.thermometer.thermal_status": "ǝɹnsodxǝ ןɐɯɹǝɥʇ ɹǝʎɐןԀ", + "message.ctnhcore.thermometer.pressure": "ǝɹnssǝɹԀ", + "message.ctnhcore.thermometer.temperature": "ǝɹnʇɐɹǝdɯǝ⟘", + "message.ctnhcore.thermometer.thermal_status": "snʇɐʇs ɹǝʎɐןԀ", "message.ctnhcore.thermometer.unlisted": "sǝsɐb pǝıɟıɔǝdsu∩", "message.ctnhcore.thermometer.vacuum": "sǝsɐb ou :ɯnnɔɐΛ", "multiblock.ctnh.nuclear_reactor.consume_amount": "s/ᗺɯ %s :ǝʇɐɹ uoıʇdɯnsuoɔ ʇuɐןooƆ", diff --git a/src/generated/resources/assets/ctnhcore/lang/en_us.json b/src/generated/resources/assets/ctnhcore/lang/en_us.json index be8e0be50..f7b5fc169 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_us.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_us.json @@ -812,6 +812,7 @@ "ctnhcore.ore_vein.borax_vein_ed": "End Borax Vein", "ctnhcore.ore_vein.calorite_vein_ad": "Space Calorite Vein", "ctnhcore.ore_vein.cassiterite_vein_ad": "Space Cassiterite Vein", + "ctnhcore.ore_vein.cassiterite_vein_moon": "Moon Cassiterite Vein", "ctnhcore.ore_vein.cassiterite_vein_ow": "Overworld Cassiterite Vein", "ctnhcore.ore_vein.certus_quartz_nt": "Nether Certus Quartz", "ctnhcore.ore_vein.chromite_vein_ed": "End Chromite Vein", @@ -819,6 +820,7 @@ "ctnhcore.ore_vein.coal_vein_ow": "Overworld Coal Vein", "ctnhcore.ore_vein.copper_tin_vein_ow": "Overworld Copper Tin Vein", "ctnhcore.ore_vein.copper_vein_ad": "Space Copper Vein", + "ctnhcore.ore_vein.copper_vein_moon": "Moon Copper Vein", "ctnhcore.ore_vein.copper_vein_ow": "Overworld Copper Vein", "ctnhcore.ore_vein.cryolite_vein_ed": "End Cryolite Vein", "ctnhcore.ore_vein.cryolite_vein_tf": "Twilight Forest Cryolite Vein", @@ -831,6 +833,7 @@ "ctnhcore.ore_vein.emerald_vein_at": "Aether Emerald Vein", "ctnhcore.ore_vein.europium_vein": "Europium Fluorite Vein", "ctnhcore.ore_vein.galena_vein_ad": "Space Galena Vein", + "ctnhcore.ore_vein.galena_vein_moon": "Moon Galena Vein", "ctnhcore.ore_vein.galena_vein_tf": "Twilight Forest Galena Vein", "ctnhcore.ore_vein.illusion_iron_vein_tf": "Twilight Forest Illusion Iron Vein", "ctnhcore.ore_vein.ilmenite_vein": "Ilmenite Vein", @@ -851,7 +854,9 @@ "ctnhcore.ore_vein.manganese_vein_nt": "Nether Manganese Vein", "ctnhcore.ore_vein.manganese_vein_ow": "Overworld Manganese Vein", "ctnhcore.ore_vein.molybdenum_vein_ad": "Space Molybdenite Vein", + "ctnhcore.ore_vein.molybdenum_vein_moon": "Moon Molybdenite Vein", "ctnhcore.ore_vein.molybdenum_vein_nt": "Nether Molybdenum Vein", + "ctnhcore.ore_vein.monazite_vein_moon": "Moon Monazite Vein", "ctnhcore.ore_vein.monazite_vein_n": "Moon Monazite Vein", "ctnhcore.ore_vein.monazite_vein_nt": "Nether Monazite Vein", "ctnhcore.ore_vein.naquadah_vein_ad": "Venus Naquadah Vein", @@ -874,6 +879,7 @@ "ctnhcore.ore_vein.precious_alloy_vein_ow": "Overworld Precious Alloy Vein", "ctnhcore.ore_vein.pyrolusite_vein_ad": "Venus Pyrolusite Vein", "ctnhcore.ore_vein.quartzite_vein": "Quartzite Vein", + "ctnhcore.ore_vein.quartzite_vein_moon": "Moon Quartzite Vein", "ctnhcore.ore_vein.redstone_vein_ad": "Space Redstone Vein", "ctnhcore.ore_vein.redstone_vein_at": "Aether Redstone Vein", "ctnhcore.ore_vein.redstone_vein_nt": "Nether Redstone Vein", @@ -1078,13 +1084,17 @@ "gui.ctnh.neutron_sensor.invert.disabled": "Output: Normal\n\nSwitch to reverse redstone logic\nBy default, the sensor will emit a redstone signal when the neutron kinetic energy is between the set minimum and maximum values, and stop emitting a redstone signal when it is less than the minimum value.", "gui.ctnh.neutron_sensor.invert.enabled": "Output: Reverse\n\nSwitch to reverse redstone logic\nBy default, the sensor will emit a redstone signal when the neutron kinetic energy is between the set minimum and maximum values, and stop emitting a redstone signal when it is less than the minimum value.", "gui.ctnhcore.environment_detector.close": "Close", + "gui.ctnhcore.environment_detector.close_hint": "Esc to close", "gui.ctnhcore.environment_detector.conditions": "Environment conditions", "gui.ctnhcore.environment_detector.coordinates": "Position X %1$s · Y %2$s · Z %3$s", - "gui.ctnhcore.environment_detector.corrosion": "Corrosion rate", + "gui.ctnhcore.environment_detector.corrosion": "Corrosion", "gui.ctnhcore.environment_detector.hyperthermia": "Hyperthermia", "gui.ctnhcore.environment_detector.hypothermia": "Hypothermia", "gui.ctnhcore.environment_detector.no_thermal_data": "Unavailable", - "gui.ctnhcore.environment_detector.radiation": "Radiation dose rate", + "gui.ctnhcore.environment_detector.partial_pressure": "Pressure (atm)", + "gui.ctnhcore.environment_detector.radiation": "Radiation", + "gui.ctnhcore.environment_detector.refresh": "Updates every second", + "gui.ctnhcore.environment_detector.share": "Share", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": "Horizontal Range:", "gui.digital_miner.ctnhcore.digitalminer.max_height": "Max Height:", "gui.digital_miner.ctnhcore.digitalminer.min_height": "Min Height:", @@ -2009,13 +2019,12 @@ "material.ctnhcore.zr_hf_chloride": "Zr Hf Chloride", "material.ctnhcore.zr_hf_oxy_chloride": "Zr Hf Oxy Chloride", "material.ctnhcore.zr_hf_separation_mix": "Zr Hf Separation Mix", - "message.ctnhcore.thermometer.composition": "Atmospheric composition", - "message.ctnhcore.thermometer.gas": "Pressure %1$s · Share %2$s", - "message.ctnhcore.thermometer.header": "Environment readings", + "message.ctnhcore.thermometer.composition": "Atmosphere", + "message.ctnhcore.thermometer.header": "Environment Detector", "message.ctnhcore.thermometer.location": "Dimension %s", - "message.ctnhcore.thermometer.pressure": "Total pressure", - "message.ctnhcore.thermometer.temperature": "Ambient temperature", - "message.ctnhcore.thermometer.thermal_status": "Player thermal exposure", + "message.ctnhcore.thermometer.pressure": "Pressure", + "message.ctnhcore.thermometer.temperature": "Temperature", + "message.ctnhcore.thermometer.thermal_status": "Player status", "message.ctnhcore.thermometer.unlisted": "Unspecified gases", "message.ctnhcore.thermometer.vacuum": "Vacuum: no gases", "multiblock.ctnh.nuclear_reactor.consume_amount": "Coolant consumption rate: %s mB/s", diff --git a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json index 260fad09c..6475826e3 100644 --- a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json +++ b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json @@ -858,6 +858,7 @@ "ctnhcore.ore_vein.borax_vein_ed": "末地硼砂矿脉", "ctnhcore.ore_vein.calorite_vein_ad": "太空耐热金属矿脉", "ctnhcore.ore_vein.cassiterite_vein_ad": "太空锡石矿脉", + "ctnhcore.ore_vein.cassiterite_vein_moon": "月球锡石矿脉", "ctnhcore.ore_vein.cassiterite_vein_ow": "主世界锡石矿脉", "ctnhcore.ore_vein.certus_quartz_nt": "下界赛特斯石英", "ctnhcore.ore_vein.chromite_vein_ed": "末地铬铁矿脉", @@ -865,6 +866,7 @@ "ctnhcore.ore_vein.coal_vein_ow": "主世界煤炭矿脉", "ctnhcore.ore_vein.copper_tin_vein_ow": "主世界铜锡矿脉", "ctnhcore.ore_vein.copper_vein_ad": "太空铜矿脉", + "ctnhcore.ore_vein.copper_vein_moon": "月球铜矿脉", "ctnhcore.ore_vein.copper_vein_ow": "主世界铜矿脉", "ctnhcore.ore_vein.cryolite_vein_ed": "末地冰晶石矿脉", "ctnhcore.ore_vein.cryolite_vein_tf": "暮色森林冰晶石矿脉", @@ -877,6 +879,7 @@ "ctnhcore.ore_vein.emerald_vein_at": "天境绿宝石矿脉", "ctnhcore.ore_vein.europium_vein": "铕萤石矿脉", "ctnhcore.ore_vein.galena_vein_ad": "太空方铅矿脉", + "ctnhcore.ore_vein.galena_vein_moon": "月球方铅矿脉", "ctnhcore.ore_vein.galena_vein_tf": "暮色森林方铅矿脉", "ctnhcore.ore_vein.illusion_iron_vein_tf": "暮色森林幻铁矿脉", "ctnhcore.ore_vein.ilmenite_vein": "钛铁矿脉", @@ -897,7 +900,9 @@ "ctnhcore.ore_vein.manganese_vein_nt": "下界锰矿脉", "ctnhcore.ore_vein.manganese_vein_ow": "主世界锰矿脉", "ctnhcore.ore_vein.molybdenum_vein_ad": "太空辉钼矿脉", + "ctnhcore.ore_vein.molybdenum_vein_moon": "月球辉钼矿脉", "ctnhcore.ore_vein.molybdenum_vein_nt": "下界钼矿脉", + "ctnhcore.ore_vein.monazite_vein_moon": "月球独居石矿脉", "ctnhcore.ore_vein.monazite_vein_n": "月球独居石矿脉", "ctnhcore.ore_vein.monazite_vein_nt": "下界独居石矿脉", "ctnhcore.ore_vein.naquadah_vein_ad": "金星硅岩矿脉", @@ -920,6 +925,7 @@ "ctnhcore.ore_vein.precious_alloy_vein_ow": "主世界贵金属矿脉", "ctnhcore.ore_vein.pyrolusite_vein_ad": "金星软锰矿脉", "ctnhcore.ore_vein.quartzite_vein": "石英岩矿脉", + "ctnhcore.ore_vein.quartzite_vein_moon": "月球石英岩矿脉", "ctnhcore.ore_vein.redstone_vein_ad": "太空红石矿脉", "ctnhcore.ore_vein.redstone_vein_at": "天境红石矿脉", "ctnhcore.ore_vein.redstone_vein_nt": "下界红石矿脉", @@ -1149,13 +1155,17 @@ "gui.ctnh.neutron_sensor.invert.disabled": "输出:正常\n\n切换以反转红石逻辑\n默认情况下,中子动能介于所设定的最小值和最大值之间时传感器将发出红石信号,小于最小值时则停止发出红石信号", "gui.ctnh.neutron_sensor.invert.enabled": "输出:反转\n\n切换以反转红石逻辑\n默认情况下,中子动能介于所设定的最小值和最大值之间时传感器将发出红石信号,小于最小值时则停止发出红石信号", "gui.ctnhcore.environment_detector.close": "关闭", + "gui.ctnhcore.environment_detector.close_hint": "Esc 关闭", "gui.ctnhcore.environment_detector.conditions": "环境条件", "gui.ctnhcore.environment_detector.coordinates": "坐标 X %1$s · Y %2$s · Z %3$s", "gui.ctnhcore.environment_detector.corrosion": "腐蚀速率", "gui.ctnhcore.environment_detector.hyperthermia": "热射病累积", "gui.ctnhcore.environment_detector.hypothermia": "失温累积", "gui.ctnhcore.environment_detector.no_thermal_data": "暂无读数", + "gui.ctnhcore.environment_detector.partial_pressure": "分压 (atm)", "gui.ctnhcore.environment_detector.radiation": "辐射剂量率", + "gui.ctnhcore.environment_detector.refresh": "每秒刷新", + "gui.ctnhcore.environment_detector.share": "占比", "gui.digital_miner.ctnhcore.digitalminer.horizontal_range": "水平范围:", "gui.digital_miner.ctnhcore.digitalminer.max_height": "最大高度:", "gui.digital_miner.ctnhcore.digitalminer.min_height": "最小高度:", @@ -2078,12 +2088,11 @@ "material.ctnhcore.zr_hf_oxy_chloride": "锆-铪氯氧化物", "material.ctnhcore.zr_hf_separation_mix": "锆-铪混合物分离液", "message.ctnhcore.thermometer.composition": "大气成分", - "message.ctnhcore.thermometer.gas": "分压 %1$s · 占比 %2$s", - "message.ctnhcore.thermometer.header": "环境检测读数", + "message.ctnhcore.thermometer.header": "环境检测器", "message.ctnhcore.thermometer.location": "维度 %s", "message.ctnhcore.thermometer.pressure": "总气压", "message.ctnhcore.thermometer.temperature": "环境温度", - "message.ctnhcore.thermometer.thermal_status": "玩家冷热累积", + "message.ctnhcore.thermometer.thermal_status": "玩家状态", "message.ctnhcore.thermometer.unlisted": "未描述气体", "message.ctnhcore.thermometer.vacuum": "真空:无气体", "multiblock.ctnh.nuclear_reactor.consume_amount": "冷却液消耗率:%s mB/s", diff --git a/src/generated/resources/data/ctnhcore/tags/blocks/moon_ore_replaceables.json b/src/generated/resources/data/ctnhcore/tags/blocks/moon_ore_replaceables.json new file mode 100644 index 000000000..1c9dfff2a --- /dev/null +++ b/src/generated/resources/data/ctnhcore/tags/blocks/moon_ore_replaceables.json @@ -0,0 +1,10 @@ +{ + "values": [ + "ctnhastral:moon_stone", + "ctnhastral:moon_anorthosite", + "ctnhastral:moon_broken_anorthosite", + "ctnhastral:silicon_breccia", + "minecraft:basalt", + "minecraft:smooth_basalt" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/ad_astra_stones.json b/src/generated/resources/data/forge/tags/blocks/ad_astra_stones.json index 7ba941acb..9909a00ff 100644 --- a/src/generated/resources/data/forge/tags/blocks/ad_astra_stones.json +++ b/src/generated/resources/data/forge/tags/blocks/ad_astra_stones.json @@ -1,9 +1,5 @@ { "values": [ - { - "id": "ad_astra:moon_stone", - "required": false - }, { "id": "ad_astra:mars_stone", "required": false diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/gui/EnvironmentDetectorUI.java b/src/main/java/io/github/cpearl0/ctnhcore/common/gui/EnvironmentDetectorUI.java new file mode 100644 index 000000000..c0c1dfad0 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/gui/EnvironmentDetectorUI.java @@ -0,0 +1,487 @@ +package io.github.cpearl0.ctnhcore.common.gui; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.gui.GuiTextures; +import com.gregtechceu.gtceu.config.ConfigHolder; + +import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; +import com.lowdragmc.lowdraglib.gui.modular.ModularUI; +import com.lowdragmc.lowdraglib.gui.texture.ColorRectTexture; +import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; +import com.lowdragmc.lowdraglib.gui.widget.ComponentPanelWidget; +import com.lowdragmc.lowdraglib.gui.widget.DraggableScrollableWidgetGroup; +import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; +import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; +import com.lowdragmc.lowdraglib.gui.widget.Widget; +import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; + +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.locale.Language; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.FormattedText; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import com.ctnh.ctnhastral.common.environment.Atmosphere; +import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; +import com.ctnh.ctnhastral.data.CAMedicalConditions; +import com.ctnh.ctnhastral.registry.CAEnvironments; +import com.ctnhlang.CN; +import com.ctnhlang.EN; +import com.ctnhlang.Key; +import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.TreeMap; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** 环境检测器的布局、读数格式与同步;环境和医疗状态均读取既有服务。 */ +public final class EnvironmentDetectorUI { + + private static final int TEXT_COLOR = 0xE8E8E8; + private static final int MUTED_COLOR = 0xC5C5C5; + private static final int FRAME_TEXT_COLOR = 0x404040; + // 颜色区分读数类别,不代表玩家防护后的危险等级。 + private static final int TEMPERATURE_COLOR = 0xFFC66D; + private static final int PRESSURE_COLOR = 0x6DD5ED; + private static final int RADIATION_COLOR = 0xC8A2FF; + private static final int CORROSION_COLOR = 0xA9D879; + private static final int COLD_COLOR = 0x77BFFF; + private static final int HEAT_COLOR = 0xFF997D; + + @Key("gui.ctnhcore.environment_detector.close") + @CN("关闭") + @EN("Close") + private static Lang close; + + @Key("message.ctnhcore.thermometer.header") + @CN("环境检测器") + @EN("Environment Detector") + private static Lang header; + + @Key("message.ctnhcore.thermometer.location") + @CN("维度 %s") + @EN("Dimension %s") + private static Lang location; + + @Key("gui.ctnhcore.environment_detector.coordinates") + @CN("坐标 X %1$s · Y %2$s · Z %3$s") + @EN("Position X %1$s · Y %2$s · Z %3$s") + private static Lang coordinates; + + @Key("gui.ctnhcore.environment_detector.conditions") + @CN("环境条件") + @EN("Environment conditions") + private static Lang environmentConditions; + + @Key("message.ctnhcore.thermometer.temperature") + @CN("环境温度") + @EN("Temperature") + private static Lang temperature; + + @Key("message.ctnhcore.thermometer.thermal_status") + @CN("玩家状态") + @EN("Player status") + private static Lang thermalStatus; + + @Key("gui.ctnhcore.environment_detector.hypothermia") + @CN("失温累积") + @EN("Hypothermia") + private static Lang hypothermia; + + @Key("gui.ctnhcore.environment_detector.hyperthermia") + @CN("热射病累积") + @EN("Hyperthermia") + private static Lang hyperthermia; + + @Key("gui.ctnhcore.environment_detector.no_thermal_data") + @CN("暂无读数") + @EN("Unavailable") + private static Lang noThermalData; + + @Key("message.ctnhcore.thermometer.pressure") + @CN("总气压") + @EN("Pressure") + private static Lang totalPressure; + + @Key("gui.ctnhcore.environment_detector.radiation") + @CN("辐射剂量率") + @EN("Radiation") + private static Lang radiation; + + @Key("gui.ctnhcore.environment_detector.corrosion") + @CN("腐蚀速率") + @EN("Corrosion") + private static Lang corrosion; + + @Key("message.ctnhcore.thermometer.vacuum") + @CN("真空:无气体") + @EN("Vacuum: no gases") + private static Lang vacuum; + + @Key("message.ctnhcore.thermometer.composition") + @CN("大气成分") + @EN("Atmosphere") + private static Lang composition; + + @Key("gui.ctnhcore.environment_detector.partial_pressure") + @CN("分压 (atm)") + @EN("Pressure (atm)") + private static Lang partialPressure; + + @Key("gui.ctnhcore.environment_detector.share") + @CN("占比") + @EN("Share") + private static Lang share; + + @Key("gui.ctnhcore.environment_detector.refresh") + @CN("每秒刷新") + @EN("Updates every second") + private static Lang refresh; + + @Key("gui.ctnhcore.environment_detector.close_hint") + @CN("Esc 关闭") + @EN("Esc to close") + private static Lang closeHint; + + @Key("message.ctnhcore.thermometer.unlisted") + @CN("未描述气体") + @EN("Unspecified gases") + private static Lang unlisted; + + public static ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { + var data = new PanelReadings(); + updateReadings(player, data); + var content = new WidgetGroup(0, 0, 300, 232) { + + @Override + public void detectAndSendChanges() { + if (gui.getTickCount() % 20 == 0) { + updateReadings(player, data); + super.detectAndSendChanges(); + } + } + }; + content.addWidget(new EnvironmentReadingsWidget(12, 10, 252, 9, Layout.TEXT, + text -> text.add(frameText(header)))); + content.addWidget(inset(10, 29, 280, 28)); + content.addWidget(new EnvironmentReadingsWidget(18, 32, 264, 12, Layout.TEXT, + text -> text.addAll(data.location))); + content.addWidget(section(63, environmentConditions)); + content.addWidget(inset(10, 76, 280, 38)); + content.addWidget(rect(149, 78, 1, 34, 0xFF505050)); + content.addWidget(rect(12, 94, 276, 1, 0xFF414141)); + content.addWidget(reading(18, 80, temperature, () -> data.temperature)); + content.addWidget(reading(158, 80, totalPressure, () -> data.pressure)); + content.addWidget(reading(18, 99, radiation, () -> data.radiation)); + content.addWidget(reading(158, 99, corrosion, () -> data.corrosion)); + content.addWidget(section(120, thermalStatus)); + content.addWidget(inset(10, 132, 280, 26)); + content.addWidget(rect(149, 134, 1, 22, 0xFF505050)); + content.addWidget(reading(18, 134, hypothermia, () -> data.coldValue)); + content.addWidget(reading(158, 134, hyperthermia, () -> data.heatValue)); + content.addWidget(rect(18, 149, 124, 5, 0xFF090909)); + content.addWidget(rect(158, 149, 124, 5, 0xFF090909)); + content.addWidget(new ProgressWidget(() -> Math.min(1.0, data.coldProgress), 19, 150, 122, 3) + .setProgressTexture(new ColorRectTexture(0xFF464646), new ColorRectTexture(0xFF000000 | COLD_COLOR))); + content.addWidget(new ProgressWidget(() -> Math.min(1.0, data.heatProgress), 159, 150, 122, 3) + .setProgressTexture(new ColorRectTexture(0xFF464646), new ColorRectTexture(0xFF000000 | HEAT_COLOR))); + content.addWidget(new EnvironmentReadingsWidget(18, 164, 260, 9, Layout.GAS_HEADER, + text -> text.addAll(List.of(frameText(composition), frameText(partialPressure), frameText(share))))); + content.addWidget(inset(10, 176, 280, 34)); + // 上下各留 1 像素;两行内容不顶满滚动区,缩回两行时也能正确重算范围。 + var gases = new EnvironmentReadingsWidget(8, 1, 260, 16, Layout.GASES, + text -> text.addAll(data.gases)); + var scroll = new DraggableScrollableWidgetGroup(10, 176, 280, 34) { + + @Override + public void computeMax() { + int previousOffset = getScrollYOffset(); + super.computeMax(); + // LDLib 默认随内容高度变化调整位置;读数刷新只收紧边界,不跳到列表末尾。 + setScrollYOffset(Math.min(previousOffset, Math.max(0, getMaxHeight() - getSizeHeight()))); + } + + @Override + public Widget getHoverElement(double mouseX, double mouseY) { + return isMouseOverElement(mouseX, mouseY) ? super.getHoverElement(mouseX, mouseY) : null; + } + }.setYScrollBarWidth(4) + .setYBarStyle(null, GuiTextures.BUTTON) + .setDraggable(false); + scroll.addWidget(gases); + content.addWidget(scroll); + content.addWidget(new EnvironmentReadingsWidget(12, 218, 276, 9, Layout.PAIR, + text -> text.addAll(List.of(frameText(refresh), frameText(closeHint))))); + + return new ModularUI(300, 232, holder, player) + .background(GuiTextures.BACKGROUND) + .widget(content) + .widget(new ButtonWidget(274, 6, 18, 18, click -> { + if (player instanceof ServerPlayer serverPlayer) { + serverPlayer.closeContainer(); + } + }).setButtonTexture(GuiTextures.BUTTON, GuiTextures.CLOSE_ICON) + .setHoverBorderTexture(1, 0xFFFFFFFF) + .setClickedTexture(GuiTextures.BACKGROUND_INVERSE, GuiTextures.CLOSE_ICON) + .setHoverTooltips(close.translate())); + } + + private static Component frameText(Lang text) { + return text.translate().withStyle(style -> style.withColor(FRAME_TEXT_COLOR)); + } + + private static EnvironmentReadingsWidget section(int y, Lang title) { + return new EnvironmentReadingsWidget(12, y, 276, 9, Layout.SECTION, text -> text.add(frameText(title))); + } + + private static EnvironmentReadingsWidget reading(int x, int y, Lang title, Supplier value) { + return new EnvironmentReadingsWidget(x, y, 124, 13, Layout.PAIR, + text -> text.addAll( + List.of(title.translate().withStyle(style -> style.withColor(TEXT_COLOR)), value.get()))); + } + + private static ImageWidget rect(int x, int y, int width, int height, int color) { + return new ImageWidget(x, y, width, height, new ColorRectTexture(color)); + } + + private static WidgetGroup inset(int x, int y, int width, int height) { + return new WidgetGroup(x, y, width, height) + .addWidget(rect(0, 0, width, height, 0xFFF0F0F0)) + .addWidget(rect(0, 0, width - 1, height - 1, 0xFF555555)) + .addWidget(rect(1, 1, width - 2, height - 2, 0xFF242424)); + } + + private static void updateReadings(Player player, PanelReadings data) { + // 客户端只展示同步后的文本,不自行计算环境或读取服务端医疗状态。 + if (!(player.level() instanceof ServerLevel level)) return; + var pos = player.blockPosition(); + var environment = PlanetEnvironmentService.getEnvironment(level, pos); + Atmosphere atmosphere = environment.get(CAEnvironments.ATMOSPHERE); + data.location = List.of( + location.translate(value(level.dimension().location().toString(), TEXT_COLOR)) + .withStyle(style -> style.withColor(MUTED_COLOR)), + coordinates.translate(value(Integer.toString(pos.getX()), TEXT_COLOR), + value(Integer.toString(pos.getY()), TEXT_COLOR), + value(Integer.toString(pos.getZ()), TEXT_COLOR)) + .withStyle(style -> style.withColor(MUTED_COLOR))); + data.temperature = quantity(decimal(environment.get(CAEnvironments.TEMPERATURE).celsius()), + "°C", TEMPERATURE_COLOR); + data.pressure = quantity(number(atmosphere.pressure()), "atm", PRESSURE_COLOR); + data.radiation = quantity(number(environment.get(CAEnvironments.RADIATION).rate()), "rad/s", RADIATION_COLOR); + data.corrosion = quantity(number(environment.get(CAEnvironments.CORROSION).rate()), "mm/a", CORROSION_COLOR); + + data.coldProgress = 0.0; + data.heatProgress = 0.0; + data.coldValue = noThermalData.translate().withStyle(style -> style.withColor(MUTED_COLOR)); + data.heatValue = data.coldValue; + var tracker = GTCapabilityHelper.getMedicalConditionTracker(player); + if (tracker != null && ConfigHolder.INSTANCE.gameplay.hazardsEnabled) { + var conditions = tracker.getMedicalConditions(); + data.coldProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPOTHERMIA)) / + CAMedicalConditions.HYPOTHERMIA.maxProgression; + data.heatProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPERTHERMIA)) / + CAMedicalConditions.HYPERTHERMIA.maxProgression; + data.coldValue = quantity(decimal(data.coldProgress * 100.0), "%", COLD_COLOR); + data.heatValue = quantity(decimal(data.heatProgress * 100.0), "%", HEAT_COLOR); + } + + data.gases = new ArrayList<>(); + float pressure = atmosphere.pressure(); + if (pressure == 0.0F) { + data.gases.add(vacuum.translate().withStyle(ChatFormatting.GOLD)); + data.gases.add(Component.empty()); + data.gases.add(Component.empty()); + } else { + new TreeMap<>(atmosphere.partialPressures()).forEach((gas, partialPressure) -> { + Component name = Component.translatableWithFallback( + "gas." + gas.getNamespace() + "." + gas.getPath().replace('/', '.'), gas.toString()); + gasReadings(data.gases, name, partialPressure, 100.0 * partialPressure / pressure); + }); + double described = atmosphere.partialPressures().values().stream().mapToDouble(Float::doubleValue).sum(); + double remainder = pressure - described; + // 忽略浮点归一化的一位舍入误差,不把已描述完整的成分报为额外背景。 + if (remainder > Math.ulp(pressure)) { + gasReadings(data.gases, unlisted.translate(), remainder, 100.0 * remainder / pressure); + } + } + } + + private static void gasReadings(List text, Component name, double partialPressure, double share) { + text.add(name.copy().withStyle(style -> style.withColor(TEXT_COLOR))); + text.add(value(number(partialPressure), PRESSURE_COLOR)); + text.add(value(String.format(Locale.ROOT, "%.1f%%", share), TEMPERATURE_COLOR)); + } + + private static MutableComponent value(String value, int color) { + return Component.literal(value).withStyle(style -> style.withColor(color)); + } + + private static Component quantity(String value, String unit, int color) { + return value(value, color) + .append(Component.literal(" " + unit).withStyle(style -> style.withColor(MUTED_COLOR).withBold(false))); + } + + private static String number(double value) { + return String.format(Locale.ROOT, "%.4g", value); + } + + private static String decimal(double value) { + return Math.abs(value) < 100000.0 ? String.format(Locale.ROOT, "%.1f", value) : number(value); + } + + /** 每个打开的面板各自持有显示值;所有读数在同一次服务端采样中更新。 */ + private static final class PanelReadings { + + private List location = List.of(); + private Component temperature = Component.empty(); + private Component pressure = Component.empty(); + private Component radiation = Component.empty(); + private Component corrosion = Component.empty(); + private Component coldValue = Component.empty(); + private Component heatValue = Component.empty(); + private double coldProgress; + private double heatProgress; + private List gases = List.of(); + } + + private enum Layout { + + TEXT(1), + PAIR(2), + GAS_HEADER(3), + GASES(3), + SECTION(1); + + private final int columns; + + Layout(int columns) { + this.columns = columns; + } + } + + /** 固定行高的只读表格,复用 ComponentPanelWidget 的服务端文本同步。 */ + private static final class EnvironmentReadingsWidget extends ComponentPanelWidget { + + private final int tableWidth; + private final int rowHeight; + private final Layout layout; + private final Set clippedRows = new HashSet<>(); + + private EnvironmentReadingsWidget(int x, int y, int width, int rowHeight, Layout layout, + Consumer> textSupplier) { + super(x, y, textSupplier); + this.tableWidth = width; + this.rowHeight = rowHeight; + this.layout = layout; + updateComponentTextSize(); + } + + @Override + public void formatDisplayText() { + // 单元格在绘制时按 Font 度量,不能让父类的自动换行改变固定布局。 + } + + @Override + public void updateComponentTextSize() { + setSize(tableWidth, Math.max(1, (lastText.size() + layout.columns - 1) / layout.columns) * rowHeight); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void drawInBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + clippedRows.clear(); + Font font = Minecraft.getInstance().font; + int x = getPositionX(); + for (int index = 0; index < lastText.size(); index += layout.columns) { + int row = index / layout.columns; + int top = getPositionY() + row * rowHeight; + int y = top + Math.max(0, (rowHeight - font.lineHeight + 1) / 2); + Component label = lastText.get(index); + boolean gasColumns = (layout == Layout.GASES || layout == Layout.GAS_HEADER) && + index + 2 < lastText.size() && !lastText.get(index + 1).getString().isEmpty(); + boolean clipped; + if (layout == Layout.PAIR && index + 1 < lastText.size()) { + Component value = lastText.get(index + 1); + int valueWidth = Math.min(tableWidth - 32, font.width(value)); + clipped = drawCell(graphics, label, x, y, tableWidth - valueWidth - 8, false); + clipped |= drawCell(graphics, value, x + tableWidth - valueWidth, y, valueWidth, true); + } else if (gasColumns) { + // 名称、分压、占比列:表头与数据使用同一组右边界。 + clipped = drawCell(graphics, label, x, y, tableWidth - 148, false); + clipped |= drawCell(graphics, lastText.get(index + 1), x + tableWidth - 140, y, 80, true); + clipped |= drawCell(graphics, lastText.get(index + 2), x + tableWidth - 52, y, 52, true); + } else { + clipped = drawCell(graphics, label, x, y, tableWidth, false); + } + if (clipped) clippedRows.add(row); + if (layout == Layout.SECTION) { + int start = x + Math.min(tableWidth, font.width(label) + 8); + graphics.fill(start, y + 4, x + tableWidth, y + 5, 0xFF8B8B8B); + graphics.fill(start, y + 5, x + tableWidth, y + 6, 0xFFEDEDED); + } else if (layout == Layout.GASES && row > 0) { + graphics.fill(x, top - 2, x + tableWidth, top - 1, 0xFF414141); + } + } + } + + @OnlyIn(Dist.CLIENT) + private static boolean drawCell(GuiGraphics graphics, Component text, int x, int y, int width, boolean right) { + Font font = Minecraft.getInstance().font; + boolean clipped = font.width(text) > width; + FormattedText shown = text; + if (clipped) { + Component ellipsis = Component.literal("…").withStyle(text.getStyle()); + shown = FormattedText.composite(font.substrByWidth(text, Math.max(0, width - font.width(ellipsis))), + ellipsis); + } + graphics.drawString(font, Language.getInstance().getVisualOrder(shown), + right ? x + width - font.width(shown) : x, y, 0xFFE8E8E8, false); + return clipped; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void drawInForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + if (!isMouseOverElement(mouseX, mouseY)) return; + int row = (mouseY - getPositionY()) / rowHeight; + int index = row * layout.columns; + if (index >= lastText.size() || !clippedRows.contains(row)) return; + List tooltip = new ArrayList<>(); + tooltip.add(lastText.get(index)); + if ((layout == Layout.GASES || layout == Layout.GAS_HEADER) && index + 2 < lastText.size()) { + Component pressure = lastText.get(index + 1); + if (!pressure.getString().isEmpty()) { + tooltip.add(layout == Layout.GASES ? pressure.copy().append(" atm") : pressure); + } + if (!lastText.get(index + 2).getString().isEmpty()) { + tooltip.add(lastText.get(index + 2)); + } + } else if (layout == Layout.PAIR && index + 1 < lastText.size()) { + tooltip.add(lastText.get(index + 1)); + } + setHoverTooltips(tooltip); + // 由 ModularUI 最后统一画 tooltip,避免被气体列表的裁切区域截掉。 + drawTooltipTexts(mouseX, mouseY); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + return false; + } + } + + private EnvironmentDetectorUI() {} +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/item/AstronomyCircuitItem.java b/src/main/java/io/github/cpearl0/ctnhcore/common/item/AstronomyCircuitItem.java index 55e005bf4..926195345 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/item/AstronomyCircuitItem.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/item/AstronomyCircuitItem.java @@ -16,7 +16,7 @@ public class AstronomyCircuitItem extends Item { public static final ResourceLocation[][] DIMENSIONS = new ResourceLocation[][] { { CTNHWorlds.THE_AETHER }, - { CTNHWorlds.THE_AETHER, ResourceLocation.tryParse("ad_astra:moon") }, + { CTNHWorlds.THE_AETHER, CTNHWorlds.MOON }, }; private final int tier; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/SpacePhotovoltaicBaseStation.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/SpacePhotovoltaicBaseStation.java index 6b65fb0a0..9ed45c60c 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/SpacePhotovoltaicBaseStation.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/electric/SpacePhotovoltaicBaseStation.java @@ -3,6 +3,7 @@ import io.github.cpearl0.ctnhcore.common.block.blockdata.IPBData; import io.github.cpearl0.ctnhcore.common.machine.multiblock.generator.PhotoVoltaicDroneStation; import io.github.cpearl0.ctnhcore.registry.CTNHRecipeTypes; +import io.github.cpearl0.ctnhcore.registry.CTNHWorlds; import com.gregtechceu.gtceu.api.machine.IMachineBlockEntity; import com.gregtechceu.gtceu.api.machine.MetaMachine; @@ -117,7 +118,7 @@ public double dimension_check() { rate *= 0.5; } else if (dimension == AetherDimensions.AETHER_LEVEL) { rate *= 1; - } else if (dimension == Planet.MOON || dimension == Planet.MOON_ORBIT) { + } else if (dimension.location().equals(CTNHWorlds.MOON) || dimension == Planet.MOON_ORBIT) { rate *= 2; } else if (dimension == Planet.VENUS || dimension == Planet.VENUS_ORBIT) { rate *= 4; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotoVoltaicDroneStation.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotoVoltaicDroneStation.java index eb702b39d..b4c516349 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotoVoltaicDroneStation.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotoVoltaicDroneStation.java @@ -2,6 +2,7 @@ import io.github.cpearl0.ctnhcore.common.item.IDroneItem; import io.github.cpearl0.ctnhcore.common.machine.multiblock.part.DroneHolderMachine; +import io.github.cpearl0.ctnhcore.registry.CTNHWorlds; import com.gregtechceu.gtceu.api.capability.IParallelHatch; import com.gregtechceu.gtceu.api.capability.recipe.ItemRecipeCapability; @@ -130,7 +131,7 @@ public double dimension_check() { rate *= 0.5; } else if (dimension == AetherDimensions.AETHER_LEVEL) { rate *= 1; - } else if (dimension == Planet.MOON || dimension == Planet.MOON_ORBIT) { + } else if (dimension.location().equals(CTNHWorlds.MOON) || dimension == Planet.MOON_ORBIT) { rate *= 2; } else if (dimension == Planet.VENUS || dimension == Planet.VENUS_ORBIT) { rate *= 4; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotovoltaicPowerStationMachine.java b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotovoltaicPowerStationMachine.java index 94a71a16c..5f45f414c 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotovoltaicPowerStationMachine.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/common/machine/multiblock/generator/PhotovoltaicPowerStationMachine.java @@ -1,5 +1,7 @@ package io.github.cpearl0.ctnhcore.common.machine.multiblock.generator; +import io.github.cpearl0.ctnhcore.registry.CTNHWorlds; + import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.capability.IEnergyContainer; import com.gregtechceu.gtceu.api.capability.IWorkable; @@ -146,7 +148,7 @@ public void onStructureFormed() { rate_mul = 1; } else if (dimension == AetherDimensions.AETHER_LEVEL) { rate_mul = 2; - } else if (dimension == Planet.MOON || dimension == Planet.MOON_ORBIT) { + } else if (dimension.location().equals(CTNHWorlds.MOON) || dimension == Planet.MOON_ORBIT) { rate_mul = 3; } else if (dimension == Planet.VENUS || dimension == Planet.VENUS_ORBIT) { rate_mul = 3; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/AdAstraRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/AdAstraRecipes.java index 47fbd251c..4aaa80d1c 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/AdAstraRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/AdAstraRecipes.java @@ -18,6 +18,7 @@ import net.minecraft.world.item.Items; import net.minecraftforge.registries.ForgeRegistries; +import com.ctnh.ctnhastral.registry.worldgen.MoonBlocks; import earth.terrarium.adastra.common.registry.ModItems; import java.util.function.Consumer; @@ -269,37 +270,36 @@ public static void init(Consumer provider) { private static void stoneRelatedRecipes(Consumer provider) { output = provider; - smelt(ModItems.MOON_STONE, ModItems.MOON_COBBLESTONE); smelt(ModItems.MARS_STONE, ModItems.MARS_COBBLESTONE); smelt(ModItems.VENUS_STONE, ModItems.VENUS_COBBLESTONE); smelt(ModItems.MERCURY_STONE, ModItems.MERCURY_COBBLESTONE); smelt(ModItems.GLACIO_STONE, ModItems.GLACIO_COBBLESTONE); - shaped(ModItems.MOON_STONE_STAIRS, 4, ModItems.MOON_STONE, "# ", "## ", "###"); + shaped(ModItems.MOON_STONE_STAIRS, 4, MoonBlocks.MOON_STONE::asItem, "# ", "## ", "###"); shaped(ModItems.MARS_STONE_STAIRS, 4, ModItems.MARS_STONE, "# ", "## ", "###"); shaped(ModItems.VENUS_STONE_STAIRS, 4, ModItems.VENUS_STONE, "# ", "## ", "###"); shaped(ModItems.MERCURY_STONE_STAIRS, 4, ModItems.MERCURY_STONE, "# ", "## ", "###"); shaped(ModItems.GLACIO_STONE_STAIRS, 4, ModItems.GLACIO_STONE, "# ", "## ", "###"); - shaped(ModItems.MOON_STONE_SLAB, 6, ModItems.MOON_STONE, "###"); + shaped(ModItems.MOON_STONE_SLAB, 6, MoonBlocks.MOON_STONE::asItem, "###"); shaped(ModItems.MARS_STONE_SLAB, 6, ModItems.MARS_STONE, "###"); shaped(ModItems.VENUS_STONE_SLAB, 6, ModItems.VENUS_STONE, "###"); shaped(ModItems.MERCURY_STONE_SLAB, 6, ModItems.MERCURY_STONE, "###"); shaped(ModItems.GLACIO_STONE_SLAB, 6, ModItems.GLACIO_STONE, "###"); - shaped(ModItems.MOON_COBBLESTONE_STAIRS, 4, ModItems.MOON_COBBLESTONE, "# ", "## ", "###"); + shaped(ModItems.MOON_COBBLESTONE_STAIRS, 4, MoonBlocks.MOON_COBBLESTONE::asItem, "# ", "## ", "###"); shaped(ModItems.MARS_COBBLESTONE_STAIRS, 4, ModItems.MARS_COBBLESTONE, "# ", "## ", "###"); shaped(ModItems.VENUS_COBBLESTONE_STAIRS, 4, ModItems.VENUS_COBBLESTONE, "# ", "## ", "###"); shaped(ModItems.MERCURY_COBBLESTONE_STAIRS, 4, ModItems.MERCURY_COBBLESTONE, "# ", "## ", "###"); shaped(ModItems.GLACIO_COBBLESTONE_STAIRS, 4, ModItems.GLACIO_COBBLESTONE, "# ", "## ", "###"); - shaped(ModItems.MOON_COBBLESTONE_SLAB, 6, ModItems.MOON_COBBLESTONE, "###"); + shaped(ModItems.MOON_COBBLESTONE_SLAB, 6, MoonBlocks.MOON_COBBLESTONE::asItem, "###"); shaped(ModItems.MARS_COBBLESTONE_SLAB, 6, ModItems.MARS_COBBLESTONE, "###"); shaped(ModItems.VENUS_COBBLESTONE_SLAB, 6, ModItems.VENUS_COBBLESTONE, "###"); shaped(ModItems.MERCURY_COBBLESTONE_SLAB, 6, ModItems.MERCURY_COBBLESTONE, "###"); shaped(ModItems.GLACIO_COBBLESTONE_SLAB, 6, ModItems.GLACIO_COBBLESTONE, "###"); - shaped(ModItems.MOON_STONE_BRICKS, 4, ModItems.MOON_STONE, "##", "##"); + shaped(ModItems.MOON_STONE_BRICKS, 4, MoonBlocks.MOON_STONE::asItem, "##", "##"); shaped(ModItems.MARS_STONE_BRICKS, 4, ModItems.MARS_STONE, "##", "##"); shaped(ModItems.VENUS_STONE_BRICKS, 4, ModItems.VENUS_STONE, "##", "##"); shaped(ModItems.MERCURY_STONE_BRICKS, 4, ModItems.MERCURY_STONE, "##", "##"); @@ -341,7 +341,7 @@ private static void stoneRelatedRecipes(Consumer provider) { shaped(ModItems.CHISELED_MERCURY_STONE_SLAB, 6, ModItems.CHISELED_MERCURY_STONE_BRICKS, "###"); shaped(ModItems.CHISELED_GLACIO_STONE_SLAB, 6, ModItems.CHISELED_GLACIO_STONE_BRICKS, "###"); - shaped(ModItems.POLISHED_MOON_STONE, 4, ModItems.MOON_COBBLESTONE, "##", "##"); + shaped(ModItems.POLISHED_MOON_STONE, 4, MoonBlocks.MOON_COBBLESTONE::asItem, "##", "##"); shaped(ModItems.POLISHED_MARS_STONE, 4, ModItems.MARS_COBBLESTONE, "##", "##"); shaped(ModItems.POLISHED_VENUS_STONE, 4, ModItems.VENUS_COBBLESTONE, "##", "##"); shaped(ModItems.POLISHED_MERCURY_STONE, 4, ModItems.MERCURY_COBBLESTONE, "##", "##"); @@ -359,7 +359,7 @@ private static void stoneRelatedRecipes(Consumer provider) { shaped(ModItems.POLISHED_MERCURY_STONE_SLAB, 6, ModItems.POLISHED_MERCURY_STONE, "###"); shaped(ModItems.POLISHED_GLACIO_STONE_SLAB, 6, ModItems.POLISHED_GLACIO_STONE, "###"); - shaped(ModItems.MOON_PILLAR, 2, ModItems.MOON_STONE, "#", "#"); + shaped(ModItems.MOON_PILLAR, 2, MoonBlocks.MOON_STONE::asItem, "#", "#"); shaped(ModItems.MARS_PILLAR, 2, ModItems.MARS_STONE, "#", "#"); shaped(ModItems.VENUS_PILLAR, 2, ModItems.VENUS_STONE, "#", "#"); shaped(ModItems.MERCURY_PILLAR, 2, ModItems.MERCURY_STONE, "#", "#"); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java index de6f01a95..c59774ea2 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java @@ -34,6 +34,7 @@ public static void init(Consumer provider) { GtceuAssemblerRecipeFixes.init(provider); OreProcessingRecipes.init(provider); + MoonMaterialRecipes.init(provider); UnderfloorHeatingSystemRecipes.init(provider); AstronomicalObservatoryRecipes.init(provider); PersonalComputerRecipes.init(provider); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java new file mode 100644 index 000000000..1cc9cfd45 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java @@ -0,0 +1,80 @@ +package io.github.cpearl0.ctnhcore.data.recipe; + +import com.gregtechceu.gtceu.api.data.chemical.material.ItemMaterialData; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.ItemMaterialInfo; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; +import com.gregtechceu.gtceu.data.recipe.StoneTypeEntry; +import com.gregtechceu.gtceu.data.recipe.misc.StoneMachineRecipes; + +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.world.level.ItemLike; + +import earth.terrarium.adastra.common.registry.ModItems; + +import java.util.List; +import java.util.function.Consumer; + +import static com.ctnh.ctnhastral.data.CAMaterials.Moonstone; +import static com.ctnh.ctnhastral.registry.worldgen.MoonBlocks.*; +import static com.gregtechceu.gtceu.api.GTValues.M; +import static com.gregtechceu.gtceu.common.data.GTMaterials.*; + +/** Bind existing lunar blocks to GT's stone families and material recycling, without per-block recipes. */ +public class MoonMaterialRecipes { + + public static void init(Consumer provider) { + // The addon hook runs before GT's RecyclingRecipes.init, on every recipe reload. + // Keep the declarations here so the generic generators see the current material data. + for (var entry : List.of( + new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_stone") + .stone(MOON_STONE.asItem()).crackedStone(MOON_COBBLESTONE.asItem()) + .polishedStone(ModItems.MOON_STONE_BRICKS.get()) + .slab(ModItems.MOON_STONE_SLAB.get()).stair(ModItems.MOON_STONE_STAIRS.get()) + .chiselStone(ModItems.MOON_PILLAR.get()) + .material(Moonstone).registerAllMaterialInfo().build(), + new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_cobblestone") + .stone(MOON_COBBLESTONE.asItem()).smeltStone(MOON_STONE.asItem()) + .polishedStone(ModItems.POLISHED_MOON_STONE.get()) + .slab(ModItems.MOON_COBBLESTONE_SLAB.get()).stair(ModItems.MOON_COBBLESTONE_STAIRS.get()) + .material(Moonstone).registerAllMaterialInfo().build(), + new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_anorthosite") + .stone(MOON_ANORTHOSITE.asItem()).crackedStone(MOON_BROKEN_ANORTHOSITE.asItem()) + .material(Stone).registerAllMaterialInfo().build(), + new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_broken_anorthosite") + .stone(MOON_BROKEN_ANORTHOSITE.asItem()).smeltStone(MOON_ANORTHOSITE.asItem()) + .material(Stone).registerAllMaterialInfo().build(), + new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_silicon_crust") + .stone(SILICON_CRUST.asItem()).crackedStone(SILICON_GRAVEL.asItem()) + .material(SiliconDioxide).registerAllMaterialInfo().build())) { + StoneMachineRecipes.registerStoneMaterialInfo(entry); + StoneMachineRecipes.registerStoneTypeRecipes(provider, entry); + } + + material(MOON_SAND, Moonstone, M); + material(SILICON_BRECCIA, Stone, M); + for (var block : List.of(MOONLIGHT_SAND, SILICON_GRAVEL, SILICON_CRYSTAL)) { + material(block, SiliconDioxide, M); + } + material(IRIDESCENT_SILICON_CRYSTAL, SiliconDioxide, 2 * M); + material(SILICON_CRYSTAL_BLOCK, SiliconDioxide, 4 * M); + material(BUDDING_SILICON_CRYSTAL, SiliconDioxide, 4 * M); + material(SMALL_SILICON_CRYSTAL_BUD, SiliconDioxide, M / 9); + material(MEDIUM_SILICON_CRYSTAL_BUD, SiliconDioxide, 2 * M / 9); + material(LARGE_SILICON_CRYSTAL_BUD, SiliconDioxide, 4 * M / 9); + + ItemMaterialData.registerMaterialInfo(LUMINOUS_MOON_SAND, new ItemMaterialInfo( + new MaterialStack(SiliconDioxide, M), new MaterialStack(Glowstone, M))); + ItemMaterialData.registerMaterialInfo(MOONLIGHT_CRYSTAL, new ItemMaterialInfo( + new MaterialStack(SiliconDioxide, 4 * M), new MaterialStack(Glowstone, 4 * M))); + + // Use the same Ice material as vanilla ice. Its dust already has GT extraction/heating recipes. + material(MOON_DENSE_ICE, Ice, M); + ItemMaterialData.registerMaterialInfo(MOON_DUSTY_ICE, new ItemMaterialInfo( + new MaterialStack(Ice, M / 2), new MaterialStack(Moonstone, M / 2))); + } + + private static void material(ItemLike item, Material material, long amount) { + ItemMaterialData.registerMaterialInfo(item, new ItemMaterialInfo(new MaterialStack(material, amount))); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/NanoRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/NanoRecipes.java index d334becdc..a165f07d9 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/NanoRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/NanoRecipes.java @@ -14,6 +14,7 @@ import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.world.item.Items; +import com.ctnh.ctnhastral.registry.worldgen.MoonBlocks; import com.mo_guang.ctpp.registry.CTPPBlocks; import earth.terrarium.adastra.common.registry.ModBlocks; @@ -23,7 +24,7 @@ public class NanoRecipes { - // ad_astra planet stone blocks: ModBlocks (RegistryEntry, use .get().asItem()) + // Moon stone belongs to Astral; other planet stone blocks still come from Ad Astra. // gtceu stone dust materials: CAMaterials (CTNH-Astral module) public static void init(Consumer provider) { @@ -52,7 +53,7 @@ public static void init(Consumer provider) { // Nano generator: moon_cobblestone -> moon_stone_dust CTNHRecipeTypes.NANO_GENERATOR.recipeBuilder(CTNHCore.id("moon_cobblestone")) - .inputItems(ModBlocks.MOON_COBBLESTONE.get().asItem()) + .inputItems(MoonBlocks.MOON_COBBLESTONE.asItem()) .outputItems(ChemicalHelper.get(TagPrefix.dust, Moonstone), 3) .EUt(-6) .duration(10) diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java index ff6108e4b..7c3cdf3b0 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java @@ -56,6 +56,7 @@ import java.util.function.Consumer; import static com.ctnh.ctnhastral.data.CAMaterials.*; +import static com.ctnh.ctnhastral.registry.worldgen.MoonBlocks.MOON_STONE; import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*; import static com.gregtechceu.gtceu.common.data.GTMaterials.*; import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*; @@ -1924,7 +1925,7 @@ public static void init(Consumer provider) { // ore_production_3 CTNHRecipeTypes.MARTIAL_MORALITY_EYE.recipeBuilder(CTNHCore.id("ore_production_3")) - .inputItems(ModItems.MOON_STONE.get(), 64) + .inputItems(MOON_STONE.asStack(64)) .chancedInput(ChemicalHelper.get(block, GalliumArsenide, 4), 5500, -100) .inputFluids(RocketFuel.getFluid(4000)) .outputFluids(NitricAcid.getFluid(1000)) diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/tags/StoneTags.java b/src/main/java/io/github/cpearl0/ctnhcore/data/tags/StoneTags.java index 22ee49dec..c4e18733f 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/tags/StoneTags.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/tags/StoneTags.java @@ -1,6 +1,7 @@ package io.github.cpearl0.ctnhcore.data.tags; import io.github.cpearl0.ctnhcore.registry.CTNHTags; +import io.github.cpearl0.ctnhcore.registry.ores.MoonOres; import net.minecraft.tags.TagKey; import net.minecraft.world.level.block.Block; @@ -17,7 +18,10 @@ public class StoneTags { public static void init(RegistrateTagsProvider provider) { - create(provider, CTNHTags.AD_ASTRA_STONES, ModBlocks.MOON_STONE.get(), ModBlocks.MARS_STONE.get(), + var moonHosts = provider.addTag(CTNHTags.MOON_ORE_REPLACEABLES); + MoonOres.oreHosts().keySet() + .forEach(state -> moonHosts.add(state.get().getBlock().builtInRegistryHolder().key())); + create(provider, CTNHTags.AD_ASTRA_STONES, ModBlocks.MARS_STONE.get(), ModBlocks.MERCURY_STONE.get(), ModBlocks.VENUS_STONE.get(), ModBlocks.GLACIO_STONE.get(), Blocks.BLACKSTONE, Blocks.BASALT, Blocks.DEEPSLATE, Blocks.SOUL_SOIL); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java index d247fe166..d154d9250 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/legendary/ThermometerEnvironmentIntegration.java @@ -2,27 +2,9 @@ import io.github.cpearl0.ctnhcore.CTNHCore; -import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.config.ConfigHolder; - -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; -import com.lowdragmc.lowdraglib.gui.modular.ModularUI; -import com.lowdragmc.lowdraglib.gui.texture.ColorRectTexture; -import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; -import com.lowdragmc.lowdraglib.gui.widget.ComponentPanelWidget; -import com.lowdragmc.lowdraglib.gui.widget.DraggableScrollableWidgetGroup; -import com.lowdragmc.lowdraglib.gui.widget.ImageWidget; -import com.lowdragmc.lowdraglib.gui.widget.LabelWidget; -import com.lowdragmc.lowdraglib.gui.widget.ProgressWidget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; -import com.lowdragmc.lowdraglib.gui.widget.layout.Layout; import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -31,37 +13,16 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import com.ctnh.ctnhastral.common.environment.Atmosphere; -import com.ctnh.ctnhastral.common.environment.PlanetEnvironmentService; -import com.ctnh.ctnhastral.data.CAMedicalConditions; -import com.ctnh.ctnhastral.registry.CAEnvironments; import com.ctnhlang.CN; import com.ctnhlang.EN; import com.ctnhlang.Key; import sfiomn.legendarysurvivaloverhaul.registry.ItemRegistry; import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.TreeMap; -import java.util.function.DoubleSupplier; -import java.util.function.Supplier; - -/** 复用温度计外观,在物品面板中显示并同步 Astral 服务端环境读数。 */ +/** 将 LSO 温度计的物品事件接入环境检测器。 */ @Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public final class ThermometerEnvironmentIntegration { - private static final int TEXT_COLOR = 0xE4EDF2; - private static final int MUTED_COLOR = 0x9FAFB8; - // 颜色区分读数类别,不代表玩家防护后的危险等级。 - private static final int TEMPERATURE_COLOR = 0xFFC66D; - private static final int PRESSURE_COLOR = 0x6DD5ED; - private static final int RADIATION_COLOR = 0xC8A2FF; - private static final int CORROSION_COLOR = 0xA9D879; - private static final int COLD_COLOR = 0x77BFFF; - private static final int HEAT_COLOR = 0xFF997D; - @Key("tooltip.ctnhcore.thermometer.environment") @CN("对空气右键打开环境检测面板") @EN("Right-click in the air to open the environment panel") @@ -72,91 +33,6 @@ public final class ThermometerEnvironmentIntegration { @EN("Updates every second; press Esc to close") private static Lang readings; - @Key("gui.ctnhcore.environment_detector.close") - @CN("关闭") - @EN("Close") - private static Lang close; - - @Key("message.ctnhcore.thermometer.header") - @CN("环境检测读数") - @EN("Environment readings") - private static Lang header; - - @Key("message.ctnhcore.thermometer.location") - @CN("维度 %s") - @EN("Dimension %s") - private static Lang location; - - @Key("gui.ctnhcore.environment_detector.coordinates") - @CN("坐标 X %1$s · Y %2$s · Z %3$s") - @EN("Position X %1$s · Y %2$s · Z %3$s") - private static Lang coordinates; - - @Key("gui.ctnhcore.environment_detector.conditions") - @CN("环境条件") - @EN("Environment conditions") - private static Lang environmentConditions; - - @Key("message.ctnhcore.thermometer.temperature") - @CN("环境温度") - @EN("Ambient temperature") - private static Lang temperature; - - @Key("message.ctnhcore.thermometer.thermal_status") - @CN("玩家冷热累积") - @EN("Player thermal exposure") - private static Lang thermalStatus; - - @Key("gui.ctnhcore.environment_detector.hypothermia") - @CN("失温累积") - @EN("Hypothermia") - private static Lang hypothermia; - - @Key("gui.ctnhcore.environment_detector.hyperthermia") - @CN("热射病累积") - @EN("Hyperthermia") - private static Lang hyperthermia; - - @Key("gui.ctnhcore.environment_detector.no_thermal_data") - @CN("暂无读数") - @EN("Unavailable") - private static Lang noThermalData; - - @Key("message.ctnhcore.thermometer.pressure") - @CN("总气压") - @EN("Total pressure") - private static Lang totalPressure; - - @Key("gui.ctnhcore.environment_detector.radiation") - @CN("辐射剂量率") - @EN("Radiation dose rate") - private static Lang radiation; - - @Key("gui.ctnhcore.environment_detector.corrosion") - @CN("腐蚀速率") - @EN("Corrosion rate") - private static Lang corrosion; - - @Key("message.ctnhcore.thermometer.vacuum") - @CN("真空:无气体") - @EN("Vacuum: no gases") - private static Lang vacuum; - - @Key("message.ctnhcore.thermometer.composition") - @CN("大气成分") - @EN("Atmospheric composition") - private static Lang composition; - - @Key("message.ctnhcore.thermometer.gas") - @CN("分压 %1$s · 占比 %2$s") - @EN("Pressure %1$s · Share %2$s") - private static Lang gasReading; - - @Key("message.ctnhcore.thermometer.unlisted") - @CN("未描述气体") - @EN("Unspecified gases") - private static Lang unlisted; - @SubscribeEvent public static void onRightClickItem(PlayerInteractEvent.RightClickItem event) { Player player = event.getEntity(); @@ -179,173 +55,5 @@ public static void onItemTooltip(ItemTooltipEvent event) { event.getToolTip().add(readings.translate().withStyle(ChatFormatting.DARK_GRAY)); } - public static ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { - var data = new PanelReadings(); - updateReadings(player, data); - var content = new WidgetGroup(8, 0, 264, 0) { - - @Override - public void detectAndSendChanges() { - if (gui.getTickCount() % 20 == 0) { - updateReadings(player, data); - super.detectAndSendChanges(); - } - } - }; - content.setLayout(Layout.VERTICAL_LEFT); - content.setLayoutPadding(6); - content.setDynamicSized(true); - content.addWidget(new ComponentPanelWidget(0, 0, text -> text.addAll(data.location)) - .setMaxWidthLimit(264).setSpace(3)); - content.addWidget(section(environmentConditions)); - content.addWidget(new WidgetGroup(0, 0, 264, 32) - .addWidget(readingCard(0, temperature, TEMPERATURE_COLOR, () -> data.temperature)) - .addWidget(readingCard(136, totalPressure, PRESSURE_COLOR, () -> data.pressure))); - content.addWidget(new WidgetGroup(0, 0, 264, 32) - .addWidget(readingCard(0, radiation, RADIATION_COLOR, () -> data.radiation)) - .addWidget(readingCard(136, corrosion, CORROSION_COLOR, () -> data.corrosion))); - content.addWidget(section(thermalStatus)); - content.addWidget(new WidgetGroup(0, 0, 264, 38) - .addWidget(thermalCard(0, hypothermia, COLD_COLOR, () -> data.coldValue, () -> data.coldProgress)) - .addWidget(thermalCard(136, hyperthermia, HEAT_COLOR, () -> data.heatValue, () -> data.heatProgress))); - content.addWidget(section(composition)); - content.addWidget(new ComponentPanelWidget(0, 0, text -> text.addAll(data.gases)) - .setMaxWidthLimit(264).setSpace(3)); - - var scroll = new DraggableScrollableWidgetGroup(8, 30, 284, 180) - .setBackground(GuiTextures.DISPLAY) - .setYScrollBarWidth(4) - .setYBarStyle(null, ColorPattern.T_WHITE.rectTexture().setRadius(2)); - scroll.addWidget(content); - - return new ModularUI(300, 238, holder, player) - .background(GuiTextures.BACKGROUND) - .widget(new LabelWidget(12, 12, header.translate()).setTextColor(0xFF404040).setDropShadow(false)) - .widget(scroll) - .widget(new LabelWidget(12, 221, readings.translate()).setTextColor(0xFF404040).setDropShadow(false)) - .widget(new ButtonWidget(270, 7, 18, 18, click -> { - if (player instanceof ServerPlayer serverPlayer) { - serverPlayer.closeContainer(); - } - }).setButtonTexture(GuiTextures.BUTTON, GuiTextures.CLOSE_ICON) - .setHoverTooltips(close.translate())); - } - - private static WidgetGroup section(Lang title) { - return new WidgetGroup(0, 0, 264, 14) - .addWidget(new LabelWidget(0, 0, title.translate().withStyle(ChatFormatting.BOLD)) - .setTextColor(0xFF000000 | TEXT_COLOR).setDropShadow(false)) - .addWidget(new ImageWidget(0, 12, 264, 1, new ColorRectTexture(0xFF42545F))); - } - - private static WidgetGroup readingCard(int x, Lang title, int color, Supplier value) { - var card = new WidgetGroup(x, 0, 128, 32); - card.setBackground(new ColorRectTexture(0xFF20313B)); - card.addWidget(new ImageWidget(0, 0, 2, 32, new ColorRectTexture(0xFF000000 | color))); - card.addWidget(new LabelWidget(8, 5, title.translate()) - .setTextColor(0xFF000000 | MUTED_COLOR).setDropShadow(false)); - card.addWidget(new ComponentPanelWidget(8, 18, text -> text.add(value.get())).setMaxWidthLimit(112)); - return card; - } - - private static WidgetGroup thermalCard(int x, Lang title, int color, Supplier value, - DoubleSupplier progress) { - var card = readingCard(x, title, color, value); - card.setSizeHeight(38); - card.addWidget(new ProgressWidget(() -> Math.min(1.0, progress.getAsDouble()), 8, 31, 112, 3) - .setProgressTexture(new ColorRectTexture(0xFF101C24), new ColorRectTexture(0xFF000000 | color))); - return card; - } - - private static void updateReadings(Player player, PanelReadings data) { - // 客户端只展示同步后的文本,不自行计算环境或读取服务端医疗状态。 - if (!(player.level() instanceof ServerLevel level)) return; - var pos = player.blockPosition(); - var environment = PlanetEnvironmentService.getEnvironment(level, pos); - Atmosphere atmosphere = environment.get(CAEnvironments.ATMOSPHERE); - data.location = List.of( - location.translate(value(level.dimension().location().toString(), TEXT_COLOR)) - .withStyle(style -> style.withColor(MUTED_COLOR)), - coordinates.translate(value(Integer.toString(pos.getX()), TEXT_COLOR), - value(Integer.toString(pos.getY()), TEXT_COLOR), - value(Integer.toString(pos.getZ()), TEXT_COLOR)) - .withStyle(style -> style.withColor(MUTED_COLOR))); - data.temperature = quantity( - String.format(Locale.ROOT, "%.1f", environment.get(CAEnvironments.TEMPERATURE).celsius()), - "°C", TEMPERATURE_COLOR); - data.pressure = quantity(number(atmosphere.pressure()), "atm", PRESSURE_COLOR); - data.radiation = quantity(number(environment.get(CAEnvironments.RADIATION).rate()), "rad/s", RADIATION_COLOR); - data.corrosion = quantity(number(environment.get(CAEnvironments.CORROSION).rate()), "mm/a", CORROSION_COLOR); - - data.coldProgress = 0.0; - data.heatProgress = 0.0; - data.coldValue = noThermalData.translate().withStyle(style -> style.withColor(MUTED_COLOR)); - data.heatValue = data.coldValue; - var tracker = GTCapabilityHelper.getMedicalConditionTracker(player); - if (tracker != null && ConfigHolder.INSTANCE.gameplay.hazardsEnabled) { - var conditions = tracker.getMedicalConditions(); - data.coldProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPOTHERMIA)) / - CAMedicalConditions.HYPOTHERMIA.maxProgression; - data.heatProgress = Math.max(0.0F, conditions.getFloat(CAMedicalConditions.HYPERTHERMIA)) / - CAMedicalConditions.HYPERTHERMIA.maxProgression; - data.coldValue = quantity(String.format(Locale.ROOT, "%.1f", data.coldProgress * 100.0), "%", COLD_COLOR); - data.heatValue = quantity(String.format(Locale.ROOT, "%.1f", data.heatProgress * 100.0), "%", HEAT_COLOR); - } - - data.gases = new ArrayList<>(); - float pressure = atmosphere.pressure(); - if (pressure == 0.0F) { - data.gases.add(vacuum.translate().withStyle(ChatFormatting.GOLD)); - } else { - new TreeMap<>(atmosphere.partialPressures()).forEach((gas, partialPressure) -> { - Component name = Component.translatableWithFallback( - "gas." + gas.getNamespace() + "." + gas.getPath().replace('/', '.'), gas.toString()); - gasReadings(data.gases, name, partialPressure, 100.0 * partialPressure / pressure); - }); - double described = atmosphere.partialPressures().values().stream().mapToDouble(Float::doubleValue).sum(); - double remainder = pressure - described; - // 忽略浮点归一化的一位舍入误差,不把已描述完整的成分报为额外背景。 - if (remainder > Math.ulp(pressure)) { - gasReadings(data.gases, unlisted.translate(), remainder, 100.0 * remainder / pressure); - } - } - } - - private static void gasReadings(List text, Component name, double partialPressure, double share) { - if (!text.isEmpty()) text.add(Component.empty()); - text.add(name.copy().withStyle(style -> style.withColor(TEXT_COLOR).withBold(true))); - text.add(gasReading.translate(quantity(number(partialPressure), "atm", PRESSURE_COLOR), - quantity(String.format(Locale.ROOT, "%.1f", share), "%", TEMPERATURE_COLOR)) - .withStyle(style -> style.withColor(MUTED_COLOR))); - } - - private static MutableComponent value(String value, int color) { - return Component.literal(value).withStyle(style -> style.withColor(color).withBold(true)); - } - - private static Component quantity(String value, String unit, int color) { - return value(value, color) - .append(Component.literal(" " + unit).withStyle(style -> style.withColor(MUTED_COLOR).withBold(false))); - } - - private static String number(double value) { - return String.format(Locale.ROOT, "%.4g", value); - } - - /** 每个打开的面板各自持有显示值;所有读数在同一次服务端采样中更新。 */ - private static final class PanelReadings { - - private List location = List.of(); - private Component temperature = Component.empty(); - private Component pressure = Component.empty(); - private Component radiation = Component.empty(); - private Component corrosion = Component.empty(); - private Component coldValue = Component.empty(); - private Component heatValue = Component.empty(); - private double coldProgress; - private double heatProgress; - private List gases = List.of(); - } - private ThermometerEnvironmentIntegration() {} } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java index 819d1a1b5..23c9d6b5e 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/legendarysurvival/ThermometerItemMixin.java @@ -1,6 +1,6 @@ package io.github.cpearl0.ctnhcore.mixin.legendarysurvival; -import io.github.cpearl0.ctnhcore.integration.legendary.ThermometerEnvironmentIntegration; +import io.github.cpearl0.ctnhcore.common.gui.EnvironmentDetectorUI; import com.lowdragmc.lowdraglib.gui.factory.HeldItemUIFactory; import com.lowdragmc.lowdraglib.gui.modular.ModularUI; @@ -46,7 +46,7 @@ public String getDescriptionId() { @Override public ModularUI createUI(Player player, HeldItemUIFactory.HeldItemHolder holder) { - return ThermometerEnvironmentIntegration.createUI(player, holder); + return EnvironmentDetectorUI.createUI(player, holder); } /** 使用说明由 Core 的物品提示事件提供,移除原有体温/饰品 HUD 说明。 */ diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHDimensionMarkers.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHDimensionMarkers.java index 25d676733..72cc353a8 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHDimensionMarkers.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHDimensionMarkers.java @@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceLocation; +import com.ctnh.ctnhastral.registry.worldgen.MoonBlocks; import com.ctnhlang.CN; import com.ctnhlang.EN; import tech.vixhentx.mcmod.ctnhlib.langprovider.Lang; @@ -44,8 +45,8 @@ public class CTNHDimensionMarkers { @EN("Twilight Forest") public static Lang dimensionTwilightforestTwilightForest; - public static final DimensionMarker MOON = createAndRegister(ResourceLocation.tryParse("ad_astra:moon"), - 1, ResourceLocation.tryParse("ad_astra:moon_stone"), dimensionAdAstraMoon.key()); + public static final DimensionMarker MOON = createAndRegister(CTNHWorlds.MOON, + 1, () -> MoonBlocks.MOON_STONE.get(), dimensionAdAstraMoon.key()); public static final DimensionMarker MARS = createAndRegister(ResourceLocation.tryParse("ad_astra:mars"), 2, ResourceLocation.tryParse("ad_astra:mars_stone"), dimensionAdAstraMars.key()); public static final DimensionMarker VENUS = createAndRegister(ResourceLocation.tryParse("ad_astra:venus"), diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHOres.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHOres.java index 6dc4a2537..cd5e7de41 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHOres.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHOres.java @@ -5,6 +5,7 @@ import io.github.cpearl0.ctnhcore.registry.ores.AetherOres; import io.github.cpearl0.ctnhcore.registry.ores.AlfheimOres; import io.github.cpearl0.ctnhcore.registry.ores.EndOres; +import io.github.cpearl0.ctnhcore.registry.ores.MoonOres; import io.github.cpearl0.ctnhcore.registry.ores.NetherOres; import io.github.cpearl0.ctnhcore.registry.ores.OverworldOres; import io.github.cpearl0.ctnhcore.registry.ores.TwilightForestOres; @@ -35,6 +36,7 @@ public static void init() { TwilightForestOres.init(); AetherOres.init(); AlfheimOres.init(); + MoonOres.init(); AdAstraOres.init(); } } diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTags.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTags.java index ec6423df1..3b6f87d69 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTags.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHTags.java @@ -12,6 +12,8 @@ public class CTNHTags { public static TagKey AD_ASTRA_STONES = TagUtil.createBlockTag("ad_astra_stones"); + public static final TagKey MOON_ORE_REPLACEABLES = TagKey.create(Registries.BLOCK, + CTNHCore.id("moon_ore_replaceables")); public static TagKey AETHER_STONES = TagUtil.createBlockTag("aether_stones"); public static TagKey ALFHEIM_STONES = TagUtil.createBlockTag("alfheim_stones"); // public static TagKey TIER5_RUNES = TagUtil.createItemTag("zenith_runes"); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorldgenLayers.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorldgenLayers.java index d1d2c98e8..4a8875b9c 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorldgenLayers.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorldgenLayers.java @@ -1,5 +1,8 @@ package io.github.cpearl0.ctnhcore.registry; +import io.github.cpearl0.ctnhcore.registry.ores.MoonOres; + +import com.gregtechceu.gtceu.api.data.chemical.material.ItemMaterialData; import com.gregtechceu.gtceu.api.data.worldgen.IWorldGenLayer; import com.gregtechceu.gtceu.api.data.worldgen.WorldGeneratorUtils; @@ -18,7 +21,9 @@ public enum CTNHWorldgenLayers implements IWorldGenLayer, StringRepresentable { - ADASTRA("ad_astra", new TagMatchTest(CTNHTags.AD_ASTRA_STONES), Set.of(MOON, MARS, MERCURY, VENUS, GLACIO)), + MOON("ctnh_moon", new TagMatchTest(CTNHTags.MOON_ORE_REPLACEABLES), Set.of(CTNHWorlds.MOON)), + + ADASTRA("ad_astra", new TagMatchTest(CTNHTags.AD_ASTRA_STONES), Set.of(MARS, MERCURY, VENUS, GLACIO)), TWILIGHT("twilight_forest", new TagMatchTest(BlockTags.STONE_ORE_REPLACEABLES), Set.of(TWILIGHT_FOREST)), @@ -26,7 +31,10 @@ public enum CTNHWorldgenLayers implements IWorldGenLayer, StringRepresentable { ALFHEIM("alfheim", new TagMatchTest(CTNHTags.ALFHEIM_STONES), Set.of(CTNHWorlds.ALFHEIM)); - public static void init() {} + public static void init() { + // GT resolves material layers through the host state's ore prefix after testing the replacement tag. + ItemMaterialData.ORES_INVERSE.putAll(MoonOres.oreHosts()); + } CTNHWorldgenLayers(String name, RuleTest target, Set levels) { this.name = name; diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorlds.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorlds.java index 6e781e2ab..f1bdb84d0 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorlds.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHWorlds.java @@ -2,11 +2,13 @@ import net.minecraft.resources.ResourceLocation; +import com.ctnh.ctnhastral.data.worldgen.WorldgenKeys; + public class CTNHWorlds { public static final ResourceLocation TWILIGHT_FOREST = ResourceLocation.tryBuild("twilightforest", "twilight_forest"); - public static final ResourceLocation MOON = ResourceLocation.tryBuild("ad_astra", "moon"); + public static final ResourceLocation MOON = WorldgenKeys.Dimensions.MOON.location(); public static final ResourceLocation VENUS = ResourceLocation.tryBuild("ad_astra", "venus"); public static final ResourceLocation MARS = ResourceLocation.tryBuild("ad_astra", "mars"); public static final ResourceLocation MERCURY = ResourceLocation.tryBuild("ad_astra", "mercury"); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/AdAstraOres.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/AdAstraOres.java index c125b9420..31b7ea618 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/AdAstraOres.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/AdAstraOres.java @@ -16,95 +16,6 @@ public class AdAstraOres { - // ==================== Moon ==================== - - public static GTOreDefinition SHELDONITE_VEIN_MOON = create("sheldonite_vein_moon", - "Moon Sheldonite Vein", - "月球谢尔顿矿脉", - vein -> vein.clusterSize(40) - .density(0.3F) - .weight(40) - .layer(CTNHWorldgenLayers.ADASTRA) - .heightRangeUniform(5, 50) - .dimensions(MOON) - .layeredVeinGenerator(generator -> generator - .buildLayerPattern(pattern -> pattern - .layer(l -> l.weight(3).mat(GTMaterials.Bornite).size(2, 4)) - .layer(l -> l.weight(2).mat(GTMaterials.Cooperite).size(1, 1)) - .layer(l -> l.weight(2).mat(PlatinumLineMaterials.PlatinumOre).size(1, 1)) - .layer(l -> l.weight(1).mat(PlatinumLineMaterials.PalladiumOre).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(PlatinumLineMaterials.PlatinumOre) - .placement(ABOVE) - .density(0.4F) - .radius(5))); - - public static GTOreDefinition PHOSPHATE_VEIN = create("phosphate_vein", - "Phosphate Vein", - "磷酸盐矿脉", - vein -> vein.weight(40) - .clusterSize(30) - .density(0.30F) - .discardChanceOnAirExposure(0) - .layer(CTNHWorldgenLayers.ADASTRA) - .dimensions(MOON) - .heightRangeUniform(-20, 50) - .layeredVeinGenerator(generator -> generator - .buildLayerPattern(pattern -> pattern - .layer(l -> l.weight(3).mat(GTMaterials.Apatite).size(2, 4)) - .layer(l -> l.weight(2).mat(GTMaterials.TricalciumPhosphate).size(1, 3)) - .layer(l -> l.weight(2).mat(CTNHMaterials.TrisodiumPhosphate).size(1, 2)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(CTNHMaterials.TrisodiumPhosphate) - .placement(ABOVE) - .density(0.4F) - .radius(5))); - - public static final GTOreDefinition BAUXITE_VEIN = create("bauxite_vein", - "Moon Bauxite Vein", - "月球铝土矿脉", - vein -> { - vein.clusterSize(36).weight(80).layer(CTNHWorldgenLayers.ADASTRA).density(0.3f).dimensions(MOON) - .heightRangeUniform(10, 80).discardChanceOnAirExposure(0f) - .layeredVeinGenerator(generator -> { - generator.buildLayerPattern(pattern -> { - pattern.layer(l -> l.weight(2).mat(GTMaterials.Bauxite).size(1, 4)) - .layer(l -> l.weight(1).mat(GTMaterials.Ilmenite).size(1, 2)) - .layer(l -> l.weight(1).mat(CTNHMaterials.Alumina).size(1, 1)); - }); - }); - }); - - public static final GTOreDefinition ILMENITE_VEIN = create("ilmenite_vein", - "Ilmenite Vein", - "钛铁矿脉", - vein -> { - vein.clusterSize(24).weight(16).layer(CTNHWorldgenLayers.ADASTRA).density(0.2f).dimensions(MOON) - .heightRangeUniform(-70, 10).discardChanceOnAirExposure(0f) - .layeredVeinGenerator(generator -> { - generator.buildLayerPattern(pattern -> { - pattern.layer(l -> l.weight(3).mat(GTMaterials.Ilmenite).size(1, 4)) - .layer(l -> l.weight(2).mat(GTMaterials.Chromite).size(1, 4)) - .layer(l -> l.weight(2).mat(GTMaterials.Uvarovite).size(1, 2)) - .layer(l -> l.weight(1).mat(GTMaterials.Perlite).size(1, 1)); - }); - }); - }); - - public static final GTOreDefinition DESH_VEIN_AD = create("desh_vein_ad", - "Moon Desh Vein", - "月球戴斯矿脉", - vein -> { - vein.clusterSize(24).weight(30).layer(CTNHWorldgenLayers.ADASTRA).density(0.3f).dimensions(MOON) - .heightRangeUniform(5, 40).discardChanceOnAirExposure(0f) - .layeredVeinGenerator(generator -> { - generator.buildLayerPattern(pattern -> { - pattern.layer(l -> l.weight(3).mat(AdastraMaterials.Desh).size(2, 3)) - .layer(l -> l.weight(1).mat(ArcaneCrystal).size(1, 2)); - }); - }); - }); - // ==================== Mars ==================== public static final GTOreDefinition OSTRUM_VEIN_AD = create("ostrum_vein_ad", @@ -517,7 +428,7 @@ public class AdAstraOres { "月球独居石矿脉", vein -> { vein.clusterSize(24).weight(30).layer(CTNHWorldgenLayers.ADASTRA).density(0.2f) - .dimensions(MOON, VENUS, GLACIO).heightRangeUniform(20, 40) + .dimensions(VENUS, GLACIO).heightRangeUniform(20, 40) .discardChanceOnAirExposure(0f).layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(3).mat(GTMaterials.Bastnasite).size(2, 4)) @@ -532,7 +443,7 @@ public class AdAstraOres { "石英岩矿脉", vein -> { vein.clusterSize(24).weight(20).layer(CTNHWorldgenLayers.ADASTRA).density(0.3f) - .dimensions(MOON, MARS, VENUS).heightRangeUniform(30, 80) + .dimensions(MARS, VENUS).heightRangeUniform(30, 80) .discardChanceOnAirExposure(0f).layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(3).mat(GTMaterials.Quartzite).size(2, 4)) @@ -547,7 +458,7 @@ public class AdAstraOres { "太空辉钼矿脉", vein -> { vein.clusterSize(25).weight(5).layer(CTNHWorldgenLayers.ADASTRA).density(0.25f) - .dimensions(MOON, MERCURY).heightRangeUniform(20, 50).discardChanceOnAirExposure(0f) + .dimensions(MERCURY).heightRangeUniform(20, 50).discardChanceOnAirExposure(0f) .layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(3).mat(GTMaterials.Wulfenite).size(2, 4)) @@ -563,7 +474,7 @@ public class AdAstraOres { "太空方铅矿脉", vein -> { vein.clusterSize(30).weight(40).layer(CTNHWorldgenLayers.ADASTRA).density(0.25f) - .dimensions(MOON, MARS, VENUS, GLACIO).heightRangeUniform(-15, 45) + .dimensions(MARS, VENUS, GLACIO).heightRangeUniform(-15, 45) .discardChanceOnAirExposure(0f).layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(3).mat(GTMaterials.Galena).size(2, 4)) @@ -578,7 +489,7 @@ public class AdAstraOres { "太空铜矿脉", vein -> { vein.clusterSize(36).weight(80).layer(CTNHWorldgenLayers.ADASTRA).density(0.3f) - .dimensions(MOON, MERCURY).heightRangeUniform(-40, 15).discardChanceOnAirExposure(0f) + .dimensions(MERCURY).heightRangeUniform(-40, 15).discardChanceOnAirExposure(0f) .layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(2).mat(GTMaterials.Chalcopyrite).size(2, 3)) @@ -594,7 +505,7 @@ public class AdAstraOres { "太空锡石矿脉", vein -> { vein.clusterSize(36).weight(50).layer(CTNHWorldgenLayers.ADASTRA).density(0.4f) - .dimensions(MOON, VENUS).heightRangeUniform(10, 80).discardChanceOnAirExposure(0f) + .dimensions(VENUS).heightRangeUniform(10, 80).discardChanceOnAirExposure(0f) .layeredVeinGenerator(generator -> { generator.buildLayerPattern(pattern -> { pattern.layer(l -> l.weight(3).mat(GTMaterials.Tin).size(2, 3)) diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java new file mode 100644 index 000000000..d3fc0f6c1 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java @@ -0,0 +1,212 @@ +package io.github.cpearl0.ctnhcore.registry.ores; + +import io.github.cpearl0.ctnhcore.data.materials.AdastraMaterials; +import io.github.cpearl0.ctnhcore.data.materials.PlatinumLineMaterials; +import io.github.cpearl0.ctnhcore.registry.CTNHWorldgenLayers; +import io.github.cpearl0.ctnhcore.registry.material.CTNHMaterials; + +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.common.data.GTMaterials; + +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +import com.ctnh.ctnhastral.data.CATagPrefixes; +import com.ctnh.ctnhastral.registry.worldgen.MoonBlocks; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import static com.gregtechceu.gtceu.api.data.worldgen.generator.indicators.SurfaceIndicatorGenerator.IndicatorPlacement.ABOVE; +import static io.github.cpearl0.ctnhcore.registry.CTNHOres.create; +import static io.github.cpearl0.ctnhcore.registry.CTNHWorlds.MOON; + +/** Lunar ore composition and host rocks; placement and vein shapes use the standard GT generators. */ +public final class MoonOres { + + private MoonOres() {} + + public static Map, TagPrefix> oreHosts() { + // Reuse existing ore variants for solid host rocks; ice, sand and crystals are not ore hosts. + Map, TagPrefix> hosts = new LinkedHashMap<>(); + hosts.put(MoonBlocks.MOON_STONE::getDefaultState, CATagPrefixes.oreMoonStone); + hosts.put(MoonBlocks.MOON_ANORTHOSITE::getDefaultState, CATagPrefixes.oreMoonStone); + hosts.put(MoonBlocks.MOON_BROKEN_ANORTHOSITE::getDefaultState, CATagPrefixes.oreMoonStone); + hosts.put(MoonBlocks.SILICON_BRECCIA::getDefaultState, CATagPrefixes.oreMoonStone); + hosts.put(Blocks.BASALT::defaultBlockState, TagPrefix.oreBasalt); + hosts.put(Blocks.SMOOTH_BASALT::defaultBlockState, TagPrefix.oreBasalt); + return hosts; + } + + public static void init() { + // Recreate definitions when GT rebuilds its ore registry during a resource reload. + create("sheldonite_vein_moon", "Moon Sheldonite Vein", "月球谢尔顿矿脉", + vein -> vein.clusterSize(40) + .density(0.3F).weight(40) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(5, 50) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Bornite).size(2, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.Cooperite).size(1, 1)) + .layer(l -> l.weight(2).mat(PlatinumLineMaterials.PlatinumOre).size(1, 1)) + .layer(l -> l.weight(1).mat(PlatinumLineMaterials.PalladiumOre).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(PlatinumLineMaterials.PlatinumOre) + .placement(ABOVE).density(0.4F).radius(5))); + + create("phosphate_vein", "Phosphate Vein", "磷酸盐矿脉", + vein -> vein.clusterSize(30) + .density(0.3F).weight(40) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(-20, 50) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Apatite).size(2, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.TricalciumPhosphate).size(1, 3)) + .layer(l -> l.weight(2).mat(CTNHMaterials.TrisodiumPhosphate).size(1, 2)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(CTNHMaterials.TrisodiumPhosphate) + .placement(ABOVE).density(0.4F).radius(5))); + + create("bauxite_vein", "Moon Bauxite Vein", "月球铝土矿脉", + vein -> vein.clusterSize(36) + .density(0.3F).weight(80) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(10, 80) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(2).mat(GTMaterials.Bauxite).size(1, 4)) + .layer(l -> l.weight(1).mat(GTMaterials.Ilmenite).size(1, 2)) + .layer(l -> l.weight(1).mat(CTNHMaterials.Alumina).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Bauxite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("ilmenite_vein", "Ilmenite Vein", "钛铁矿脉", + vein -> vein.clusterSize(24) + .density(0.2F).weight(16) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + // Keep a 12-block radius above the Moon's bottom bedrock layers. + .heightRangeUniform(-48, 10) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Ilmenite).size(1, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.Chromite).size(1, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.Uvarovite).size(1, 2)) + .layer(l -> l.weight(1).mat(GTMaterials.Perlite).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Ilmenite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("desh_vein_ad", "Moon Desh Vein", "月球戴斯矿脉", + vein -> vein.clusterSize(24) + .density(0.3F).weight(30) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(5, 40) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(AdastraMaterials.Desh).size(2, 3)) + .layer(l -> l.weight(1).mat(CTNHMaterials.ArcaneCrystal).size(1, 2)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(AdastraMaterials.Desh) + .placement(ABOVE).density(0.4F).radius(5))); + + create("monazite_vein_moon", "Moon Monazite Vein", "月球独居石矿脉", + vein -> vein.clusterSize(24) + .density(0.2F).weight(30) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(20, 40) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Bastnasite).size(2, 4)) + .layer(l -> l.weight(1).mat(GTMaterials.Monazite).size(1, 1)) + .layer(l -> l.weight(1).mat(GTMaterials.Neodymium).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Monazite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("quartzite_vein_moon", "Moon Quartzite Vein", "月球石英岩矿脉", + vein -> vein.clusterSize(24) + .density(0.3F).weight(20) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(30, 80) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Quartzite).size(2, 4)) + .layer(l -> l.weight(3).mat(GTMaterials.Barite).size(2, 4)) + .layer(l -> l.weight(3).mat(GTMaterials.CertusQuartz).size(2, 4)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Quartzite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("molybdenum_vein_moon", "Moon Molybdenite Vein", "月球辉钼矿脉", + vein -> vein.clusterSize(25) + .density(0.25F).weight(5) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(20, 50) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Wulfenite).size(2, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.Molybdenite).size(1, 1)) + .layer(l -> l.weight(1).mat(GTMaterials.Molybdenum).size(1, 1)) + .layer(l -> l.weight(1).mat(GTMaterials.Powellite).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Molybdenite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("galena_vein_moon", "Moon Galena Vein", "月球方铅矿脉", + vein -> vein.clusterSize(30) + .density(0.25F).weight(40) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(-15, 45) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Galena).size(2, 4)) + .layer(l -> l.weight(2).mat(GTMaterials.Silver).size(1, 1)) + .layer(l -> l.weight(1).mat(GTMaterials.Lead).size(1, 1)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Galena) + .placement(ABOVE).density(0.4F).radius(5))); + + create("copper_vein_moon", "Moon Copper Vein", "月球铜矿脉", + vein -> vein.clusterSize(36) + .density(0.3F).weight(80) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(-40, 15) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(2).mat(GTMaterials.Chalcopyrite).size(2, 3)) + .layer(l -> l.weight(1).mat(GTMaterials.Iron).size(1, 2)) + .layer(l -> l.weight(1).mat(GTMaterials.Pyrite).size(1, 2)) + .layer(l -> l.weight(1).mat(GTMaterials.Copper).size(1, 2)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Chalcopyrite) + .placement(ABOVE).density(0.4F).radius(5))); + + create("cassiterite_vein_moon", "Moon Cassiterite Vein", "月球锡石矿脉", + vein -> vein.clusterSize(36) + .density(0.4F).weight(50) + .layer(CTNHWorldgenLayers.MOON).dimensions(MOON) + .heightRangeUniform(10, 80) + .discardChanceOnAirExposure(0) + .layeredVeinGenerator(generator -> generator + .buildLayerPattern(pattern -> pattern + .layer(l -> l.weight(3).mat(GTMaterials.Tin).size(2, 3)) + .layer(l -> l.weight(1).mat(GTMaterials.Cassiterite).size(1, 2)))) + .surfaceIndicatorGenerator(indicator -> indicator + .surfaceRock(GTMaterials.Cassiterite) + .placement(ABOVE).density(0.4F).radius(5))); + } +} From 3abecbaea29aa0ecccb1f196ca737db554705f76 Mon Sep 17 00:00:00 2001 From: ShenShang <16601765+daijugui@user.noreply.gitee.com> Date: Sat, 17 Oct 2026 00:16:33 -0700 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=9C=88?= =?UTF-8?q?=E7=90=83=E8=B5=84=E6=BA=90=E5=A4=84=E7=90=86=E4=B8=8EFTB?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接入月海卤水提锂、Li6PS5Cl固态电解质与IV固态电池产线,补充月石脱气、矿物分离与月球材料回收。 从实际模型贴图、顶点色和位置着色计算FTB默认地图颜色,并通过独立像素快照与重绘时序修复资源重载后地图停止刷新的问题。 同步生成语言、物品模型与电池标签。 --- .../resources/assets/ctnhcore/lang/en_ud.json | 12 + .../resources/assets/ctnhcore/lang/en_us.json | 12 + .../resources/assets/ctnhcore/lang/zh_cn.json | 12 + .../item/iv_moon_solid_state_battery.json | 56 +++++ .../data/gtceu/tags/items/batteries/iv.json | 1 + .../data/materials/MoonBrineMaterials.java | 88 +++++++ .../data/materials/StonePowderMaterials.java | 24 ++ .../data/recipe/CTNHCoreRecipeAddition.java | 1 + .../data/recipe/MoonMaterialRecipes.java | 12 +- .../data/recipe/chain/MoonBrineChain.java | 122 ++++++++++ .../recipe/migrated/GtceuScriptRecipes.java | 6 +- .../ftbchunks/TextureBlockColor.java | 224 ++++++++++++++++++ .../mixin/ftbchunks/ColorMapLoaderMixin.java | 30 +++ .../cpearl0/ctnhcore/registry/CTNHItems.java | 19 ++ .../registry/material/CTNHMaterials.java | 1 + .../registry/material/GTMaterialAddon.java | 1 + .../ctnhcore/registry/ores/MoonOres.java | 56 +---- src/main/resources/ctnhcore.mixins.json | 1 + 18 files changed, 627 insertions(+), 51 deletions(-) create mode 100644 src/generated/resources/assets/ctnhcore/models/item/iv_moon_solid_state_battery.json create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/data/materials/MoonBrineMaterials.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/data/recipe/chain/MoonBrineChain.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/integration/ftbchunks/TextureBlockColor.java create mode 100644 src/main/java/io/github/cpearl0/ctnhcore/mixin/ftbchunks/ColorMapLoaderMixin.java diff --git a/src/generated/resources/assets/ctnhcore/lang/en_ud.json b/src/generated/resources/assets/ctnhcore/lang/en_ud.json index adda6e208..46d5e8840 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_ud.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_ud.json @@ -1241,6 +1241,7 @@ "item.ctnhcore.heavy_plate_t4": "ㄣ⟘ ǝʇɐןԀ ʎoןןⱯ ʎʌɐǝH", "item.ctnhcore.high_quality_solid_fuel": "ןǝnℲ pıןoS ʎʇıןɐnὉ ɥbıH", "item.ctnhcore.inverter": "ɹǝʇɹǝʌuI", + "item.ctnhcore.iv_moon_solid_state_battery": "ʎɹǝʇʇɐᗺ ǝʇɐʇS pıןoS uooW ΛI", "item.ctnhcore.lapotron_crystal_granule": "ǝןnuɐɹ⅁ ןɐʇsʎɹƆ uoɹʇodɐꞀ", "item.ctnhcore.level": "ןǝʌǝן", "item.ctnhcore.lpic_wafer_rubber_masked": "ɹǝɟɐM ƆIԀꞀ pǝʞsɐɯ-ɹǝqqnᴚ", @@ -1368,6 +1369,7 @@ "material.ctnhcore.barium_chloride": "ǝpıɹoןɥƆ ɯnıɹɐᗺ", "material.ctnhcore.barium_hydroxide": "ǝpıxoɹpʎH ɯnıɹɐᗺ", "material.ctnhcore.barium_sulfate_solution": "uoıʇnןoS ǝʇɐɟןnS ɯnıɹɐᗺ", + "material.ctnhcore.battery_grade_lithium_chloride": "ǝpıɹoןɥƆ ɯnıɥʇıꞀ ǝpɐɹ⅁ ʎɹǝʇʇɐᗺ", "material.ctnhcore.bedrock_dust": "ʇsnᗡ ʞɔoɹpǝᗺ", "material.ctnhcore.bedrock_dust_solution": "uoıʇnןoS ʇsnᗡ ʞɔoɹpǝᗺ", "material.ctnhcore.bedrock_fog": "boℲ ʞɔoɹpǝᗺ", @@ -1452,6 +1454,7 @@ "material.ctnhcore.concentrated_ammonium_chlororhodate": "ǝʇɐpoɥɹoɹoןɥƆ ɯnıuoɯɯⱯ pǝʇɐɹʇuǝɔuoƆ", "material.ctnhcore.concentrated_high_level_radioactive_dust": "ʇsnᗡ ǝʌıʇɔɐoıpɐᴚ ןǝʌǝꞀ ɥbıH pǝʇɐɹʇuǝɔuoƆ", "material.ctnhcore.concentrated_low_level_radioactive_dust": "ʇsnᗡ ǝʌıʇɔɐoıpɐᴚ ןǝʌǝꞀ ʍoꞀ pǝʇɐɹʇuǝɔuoƆ", + "material.ctnhcore.concentrated_moon_brine": "ǝuıɹᗺ uooW pǝʇɐɹʇuǝɔuoƆ", "material.ctnhcore.conductive_alloy": "ʎoןןⱯ ǝʌıʇɔnpuoƆ", "material.ctnhcore.copper_alloy": "ʎoןןⱯ ɹǝddoƆ", "material.ctnhcore.copper_chloride": "ǝpıɹoןɥƆ ɹǝddoƆ", @@ -1515,6 +1518,7 @@ "material.ctnhcore.cyanide_tailings": "sbuıןıɐ⟘ ǝpıuɐʎƆ", "material.ctnhcore.dark_steel": "ןǝǝʇS ʞɹɐᗡ", "material.ctnhcore.debrominated_water": "ɹǝʇɐM pǝʇɐuıɯoɹqǝᗡ", + "material.ctnhcore.degassed_moon_stone": "ǝuoʇS uooW pǝssɐbǝᗡ", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "uoıʇnןoS ɯnıpɐןןɐԀ ɯnuıʇɐןԀ pןo⅁ pǝʇɐɹʇıuǝᗡ", "material.ctnhcore.dense_hydrazine_mixed_fuel": "ןǝnℲ pǝxıW ǝuızɐɹpʎH ǝsuǝᗡ", "material.ctnhcore.desh": "ɥsǝᗡ", @@ -1671,12 +1675,16 @@ "material.ctnhcore.liquid_twilightforest_air": "ɹıⱯ ʇsǝɹoɟʇɥbıןıʍ⟘ pınbıꞀ", "material.ctnhcore.liquid_venus_air": "ɹıⱯ snuǝΛ pınbıꞀ", "material.ctnhcore.litharge": "ǝbɹɐɥʇıꞀ", + "material.ctnhcore.lithium_mother_liquor": "ɹonbıꞀ ɹǝɥʇoW ɯnıɥʇıꞀ ɹɐunꞀ", + "material.ctnhcore.lithium_sulfide": "ǝpıɟןnS ɯnıɥʇıꞀ", + "material.ctnhcore.lithium_thiophosphate_chloride_electrolyte": "ǝʇʎןoɹʇɔǝןƎ pıןoS ǝpıɹoןɥƆ ǝʇɐɥdsoɥdoıɥ⟘ ɯnıɥʇıꞀ", "material.ctnhcore.living_metal": "ןɐʇǝW buıʌıꞀ", "material.ctnhcore.living_metal_pre": "ǝɹԀ ןɐʇǝW buıʌıꞀ", "material.ctnhcore.low_level_radioactive_dust": "ʇsnᗡ ǝʌıʇɔɐoıpɐᴚ ןǝʌǝꞀ ʍoꞀ", "material.ctnhcore.lutetium_chloride": "ǝpıɹoןɥƆ ɯnıʇǝʇnꞀ", "material.ctnhcore.lutetium_tail_solution": "uoıʇnןoS ןıɐ⟘ ɯnıʇǝʇnꞀ", "material.ctnhcore.lyase": "ǝsɐʎꞀ", + "material.ctnhcore.magnesium_calcium_precipitate": "ǝʇɐʇıdıɔǝɹԀ ɯnıɔןɐƆ ɯnısǝubɐW", "material.ctnhcore.magnesium_hydroxide": "ǝpıxoɹpʎH ɯnısǝubɐW", "material.ctnhcore.magnetron_sputtering_target_material": "ןɐıɹǝʇɐW ʇǝbɹɐ⟘ buıɹǝʇʇndS uoɹʇǝubɐW", "material.ctnhcore.manganese_acetate": "ǝʇɐʇǝɔⱯ ǝsǝuɐbuɐW", @@ -1690,6 +1698,7 @@ "material.ctnhcore.methyl_isobutyl_ketone": "ǝuoʇǝʞ ןʎʇnqosI ןʎɥʇǝW", "material.ctnhcore.methylhydrazine_nitrate_rocket_fuel": "ןǝnℲ ʇǝʞɔoᴚ ǝʇɐɹʇıN ǝuızɐɹpʎɥןʎɥʇǝW", "material.ctnhcore.molybdenum_trioxide": "ǝpıxoıɹ⟘ ɯnuǝpqʎןoW", + "material.ctnhcore.moon_anorthosite": "ǝʇısoɥʇɹouⱯ uooW", "material.ctnhcore.my_infinity": "ʎʇıuıɟuI ʎW", "material.ctnhcore.mystery_fluid": "pınןℲ ʎɹǝʇsʎW", "material.ctnhcore.nami_c": "Ɔ ıɯɐN", @@ -1758,6 +1767,7 @@ "material.ctnhcore.phosphate_buffer": "ɹǝɟɟnᗺ ǝʇɐɥdsoɥԀ", "material.ctnhcore.phosphonate": "ǝʇɐuoɥdsoɥԀ", "material.ctnhcore.phosphorous_acid": "pıɔⱯ snoɹoɥdsoɥԀ", + "material.ctnhcore.phosphorus_pentasulfide": "ǝpıɟןnsɐʇuǝԀ snɹoɥdsoɥԀ", "material.ctnhcore.phthalic_anhydride": "ǝpıɹpʎɥuⱯ ɔıןɐɥʇɥԀ", "material.ctnhcore.pikyonium": "ɯnıuoʎʞıԀ", "material.ctnhcore.piranha_solution": "uoıʇnןoS ɐɥuɐɹıԀ", @@ -1787,6 +1797,7 @@ "material.ctnhcore.pure_bitumen": "uǝɯnʇıᗺ ǝɹnԀ", "material.ctnhcore.pure_sodium_aluminate_solution": "uoıʇnןoS ǝʇɐuıɯnןⱯ ɯnıpoS ǝɹnԀ", "material.ctnhcore.purified_ender_quartz": "zʇɹɐnὉ ɹǝpuƎ pǝıɟıɹnԀ", + "material.ctnhcore.purified_lithium_brine": "ǝuıɹᗺ ɯnıɥʇıꞀ pǝıɟıɹnԀ", "material.ctnhcore.purified_meteor_crystal": "ןɐʇsʎɹƆ ɹoǝʇǝW pǝıɟıɹnԀ", "material.ctnhcore.purified_resonating_crystal": "ןɐʇsʎɹƆ buıʇɐuosǝᴚ pǝıɟıɹnԀ", "material.ctnhcore.purified_uranyl_nitrate": "ǝʇɐɹʇıN ןʎuɐɹ∩ pǝıɟıɹnԀ", @@ -1914,6 +1925,7 @@ "material.ctnhcore.succinic_anhydride": "ǝpıɹpʎɥuⱯ ɔıuıɔɔnS", "material.ctnhcore.succinimide": "ǝpıɯıuıɔɔnS", "material.ctnhcore.succinimidyl_acetate": "ǝʇɐʇǝɔⱯ ןʎpıɯıuıɔɔnS", + "material.ctnhcore.sulfide_electrolyte_mixture": "ǝɹnʇxıW ǝʇʎןoɹʇɔǝןƎ ǝpıɟןnS", "material.ctnhcore.sunnarium": "ɯnıɹɐuunS", "material.ctnhcore.sunnarium_extract": "ʇɔɐɹʇxƎ ɯnıɹɐuunS", "material.ctnhcore.superfuelmk1": "ƖʞɯןǝnɟɹǝdnS", diff --git a/src/generated/resources/assets/ctnhcore/lang/en_us.json b/src/generated/resources/assets/ctnhcore/lang/en_us.json index f7b5fc169..f960d3fff 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_us.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_us.json @@ -1241,6 +1241,7 @@ "item.ctnhcore.heavy_plate_t4": "Heavy Alloy Plate T4", "item.ctnhcore.high_quality_solid_fuel": "High Quality Solid Fuel", "item.ctnhcore.inverter": "Inverter", + "item.ctnhcore.iv_moon_solid_state_battery": "IV Moon Solid State Battery", "item.ctnhcore.lapotron_crystal_granule": "Lapotron Crystal Granule", "item.ctnhcore.level": "level", "item.ctnhcore.lpic_wafer_rubber_masked": "Rubber-masked LPIC Wafer", @@ -1368,6 +1369,7 @@ "material.ctnhcore.barium_chloride": "Barium Chloride", "material.ctnhcore.barium_hydroxide": "Barium Hydroxide", "material.ctnhcore.barium_sulfate_solution": "Barium Sulfate Solution", + "material.ctnhcore.battery_grade_lithium_chloride": "Battery Grade Lithium Chloride", "material.ctnhcore.bedrock_dust": "Bedrock Dust", "material.ctnhcore.bedrock_dust_solution": "Bedrock Dust Solution", "material.ctnhcore.bedrock_fog": "Bedrock Fog", @@ -1452,6 +1454,7 @@ "material.ctnhcore.concentrated_ammonium_chlororhodate": "Concentrated Ammonium Chlororhodate", "material.ctnhcore.concentrated_high_level_radioactive_dust": "Concentrated High Level Radioactive Dust", "material.ctnhcore.concentrated_low_level_radioactive_dust": "Concentrated Low Level Radioactive Dust", + "material.ctnhcore.concentrated_moon_brine": "Concentrated Moon Brine", "material.ctnhcore.conductive_alloy": "Conductive Alloy", "material.ctnhcore.copper_alloy": "Copper Alloy", "material.ctnhcore.copper_chloride": "Copper Chloride", @@ -1515,6 +1518,7 @@ "material.ctnhcore.cyanide_tailings": "Cyanide Tailings", "material.ctnhcore.dark_steel": "Dark Steel", "material.ctnhcore.debrominated_water": "Debrominated Water", + "material.ctnhcore.degassed_moon_stone": "Degassed Moon Stone", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "Denitrated Gold Platinum Palladium Solution", "material.ctnhcore.dense_hydrazine_mixed_fuel": "Dense Hydrazine Mixed Fuel", "material.ctnhcore.desh": "Desh", @@ -1671,12 +1675,16 @@ "material.ctnhcore.liquid_twilightforest_air": "Liquid Twilightforest Air", "material.ctnhcore.liquid_venus_air": "Liquid Venus Air", "material.ctnhcore.litharge": "Litharge", + "material.ctnhcore.lithium_mother_liquor": "Lunar Lithium Mother Liquor", + "material.ctnhcore.lithium_sulfide": "Lithium Sulfide", + "material.ctnhcore.lithium_thiophosphate_chloride_electrolyte": "Lithium Thiophosphate Chloride Solid Electrolyte", "material.ctnhcore.living_metal": "Living Metal", "material.ctnhcore.living_metal_pre": "Living Metal Pre", "material.ctnhcore.low_level_radioactive_dust": "Low Level Radioactive Dust", "material.ctnhcore.lutetium_chloride": "Lutetium Chloride", "material.ctnhcore.lutetium_tail_solution": "Lutetium Tail Solution", "material.ctnhcore.lyase": "Lyase", + "material.ctnhcore.magnesium_calcium_precipitate": "Magnesium Calcium Precipitate", "material.ctnhcore.magnesium_hydroxide": "Magnesium Hydroxide", "material.ctnhcore.magnetron_sputtering_target_material": "Magnetron Sputtering Target Material", "material.ctnhcore.manganese_acetate": "Manganese Acetate", @@ -1690,6 +1698,7 @@ "material.ctnhcore.methyl_isobutyl_ketone": "Methyl Isobutyl Ketone", "material.ctnhcore.methylhydrazine_nitrate_rocket_fuel": "Methylhydrazine Nitrate Rocket Fuel", "material.ctnhcore.molybdenum_trioxide": "Molybdenum Trioxide", + "material.ctnhcore.moon_anorthosite": "Moon Anorthosite", "material.ctnhcore.my_infinity": "My Infinity", "material.ctnhcore.mystery_fluid": "Mystery Fluid", "material.ctnhcore.nami_c": "Nami C", @@ -1758,6 +1767,7 @@ "material.ctnhcore.phosphate_buffer": "Phosphate Buffer", "material.ctnhcore.phosphonate": "Phosphonate", "material.ctnhcore.phosphorous_acid": "Phosphorous Acid", + "material.ctnhcore.phosphorus_pentasulfide": "Phosphorus Pentasulfide", "material.ctnhcore.phthalic_anhydride": "Phthalic Anhydride", "material.ctnhcore.pikyonium": "Pikyonium", "material.ctnhcore.piranha_solution": "Piranha Solution", @@ -1787,6 +1797,7 @@ "material.ctnhcore.pure_bitumen": "Pure Bitumen", "material.ctnhcore.pure_sodium_aluminate_solution": "Pure Sodium Aluminate Solution", "material.ctnhcore.purified_ender_quartz": "Purified Ender Quartz", + "material.ctnhcore.purified_lithium_brine": "Purified Lithium Brine", "material.ctnhcore.purified_meteor_crystal": "Purified Meteor Crystal", "material.ctnhcore.purified_resonating_crystal": "Purified Resonating Crystal", "material.ctnhcore.purified_uranyl_nitrate": "Purified Uranyl Nitrate", @@ -1914,6 +1925,7 @@ "material.ctnhcore.succinic_anhydride": "Succinic Anhydride", "material.ctnhcore.succinimide": "Succinimide", "material.ctnhcore.succinimidyl_acetate": "Succinimidyl Acetate", + "material.ctnhcore.sulfide_electrolyte_mixture": "Sulfide Electrolyte Mixture", "material.ctnhcore.sunnarium": "Sunnarium", "material.ctnhcore.sunnarium_extract": "Sunnarium Extract", "material.ctnhcore.superfuelmk1": "Superfuelmk1", diff --git a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json index 6475826e3..785ff6b10 100644 --- a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json +++ b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json @@ -1312,6 +1312,7 @@ "item.ctnhcore.heavy_plate_t4": "T4重型合金板", "item.ctnhcore.high_quality_solid_fuel": "高品质固体燃料", "item.ctnhcore.inverter": "逆变器", + "item.ctnhcore.iv_moon_solid_state_battery": "IV月海固态电池", "item.ctnhcore.lapotron_crystal_granule": "兰波顿水晶晶粒", "item.ctnhcore.lpic_wafer_rubber_masked": "橡胶掩膜的LPIC晶圆", "item.ctnhcore.me_advanced_terminal": "GT-MBST-A v7.0.1", @@ -1436,6 +1437,7 @@ "material.ctnhcore.barium_chloride": "氯化钡", "material.ctnhcore.barium_hydroxide": "氢氧化钡", "material.ctnhcore.barium_sulfate_solution": "硫酸钡悬浊液", + "material.ctnhcore.battery_grade_lithium_chloride": "电池级氯化锂", "material.ctnhcore.bedrock_dust": "基岩", "material.ctnhcore.bedrock_dust_solution": "基岩尘灰溶液", "material.ctnhcore.bedrock_fog": "基岩尘", @@ -1520,6 +1522,7 @@ "material.ctnhcore.concentrated_ammonium_chlororhodate": "浓缩氯铑酸铵溶液", "material.ctnhcore.concentrated_high_level_radioactive_dust": "浓缩高放射性尘埃", "material.ctnhcore.concentrated_low_level_radioactive_dust": "浓缩低放射性尘埃", + "material.ctnhcore.concentrated_moon_brine": "月海浓缩卤水", "material.ctnhcore.conductive_alloy": "导电合金", "material.ctnhcore.copper_alloy": "铜合金", "material.ctnhcore.copper_chloride": "氯化铜", @@ -1583,6 +1586,7 @@ "material.ctnhcore.cyanide_tailings": "氰化尾渣", "material.ctnhcore.dark_steel": "玄钢", "material.ctnhcore.debrominated_water": "脱溴盐水", + "material.ctnhcore.degassed_moon_stone": "脱气月石", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "除硝金-铂-钯酸性溶液", "material.ctnhcore.dense_hydrazine_mixed_fuel": "浓缩肼混合燃料", "material.ctnhcore.desh": "戴斯", @@ -1739,12 +1743,16 @@ "material.ctnhcore.liquid_twilightforest_air": "液态暮色森林空气", "material.ctnhcore.liquid_venus_air": "液态金星空气", "material.ctnhcore.litharge": "密陀僧", + "material.ctnhcore.lithium_mother_liquor": "月海含锂母液", + "material.ctnhcore.lithium_sulfide": "硫化锂", + "material.ctnhcore.lithium_thiophosphate_chloride_electrolyte": "氯硫化磷锂固态电解质", "material.ctnhcore.living_metal": "活体金属", "material.ctnhcore.living_metal_pre": "未激活态活体金属", "material.ctnhcore.low_level_radioactive_dust": "较低放射性尘埃", "material.ctnhcore.lutetium_chloride": "氯化镥", "material.ctnhcore.lutetium_tail_solution": "镥富集尾液", "material.ctnhcore.lyase": "裂解酶", + "material.ctnhcore.magnesium_calcium_precipitate": "镁钙沉淀", "material.ctnhcore.magnesium_hydroxide": "氢氧化镁", "material.ctnhcore.magnetron_sputtering_target_material": "载磁控溅射物料", "material.ctnhcore.manganese_acetate": "乙酸锰", @@ -1758,6 +1766,7 @@ "material.ctnhcore.methyl_isobutyl_ketone": "甲基异丁基酮", "material.ctnhcore.methylhydrazine_nitrate_rocket_fuel": "CN3H7O3火箭燃料", "material.ctnhcore.molybdenum_trioxide": "三氧化钼", + "material.ctnhcore.moon_anorthosite": "月球斜长岩", "material.ctnhcore.my_infinity": "无尽", "material.ctnhcore.mystery_fluid": "神秘液体", "material.ctnhcore.nami_c": "纳米级沉积碳", @@ -1826,6 +1835,7 @@ "material.ctnhcore.phosphate_buffer": "磷酸盐缓冲液", "material.ctnhcore.phosphonate": "膦酸酯", "material.ctnhcore.phosphorous_acid": "亚磷酸", + "material.ctnhcore.phosphorus_pentasulfide": "五硫化二磷", "material.ctnhcore.phthalic_anhydride": "邻苯二甲酸酐", "material.ctnhcore.pikyonium": "皮卡优", "material.ctnhcore.piranha_solution": "食人鱼洗液", @@ -1855,6 +1865,7 @@ "material.ctnhcore.pure_bitumen": "纯净沥青", "material.ctnhcore.pure_sodium_aluminate_solution": "纯净偏铝酸钠溶液", "material.ctnhcore.purified_ender_quartz": "高纯末影石英", + "material.ctnhcore.purified_lithium_brine": "净化锂卤液", "material.ctnhcore.purified_meteor_crystal": "高纯陨石水晶", "material.ctnhcore.purified_resonating_crystal": "高纯谐振水晶", "material.ctnhcore.purified_uranyl_nitrate": "纯化硝酸铀酰溶液", @@ -1982,6 +1993,7 @@ "material.ctnhcore.succinic_anhydride": "丁二酸酐", "material.ctnhcore.succinimide": "琥珀酰亚胺", "material.ctnhcore.succinimidyl_acetate": "琥珀酰亚胺醋酸酯", + "material.ctnhcore.sulfide_electrolyte_mixture": "氯硫化物电解质混料", "material.ctnhcore.sunnarium": "阳光化合物", "material.ctnhcore.sunnarium_extract": "阳光提取物", "material.ctnhcore.superfuelmk1": "超能燃料MK-I", diff --git a/src/generated/resources/assets/ctnhcore/models/item/iv_moon_solid_state_battery.json b/src/generated/resources/assets/ctnhcore/models/item/iv_moon_solid_state_battery.json new file mode 100644 index 000000000..8e996e177 --- /dev/null +++ b/src/generated/resources/assets/ctnhcore/models/item/iv_moon_solid_state_battery.json @@ -0,0 +1,56 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "gtceu:item/iv_vanadium_battery/0", + "predicate": { + "gtceu:battery": 0.0 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/1", + "predicate": { + "gtceu:battery": 0.01 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/2", + "predicate": { + "gtceu:battery": 0.02 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/3", + "predicate": { + "gtceu:battery": 0.03 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/4", + "predicate": { + "gtceu:battery": 0.04 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/5", + "predicate": { + "gtceu:battery": 0.05 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/6", + "predicate": { + "gtceu:battery": 0.06 + } + }, + { + "model": "gtceu:item/iv_vanadium_battery/7", + "predicate": { + "gtceu:battery": 0.07 + } + } + ], + "textures": { + "layer0": "gtceu:item/iv_vanadium_battery/1" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/gtceu/tags/items/batteries/iv.json b/src/generated/resources/data/gtceu/tags/items/batteries/iv.json index ae4acc95b..85e8a394f 100644 --- a/src/generated/resources/data/gtceu/tags/items/batteries/iv.json +++ b/src/generated/resources/data/gtceu/tags/items/batteries/iv.json @@ -1,5 +1,6 @@ { "values": [ + "ctnhcore:iv_moon_solid_state_battery", "ctnhcore:resonance_crystal", "ctnhcore:pure_certus_resonance_crystal" ] diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/materials/MoonBrineMaterials.java b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/MoonBrineMaterials.java new file mode 100644 index 000000000..5f1dddddd --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/MoonBrineMaterials.java @@ -0,0 +1,88 @@ +package io.github.cpearl0.ctnhcore.data.materials; + +import io.github.cpearl0.ctnhcore.CTNHCore; + +import com.gregtechceu.gtceu.api.data.chemical.material.Material; + +import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.DECOMPOSITION_BY_ELECTROLYZING; +import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.DISABLE_DECOMPOSITION; +import static com.gregtechceu.gtceu.common.data.GTMaterials.*; +import static io.github.cpearl0.ctnhcore.registry.CTNHRegistration.REGISTRATE; + +/** Lunar brine processing states and the precursors for its sulfide solid electrolyte. */ +public class MoonBrineMaterials { + + public static Material CONCENTRATED_MOON_BRINE; + public static Material LITHIUM_MOTHER_LIQUOR; + public static Material PURIFIED_LITHIUM_BRINE; + public static Material MAGNESIUM_CALCIUM_PRECIPITATE; + public static Material BATTERY_GRADE_LITHIUM_CHLORIDE; + public static Material LITHIUM_SULFIDE; + public static Material PHOSPHORUS_PENTASULFIDE; + public static Material SULFIDE_ELECTROLYTE_MIXTURE; + public static Material LITHIUM_THIOPHOSPHATE_CHLORIDE_ELECTROLYTE; + + public static void init() { + CONCENTRATED_MOON_BRINE = REGISTRATE.material(CTNHCore.id("concentrated_moon_brine")) + .lang("Concentrated Moon Brine").cnlang("月海浓缩卤水") + .formula("(NaCl)16(MgCl2)2(CaCl2)(LiCl)6+Br?+I?+H2O") + .liquid().color(0x426F86) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + LITHIUM_MOTHER_LIQUOR = REGISTRATE.material(CTNHCore.id("lithium_mother_liquor")) + .lang("Lunar Lithium Mother Liquor").cnlang("月海含锂母液") + .formula("(MgCl2)2(CaCl2)(LiCl)6+H2O") + .liquid().color(0x759487) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + PURIFIED_LITHIUM_BRINE = REGISTRATE.material(CTNHCore.id("purified_lithium_brine")) + .lang("Purified Lithium Brine").cnlang("净化锂卤液") + .formula("LiCl(aq)") + .liquid().color(0xBBCFDB) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + MAGNESIUM_CALCIUM_PRECIPITATE = REGISTRATE.material(CTNHCore.id("magnesium_calcium_precipitate")) + .lang("Magnesium Calcium Precipitate").cnlang("镁钙沉淀") + .formula("(Mg(OH)2)2CaCO3") + .dust().color(0xC8C3B3) + .components(Magnesium, 2, Calcium, 1, Hydrogen, 4, Carbon, 1, Oxygen, 7) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + BATTERY_GRADE_LITHIUM_CHLORIDE = REGISTRATE.material(CTNHCore.id("battery_grade_lithium_chloride")) + .lang("Battery Grade Lithium Chloride").cnlang("电池级氯化锂") + .formula("LiCl") + .dust().color(0xE2EAF0) + .components(Lithium, 1, Chlorine, 1) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .buildAndRegister(); + LITHIUM_SULFIDE = REGISTRATE.material(CTNHCore.id("lithium_sulfide")) + .lang("Lithium Sulfide").cnlang("硫化锂") + .formula("Li2S") + .dust().color(0xD9DCA5) + .components(Lithium, 2, Sulfur, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + PHOSPHORUS_PENTASULFIDE = REGISTRATE.material(CTNHCore.id("phosphorus_pentasulfide")) + .lang("Phosphorus Pentasulfide").cnlang("五硫化二磷") + .formula("P2S5") + .dust().color(0xE8BE4B) + .components(Phosphorus, 2, Sulfur, 5) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + SULFIDE_ELECTROLYTE_MIXTURE = REGISTRATE.material(CTNHCore.id("sulfide_electrolyte_mixture")) + .lang("Sulfide Electrolyte Mixture").cnlang("氯硫化物电解质混料") + .formula("Li6PS5Cl") + .dust().color(0xC7BC75) + .components(Lithium, 6, Phosphorus, 1, Sulfur, 5, Chlorine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + LITHIUM_THIOPHOSPHATE_CHLORIDE_ELECTROLYTE = REGISTRATE + .material(CTNHCore.id("lithium_thiophosphate_chloride_electrolyte")) + .lang("Lithium Thiophosphate Chloride Solid Electrolyte").cnlang("氯硫化磷锂固态电解质") + .formula("Li6PS5Cl") + .dust().color(0xE4DBA8) + .components(Lithium, 6, Phosphorus, 1, Sulfur, 5, Chlorine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java index 71c7aa2b0..57fafc2b1 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java @@ -4,15 +4,20 @@ import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.DECOMPOSITION_BY_CENTRIFUGING; import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.DISABLE_DECOMPOSITION; +import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconSet.ROUGH; import static com.gregtechceu.gtceu.common.data.GTMaterials.*; import static io.github.cpearl0.ctnhcore.registry.CTNHRegistration.REGISTRATE; +import static io.github.cpearl0.ctnhcore.registry.material.CTNHMaterials.Alumina; public class StonePowderMaterials { public static Material DIRTY_HEXAFLUOROSILICIC_ACID; public static Material DILUTE_HEXAFLUOROSILICIC_ACID; public static Material STONE_RESIDUE; + public static Material DEGASSED_MOON_STONE; + public static Material MOON_ANORTHOSITE; public static Material FLUOROSILICIC_ACID; public static Material UNCOMMON_RESIDUES; public static Material DIOXYGENDIFLUORIDE; @@ -54,6 +59,25 @@ public static void init() { .color(0xA1A19E) .buildAndRegister(); + // GT generates the LV mineral separation recipe; gas-bearing Moonstone remains a separate material. + // Keep Moonstone's ROUGH texture and neutral greys, darkened equally for the processed state. + DEGASSED_MOON_STONE = REGISTRATE.material(CTNHCore.id("degassed_moon_stone")) + .cnlang("脱气月石") + .dust() + .color(0x9B9B9B).secondaryColor(0x656565).iconSet(ROUGH) + .components(SiliconDioxide, 20, Alumina, 8, Quicklime, 4, Magnesia, 3, Ilmenite, 1) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .buildAndRegister(); + + // Simplify anorthite-rich lunar rock into oxide groups for GT's generated mineral separation. + MOON_ANORTHOSITE = REGISTRATE.material(CTNHCore.id("moon_anorthosite")) + .cnlang("月球斜长岩") + .dust() + .color(0xC9CDD3).secondaryColor(0x9298A2).iconSet(ROUGH) + .components(SiliconDioxide, 2, Alumina, 1, Quicklime, 1) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .buildAndRegister(); + FLUOROSILICIC_ACID = REGISTRATE.material(CTNHCore.id("fluorosilicic_acid")) .cnlang("氟硅酸") .liquid() diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java index c59774ea2..62ad8415c 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/CTNHCoreRecipeAddition.java @@ -35,6 +35,7 @@ public static void init(Consumer provider) { OreProcessingRecipes.init(provider); MoonMaterialRecipes.init(provider); + MoonBrineChain.init(provider); UnderfloorHeatingSystemRecipes.init(provider); AstronomicalObservatoryRecipes.init(provider); PersonalComputerRecipes.init(provider); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java index 1cc9cfd45..a16a003c0 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/MoonMaterialRecipes.java @@ -1,5 +1,7 @@ package io.github.cpearl0.ctnhcore.data.recipe; +import io.github.cpearl0.ctnhcore.data.materials.StonePowderMaterials; + import com.gregtechceu.gtceu.api.data.chemical.material.ItemMaterialData; import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.stack.ItemMaterialInfo; @@ -20,7 +22,7 @@ import static com.gregtechceu.gtceu.api.GTValues.M; import static com.gregtechceu.gtceu.common.data.GTMaterials.*; -/** Bind existing lunar blocks to GT's stone families and material recycling, without per-block recipes. */ +/** Lunar stone families and material recycling. */ public class MoonMaterialRecipes { public static void init(Consumer provider) { @@ -40,10 +42,10 @@ public static void init(Consumer provider) { .material(Moonstone).registerAllMaterialInfo().build(), new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_anorthosite") .stone(MOON_ANORTHOSITE.asItem()).crackedStone(MOON_BROKEN_ANORTHOSITE.asItem()) - .material(Stone).registerAllMaterialInfo().build(), + .material(StonePowderMaterials.MOON_ANORTHOSITE).registerAllMaterialInfo().build(), new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_moon_broken_anorthosite") .stone(MOON_BROKEN_ANORTHOSITE.asItem()).smeltStone(MOON_ANORTHOSITE.asItem()) - .material(Stone).registerAllMaterialInfo().build(), + .material(StonePowderMaterials.MOON_ANORTHOSITE).registerAllMaterialInfo().build(), new StoneTypeEntry.Builder("ctnhastral", "ctnhastral_silicon_crust") .stone(SILICON_CRUST.asItem()).crackedStone(SILICON_GRAVEL.asItem()) .material(SiliconDioxide).registerAllMaterialInfo().build())) { @@ -52,7 +54,7 @@ public static void init(Consumer provider) { } material(MOON_SAND, Moonstone, M); - material(SILICON_BRECCIA, Stone, M); + material(SILICON_BRECCIA, Moonstone, M); for (var block : List.of(MOONLIGHT_SAND, SILICON_GRAVEL, SILICON_CRYSTAL)) { material(block, SiliconDioxide, M); } @@ -67,6 +69,8 @@ public static void init(Consumer provider) { new MaterialStack(SiliconDioxide, M), new MaterialStack(Glowstone, M))); ItemMaterialData.registerMaterialInfo(MOONLIGHT_CRYSTAL, new ItemMaterialInfo( new MaterialStack(SiliconDioxide, 4 * M), new MaterialStack(Glowstone, 4 * M))); + ItemMaterialData.registerMaterialInfo(LAYERED_MOONLIGHT_CRYSTAL, new ItemMaterialInfo( + new MaterialStack(SiliconDioxide, 4 * M), new MaterialStack(Glowstone, 4 * M))); // Use the same Ice material as vanilla ice. Its dust already has GT extraction/heating recipes. material(MOON_DENSE_ICE, Ice, M); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/chain/MoonBrineChain.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/chain/MoonBrineChain.java new file mode 100644 index 000000000..42071ac75 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/chain/MoonBrineChain.java @@ -0,0 +1,122 @@ +package io.github.cpearl0.ctnhcore.data.recipe.chain; + +import io.github.cpearl0.ctnhcore.CTNHCore; +import io.github.cpearl0.ctnhcore.registry.CTNHItems; +import io.github.cpearl0.ctnhcore.registry.CTNHRecipeTypes; + +import com.gregtechceu.gtceu.common.data.GTItems; +import com.gregtechceu.gtceu.data.recipe.CustomTags; + +import net.minecraft.data.recipes.FinishedRecipe; + +import java.util.function.Consumer; + +import static com.ctnh.ctnhastral.data.CAMaterials.MoonEnrichedBrine; +import static com.ctnh.ctnhastral.data.CAMaterials.Moonstone; +import static com.gregtechceu.gtceu.api.GTValues.*; +import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*; +import static com.gregtechceu.gtceu.common.data.GTMaterials.*; +import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*; +import static io.github.cpearl0.ctnhcore.data.materials.MoonBrineMaterials.*; +import static io.github.cpearl0.ctnhcore.registry.material.CTNHMaterials.IodizedBrine; + +/** Lunar co-extraction feeds the existing halogen chain and native GT solid-state batteries. */ +public class MoonBrineChain { + + public static void init(Consumer provider) { + // Keep the complete co-extraction batch in the tower, without single-output distillery shortcuts. + DISTILLATION_RECIPES.recipeBuilder(CTNHCore.id("moon_brine_concentration")) + .inputFluids(MoonEnrichedBrine.getFluid(32000)) + .outputFluids(DistilledWater.getFluid(24000)) + .outputFluids(CONCENTRATED_MOON_BRINE.getFluid(8000)) + .outputItems(dust, Moonstone, 4) + .disableDistilleryRecipes(true) + .EUt(VA[HV]).duration(400) + .save(provider); + + CENTRIFUGE_RECIPES.recipeBuilder(CTNHCore.id("moon_brine_fractionation")) + .inputFluids(CONCENTRATED_MOON_BRINE.getFluid(8000)) + .outputItems(dust, Salt, 32) + .outputFluids(LITHIUM_MOTHER_LIQUOR.getFluid(4000)) + .outputFluids(IodizedBrine.getFluid(4000)) + .EUt(VA[HV]).duration(300) + .save(provider); + + LARGE_CHEMICAL_RECIPES.recipeBuilder(CTNHCore.id("lithium_mother_liquor_purification")) + .inputFluids(LITHIUM_MOTHER_LIQUOR.getFluid(4000)) + .inputItems(dust, SodiumHydroxide, 12) + .inputItems(dust, SodaAsh, 6) + .outputFluids(PURIFIED_LITHIUM_BRINE.getFluid(4000)) + .outputItems(dust, MAGNESIUM_CALCIUM_PRECIPITATE, 15) + .outputItems(dust, Salt, 12) + .EUt(VA[EV]).duration(300) + .save(provider); + + CTNHRecipeTypes.DEHYDRATOR_RECIPES.recipeBuilder(CTNHCore.id("battery_grade_lithium_chloride")) + .inputFluids(PURIFIED_LITHIUM_BRINE.getFluid(4000)) + .outputItems(dust, BATTERY_GRADE_LITHIUM_CHLORIDE, 12) + .outputFluids(Water.getFluid(4000)) + .EUt(VA[EV]).duration(200) + .save(provider); + + CTNHRecipeTypes.DEHYDRATOR_RECIPES.recipeBuilder(CTNHCore.id("moon_brine_precipitate_recovery")) + .inputItems(dust, MAGNESIUM_CALCIUM_PRECIPITATE, 15) + .outputItems(dust, Magnesia, 4) + .outputItems(dust, Calcite, 5) + .outputFluids(Water.getFluid(2000)) + .EUt(VA[HV]).duration(200) + .save(provider); + + CHEMICAL_BATH_RECIPES.recipeBuilder(CTNHCore.id("lithium_chloride_purification")) + .inputItems(dust, LithiumChloride, 12) + .inputFluids(DistilledWater.getFluid(4000)) + .outputFluids(PURIFIED_LITHIUM_BRINE.getFluid(4000)) + .EUt(VA[EV]).duration(300) + .save(provider); + + CHEMICAL_RECIPES.recipeBuilder(CTNHCore.id("lithium_sulfide")) + .inputItems(dust, Lithium, 10) + .inputItems(dust, Sulfur, 5) + .outputItems(dust, LITHIUM_SULFIDE, 15) + .EUt(VA[HV]).duration(300) + .save(provider); + + CHEMICAL_RECIPES.recipeBuilder(CTNHCore.id("phosphorus_pentasulfide")) + .inputItems(dust, Phosphorus, 2) + .inputItems(dust, Sulfur, 5) + .outputItems(dust, PHOSPHORUS_PENTASULFIDE, 7) + .EUt(VA[HV]).duration(300) + .save(provider); + + // GT dust counts: 5 Li2S + P2S5 + 2 LiCl -> 2 Li6PS5Cl (26 dust). + MIXER_RECIPES.recipeBuilder(CTNHCore.id("sulfide_electrolyte_mixture")) + .inputItems(dust, LITHIUM_SULFIDE, 15) + .inputItems(dust, PHOSPHORUS_PENTASULFIDE, 7) + .inputItems(dust, BATTERY_GRADE_LITHIUM_CHLORIDE, 4) + .outputItems(dust, SULFIDE_ELECTROLYTE_MIXTURE, 26) + .EUt(VA[EV]).duration(400) + .save(provider); + + BLAST_RECIPES.recipeBuilder(CTNHCore.id("lithium_thiophosphate_chloride_electrolyte")) + .inputItems(dust, SULFIDE_ELECTROLYTE_MIXTURE, 26) + .inputFluids(Argon.getFluid(1000)) + .outputItems(dust, LITHIUM_THIOPHOSPHATE_CHLORIDE_ELECTROLYTE, 26) + .outputFluids(Argon.getFluid(950)) + .blastFurnaceTemp(823) + .EUt(VA[IV]).duration(800) + .save(provider); + + ASSEMBLER_RECIPES.recipeBuilder(CTNHCore.id("iv_moon_solid_state_battery")) + .inputItems(GTItems.BATTERY_HULL_MEDIUM_VANADIUM) + .inputItems(dust, LITHIUM_THIOPHOSPHATE_CHLORIDE_ELECTROLYTE, 13) + .inputItems(dust, Lithium, 4) + .inputItems(dust, Vanadium, 8) + .inputItems(plate, Graphite, 4) + .inputItems(foil, Copper, 16) + .inputItems(CustomTags.EV_CIRCUITS) + .inputFluids(SiliconeRubber.getFluid(576)) + .outputItems(CTNHItems.BATTERY_IV_MOON_SOLID_STATE) + .EUt(VA[EV]).duration(400) + .save(provider); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java index 7c3cdf3b0..11214be33 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java @@ -61,6 +61,7 @@ import static com.gregtechceu.gtceu.common.data.GTMaterials.*; import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*; import static io.github.cpearl0.ctnhcore.data.materials.AviationFabricMaterials.*; +import static io.github.cpearl0.ctnhcore.data.materials.StonePowderMaterials.DEGASSED_MOON_STONE; import static io.github.cpearl0.ctnhcore.registry.CTNHBlocks.*; import static io.github.cpearl0.ctnhcore.registry.CTNHItems.*; import static io.github.cpearl0.ctnhcore.registry.material.CTNHMaterials.*; @@ -702,10 +703,11 @@ public static void init(Consumer provider) { .outputItems(dust, PlatinumSludgeResidue) .save(provider); - // 19. moon_dust: 36x moon_stone_dust -> chanced outputs + helium_3 3600. EUt 480, dur 500 + // 19. Moonstone degassing: retain the solid minerals and recover helium-3 at HV. CENTRIFUGE_RECIPES.recipeBuilder(CTNHCore.id("moon_dust")) - .EUt(480).duration(500) + .EUt(GTValues.VA[GTValues.HV]).duration(500) .inputItems(dust, Moonstone, 36) + .outputItems(dust, DEGASSED_MOON_STONE, 36) .outputFluids(Helium3.getFluid(3600)) .save(provider); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/integration/ftbchunks/TextureBlockColor.java b/src/main/java/io/github/cpearl0/ctnhcore/integration/ftbchunks/TextureBlockColor.java new file mode 100644 index 000000000..52b4565d6 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/integration/ftbchunks/TextureBlockColor.java @@ -0,0 +1,224 @@ +package io.github.cpearl0.ctnhcore.integration.ftbchunks; + +import io.github.cpearl0.ctnhcore.CTNHCore; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.SpriteContents; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; +import net.minecraftforge.client.model.data.ModelData; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import com.mojang.blaze3d.platform.NativeImage; +import dev.ftb.mods.ftbchunks.client.map.MapManager; +import dev.ftb.mods.ftbchunks.client.map.color.BlockColor; +import dev.ftb.mods.ftblibrary.icon.Color4I; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** Uses the same texture atlas and position-dependent tint inputs as world rendering. */ +@Mod.EventBusSubscriber(modid = CTNHCore.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public final class TextureBlockColor implements BlockColor { + + private static final Map TEXTURES = new ConcurrentHashMap<>(); + private static volatile Map texturePixels = Map.of(); + + private final Block block; + private final BlockColor fallback; + + public TextureBlockColor(Block block, BlockColor fallback) { + this.block = block; + this.fallback = fallback; + } + + @SubscribeEvent + public static void onTextureStitched(TextureStitchEvent.Post event) { + var atlas = event.getAtlas(); + if (!atlas.location().equals(InventoryMenu.BLOCK_ATLAS)) return; + Map snapshot = new HashMap<>(); + for (var location : atlas.getTextureLocations()) { + var contents = atlas.getSprite(location).contents(); + snapshot.put(contents, TexturePixels.copy(contents.byMipLevel[0])); + } + // Upload runs on the render thread. Publish only complete, independently owned pixel arrays. + texturePixels = Map.copyOf(snapshot); + TEXTURES.clear(); + // The model cache is replaced after the stitch event; enqueue rather than run inline. + Minecraft.getInstance().tell(() -> MapManager.getInstance().ifPresent(manager -> { + synchronized (manager.lock) { + manager.updateAllRegions(false); + } + })); + } + + @Override + public Color4I getBlockColor(BlockAndTintGetter level, BlockPos pos) { + // FTB also renders saved regions whose chunks are not loaded in the current client level. + BlockState state = level == null ? block.defaultBlockState() : level.getBlockState(pos); + if (!state.is(block)) state = block.defaultBlockState(); + var minecraft = Minecraft.getInstance(); + var fluid = state.getFluidState(); + if (!fluid.isEmpty() && state.getRenderShape() != RenderShape.MODEL) { + var properties = IClientFluidTypeExtensions.of(fluid); + var texture = level == null ? properties.getStillTexture() : properties.getStillTexture(fluid, level, pos); + var sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); + int tint = level == null ? properties.getTintColor() : properties.getTintColor(fluid, level, pos); + var samples = new Samples(); + samples.add(region(sprite), tint, 1); + return samples.weight == 0 ? fallback.getBlockColor(level, pos) : samples.color(); + } + if (state.getRenderShape() != RenderShape.MODEL) return fallback.getBlockColor(level, pos); + + var model = minecraft.getBlockRenderer().getBlockModel(state); + var data = level == null ? ModelData.EMPTY : model.getModelData(level, pos, state, ModelData.EMPTY); + long seed = state.getSeed(pos); + var random = RandomSource.create(seed); + var samples = new Samples(); + for (RenderType type : model.getRenderTypes(state, random, data)) { + random.setSeed(seed); + sampleQuads(samples, model.getQuads(state, Direction.UP, random, data, type), state, level, pos); + random.setSeed(seed); + sampleQuads(samples, model.getQuads(state, null, random, data, type), state, level, pos); + } + if (samples.weight == 0) { + int tint = minecraft.getBlockColors().getColor(state, level, pos, 0); + samples.add(region(model.getParticleIcon(data)), tint, 1); + } + return samples.weight == 0 ? fallback.getBlockColor(level, pos) : samples.color(); + } + + private static void sampleQuads(Samples samples, List quads, BlockState state, + BlockAndTintGetter level, BlockPos pos) { + for (var quad : quads) { + if (quad.getDirection() != Direction.UP) continue; + int[] vertices = quad.getVertices(); + int stride = vertices.length / 4; + double area = 0; + int red = 0, green = 0, blue = 0; + float minU = Float.POSITIVE_INFINITY, maxU = Float.NEGATIVE_INFINITY; + float minV = Float.POSITIVE_INFINITY, maxV = Float.NEGATIVE_INFINITY; + for (int i = 0; i < 4; i++) { + int a = i * stride, b = (i + 1) % 4 * stride; + area += Float.intBitsToFloat(vertices[a]) * Float.intBitsToFloat(vertices[b + 2]) - + Float.intBitsToFloat(vertices[b]) * Float.intBitsToFloat(vertices[a + 2]); + int color = vertices[a + 3]; + red += color & 255; + green += color >> 8 & 255; + blue += color >> 16 & 255; + float u = Float.intBitsToFloat(vertices[a + 4]), v = Float.intBitsToFloat(vertices[a + 5]); + minU = Math.min(minU, u); + maxU = Math.max(maxU, u); + minV = Math.min(minV, v); + maxV = Math.max(maxV, v); + } + area = Math.abs(area) * .5; + if (area == 0) continue; + var sprite = quad.getSprite(); + var contents = sprite.contents(); + int x0 = Mth.clamp( + Mth.floor((minU - sprite.getU0()) / (sprite.getU1() - sprite.getU0()) * contents.width()), + 0, contents.width() - 1); + int x1 = Mth.clamp(Mth.ceil((maxU - sprite.getU0()) / (sprite.getU1() - sprite.getU0()) * contents.width()), + x0 + 1, contents.width()); + int y0 = Mth.clamp( + Mth.floor((minV - sprite.getV0()) / (sprite.getV1() - sprite.getV0()) * contents.height()), + 0, contents.height() - 1); + int y1 = Mth.clamp( + Mth.ceil((maxV - sprite.getV0()) / (sprite.getV1() - sprite.getV0()) * contents.height()), + y0 + 1, contents.height()); + int tint = quad.isTinted() ? + Minecraft.getInstance().getBlockColors().getColor(state, level, pos, quad.getTintIndex()) : -1; + int combinedTint = Math.round((float) (tint >> 16 & 255) * red / 1020) << 16 | + Math.round((float) (tint >> 8 & 255) * green / 1020) << 8 | + Math.round((float) (tint & 255) * blue / 1020); + samples.add(new TextureRegion(contents, x0, y0, x1, y1), combinedTint, area); + } + } + + private static TextureRegion region(TextureAtlasSprite sprite) { + var contents = sprite.contents(); + return new TextureRegion(contents, 0, 0, contents.width(), contents.height()); + } + + private record TextureRegion(SpriteContents contents, int minX, int minY, int maxX, int maxY) { + + private TextureColor average() { + var image = texturePixels.get(contents); + // During model replacement an old quad can outlive its atlas; use the original map color. + if (image == null) return new TextureColor(0, 0, 0, 0); + long red = 0, green = 0, blue = 0, alpha = 0, pixels = 0; + // Average the animation sheet; model UVs refer to a single frame's region. + for (int frameY = 0; frameY < image.height; frameY += contents.height()) { + for (int frameX = 0; frameX < image.width; frameX += contents.width()) { + for (int y = minY; y < maxY; y++) { + for (int x = minX; x < maxX; x++) { + int rgba = image.rgba[(frameY + y) * image.width + frameX + x]; + int a = rgba >>> 24; + // NativeImage exposes ABGR integers, unlike BlockColors' RGB tint. + red += (long) (rgba & 255) * a; + green += (long) (rgba >> 8 & 255) * a; + blue += (long) (rgba >> 16 & 255) * a; + alpha += a; + pixels++; + } + } + } + } + return alpha == 0 ? new TextureColor(0, 0, 0, 0) : + new TextureColor((double) red / alpha, (double) green / alpha, (double) blue / alpha, + (double) alpha / (pixels * 255)); + } + } + + private record TexturePixels(int width, int height, int[] rgba) { + + private static TexturePixels copy(NativeImage image) { + int width = image.getWidth(), height = image.getHeight(); + int[] rgba = new int[width * height]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + rgba[y * width + x] = image.getPixelRGBA(x, y); + } + } + return new TexturePixels(width, height, rgba); + } + } + + private record TextureColor(double red, double green, double blue, double coverage) {} + + private static final class Samples { + + private double red, green, blue, weight; + + private void add(TextureRegion region, int tint, double area) { + var texture = TEXTURES.computeIfAbsent(region, TextureRegion::average); + double contribution = texture.coverage * area; + red += texture.red * (tint >> 16 & 255) / 255 * contribution; + green += texture.green * (tint >> 8 & 255) / 255 * contribution; + blue += texture.blue * (tint & 255) / 255 * contribution; + weight += contribution; + } + + private Color4I color() { + return Color4I.rgb((int) Math.round(red / weight), (int) Math.round(green / weight), + (int) Math.round(blue / weight)); + } + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/mixin/ftbchunks/ColorMapLoaderMixin.java b/src/main/java/io/github/cpearl0/ctnhcore/mixin/ftbchunks/ColorMapLoaderMixin.java new file mode 100644 index 000000000..77badd551 --- /dev/null +++ b/src/main/java/io/github/cpearl0/ctnhcore/mixin/ftbchunks/ColorMapLoaderMixin.java @@ -0,0 +1,30 @@ +package io.github.cpearl0.ctnhcore.mixin.ftbchunks; + +import io.github.cpearl0.ctnhcore.integration.ftbchunks.TextureBlockColor; + +import net.minecraft.world.level.block.Block; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import dev.ftb.mods.ftbchunks.ColorMapLoader; +import dev.ftb.mods.ftbchunks.client.map.color.BlockColor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Map; + +@Mixin(value = ColorMapLoader.class, remap = false) +public class ColorMapLoaderMixin { + + // FTB Chunks 2001.3.6: only the default MapColor branch, before explicit resource-pack overrides. + @WrapOperation(method = "apply(Lcom/google/gson/JsonObject;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", + at = @At(value = "INVOKE", + target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + ordinal = 5)) + private Object ctnhcore$sampleRenderedSurface(Map colors, Object id, Object color, + Operation original, @Local Block block) { + // FTB's CustomBlockColor fast path skips getBlockColor(level, pos); use the dynamic interface. + return original.call(colors, id, new TextureBlockColor(block, (BlockColor) color)); + } +} diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHItems.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHItems.java index 5d73c4207..03f8583de 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHItems.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/CTNHItems.java @@ -11,6 +11,7 @@ import com.gregtechceu.gtceu.api.data.chemical.material.stack.ItemMaterialInfo; import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack; import com.gregtechceu.gtceu.api.item.ComponentItem; +import com.gregtechceu.gtceu.api.item.component.ElectricStats; import com.gregtechceu.gtceu.api.item.component.FoodStats; import com.gregtechceu.gtceu.api.item.component.IInteractionItem; import com.gregtechceu.gtceu.common.data.models.GTModels; @@ -33,6 +34,7 @@ import net.minecraft.world.item.Items; import net.minecraft.world.item.Rarity; import net.minecraft.world.level.Level; +import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.registries.ForgeRegistries; import com.ctnhlang.CN; @@ -45,6 +47,7 @@ import static com.gregtechceu.gtceu.common.data.GTItems.attach; import static com.gregtechceu.gtceu.common.data.GTItems.materialInfo; +import static com.gregtechceu.gtceu.common.data.GTItems.modelPredicate; import static com.gregtechceu.gtceu.common.data.GTMachines.CREATIVE_TOOLTIPS; import static io.github.cpearl0.ctnhcore.data.materials.BedrockMaterials.ADAMANTITE; import static io.github.cpearl0.ctnhcore.data.materials.BedrockMaterials.SAMARIUM_DYSPROSIUM_TERBIUM_PERMANENT_MAGNET_ALLOY_MAGNETIC; @@ -229,6 +232,22 @@ private static void registerGeneralCircuits() { .cnlang("完善的一阶航天数据芯片") .lang("Great Astronomy Circuit I") .register(); + public static ItemEntry BATTERY_IV_MOON_SOLID_STATE = REGISTRATE + .item("iv_moon_solid_state_battery", ComponentItem::create) + .cnlang("IV月海固态电池").lang("IV Moon Solid State Battery") + .model((ctx, prov) -> { + var model = prov.generated(ctx, GTCEu.id("item/iv_vanadium_battery/1")); + for (int i = 0; i < 8; i++) { + model.override().predicate(GTCEu.id("battery"), i / 100f) + .model(new ModelFile.UncheckedModelFile(GTCEu.id("item/iv_vanadium_battery/" + i))) + .end(); + } + }) + .onRegister(modelPredicate(GTCEu.id("battery"), ElectricStats::getStoredPredicate)) + .onRegister(attach(ElectricStats.createRechargeableBattery(81_920_000L, GTValues.IV))) + .tag(CustomTags.IV_BATTERIES) + .register(); + public static ItemEntry SIMPLE_NUTRITIOUS_MEAL = REGISTRATE .item("simple_nutritious_meal", ComponentItem::create) .cnlang("简易营养餐") diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/material/CTNHMaterials.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/material/CTNHMaterials.java index 431661a7a..30213b063 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/material/CTNHMaterials.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/material/CTNHMaterials.java @@ -982,6 +982,7 @@ public static void init() { NiobiumTantalumJointProcessingMaterials.init(); PitchblendeRefiningMaterials.init(); RareEarthMaterials.init(); + MoonBrineMaterials.init(); StonePowderMaterials.init(); YeastRelatedMaterials.init(); ZrHfSeparationMaterials.init(); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/material/GTMaterialAddon.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/material/GTMaterialAddon.java index 725e3d40e..8d4de92bd 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/material/GTMaterialAddon.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/material/GTMaterialAddon.java @@ -23,6 +23,7 @@ public static HazardProperty radioactive(float multiplier) { } public static void init() { + Graphite.addFlags(GENERATE_PLATE); Duranium.addFlags(GENERATE_FRAME); Naquadria.addFlags(GENERATE_FRAME); NaquadahEnriched.addFlags(GENERATE_FRAME); diff --git a/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java index d3fc0f6c1..1682bb66e 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/registry/ores/MoonOres.java @@ -18,7 +18,6 @@ import java.util.Map; import java.util.function.Supplier; -import static com.gregtechceu.gtceu.api.data.worldgen.generator.indicators.SurfaceIndicatorGenerator.IndicatorPlacement.ABOVE; import static io.github.cpearl0.ctnhcore.registry.CTNHOres.create; import static io.github.cpearl0.ctnhcore.registry.CTNHWorlds.MOON; @@ -52,10 +51,7 @@ public static void init() { .layer(l -> l.weight(3).mat(GTMaterials.Bornite).size(2, 4)) .layer(l -> l.weight(2).mat(GTMaterials.Cooperite).size(1, 1)) .layer(l -> l.weight(2).mat(PlatinumLineMaterials.PlatinumOre).size(1, 1)) - .layer(l -> l.weight(1).mat(PlatinumLineMaterials.PalladiumOre).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(PlatinumLineMaterials.PlatinumOre) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(PlatinumLineMaterials.PalladiumOre).size(1, 1))))); create("phosphate_vein", "Phosphate Vein", "磷酸盐矿脉", vein -> vein.clusterSize(30) @@ -67,10 +63,7 @@ public static void init() { .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(GTMaterials.Apatite).size(2, 4)) .layer(l -> l.weight(2).mat(GTMaterials.TricalciumPhosphate).size(1, 3)) - .layer(l -> l.weight(2).mat(CTNHMaterials.TrisodiumPhosphate).size(1, 2)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(CTNHMaterials.TrisodiumPhosphate) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(2).mat(CTNHMaterials.TrisodiumPhosphate).size(1, 2))))); create("bauxite_vein", "Moon Bauxite Vein", "月球铝土矿脉", vein -> vein.clusterSize(36) @@ -82,10 +75,7 @@ public static void init() { .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(2).mat(GTMaterials.Bauxite).size(1, 4)) .layer(l -> l.weight(1).mat(GTMaterials.Ilmenite).size(1, 2)) - .layer(l -> l.weight(1).mat(CTNHMaterials.Alumina).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Bauxite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(CTNHMaterials.Alumina).size(1, 1))))); create("ilmenite_vein", "Ilmenite Vein", "钛铁矿脉", vein -> vein.clusterSize(24) @@ -99,10 +89,7 @@ public static void init() { .layer(l -> l.weight(3).mat(GTMaterials.Ilmenite).size(1, 4)) .layer(l -> l.weight(2).mat(GTMaterials.Chromite).size(1, 4)) .layer(l -> l.weight(2).mat(GTMaterials.Uvarovite).size(1, 2)) - .layer(l -> l.weight(1).mat(GTMaterials.Perlite).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Ilmenite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Perlite).size(1, 1))))); create("desh_vein_ad", "Moon Desh Vein", "月球戴斯矿脉", vein -> vein.clusterSize(24) @@ -113,10 +100,7 @@ public static void init() { .layeredVeinGenerator(generator -> generator .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(AdastraMaterials.Desh).size(2, 3)) - .layer(l -> l.weight(1).mat(CTNHMaterials.ArcaneCrystal).size(1, 2)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(AdastraMaterials.Desh) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(CTNHMaterials.ArcaneCrystal).size(1, 2))))); create("monazite_vein_moon", "Moon Monazite Vein", "月球独居石矿脉", vein -> vein.clusterSize(24) @@ -128,10 +112,7 @@ public static void init() { .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(GTMaterials.Bastnasite).size(2, 4)) .layer(l -> l.weight(1).mat(GTMaterials.Monazite).size(1, 1)) - .layer(l -> l.weight(1).mat(GTMaterials.Neodymium).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Monazite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Neodymium).size(1, 1))))); create("quartzite_vein_moon", "Moon Quartzite Vein", "月球石英岩矿脉", vein -> vein.clusterSize(24) @@ -143,10 +124,7 @@ public static void init() { .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(GTMaterials.Quartzite).size(2, 4)) .layer(l -> l.weight(3).mat(GTMaterials.Barite).size(2, 4)) - .layer(l -> l.weight(3).mat(GTMaterials.CertusQuartz).size(2, 4)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Quartzite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(3).mat(GTMaterials.CertusQuartz).size(2, 4))))); create("molybdenum_vein_moon", "Moon Molybdenite Vein", "月球辉钼矿脉", vein -> vein.clusterSize(25) @@ -159,10 +137,7 @@ public static void init() { .layer(l -> l.weight(3).mat(GTMaterials.Wulfenite).size(2, 4)) .layer(l -> l.weight(2).mat(GTMaterials.Molybdenite).size(1, 1)) .layer(l -> l.weight(1).mat(GTMaterials.Molybdenum).size(1, 1)) - .layer(l -> l.weight(1).mat(GTMaterials.Powellite).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Molybdenite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Powellite).size(1, 1))))); create("galena_vein_moon", "Moon Galena Vein", "月球方铅矿脉", vein -> vein.clusterSize(30) @@ -174,10 +149,7 @@ public static void init() { .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(GTMaterials.Galena).size(2, 4)) .layer(l -> l.weight(2).mat(GTMaterials.Silver).size(1, 1)) - .layer(l -> l.weight(1).mat(GTMaterials.Lead).size(1, 1)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Galena) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Lead).size(1, 1))))); create("copper_vein_moon", "Moon Copper Vein", "月球铜矿脉", vein -> vein.clusterSize(36) @@ -190,10 +162,7 @@ public static void init() { .layer(l -> l.weight(2).mat(GTMaterials.Chalcopyrite).size(2, 3)) .layer(l -> l.weight(1).mat(GTMaterials.Iron).size(1, 2)) .layer(l -> l.weight(1).mat(GTMaterials.Pyrite).size(1, 2)) - .layer(l -> l.weight(1).mat(GTMaterials.Copper).size(1, 2)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Chalcopyrite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Copper).size(1, 2))))); create("cassiterite_vein_moon", "Moon Cassiterite Vein", "月球锡石矿脉", vein -> vein.clusterSize(36) @@ -204,9 +173,6 @@ public static void init() { .layeredVeinGenerator(generator -> generator .buildLayerPattern(pattern -> pattern .layer(l -> l.weight(3).mat(GTMaterials.Tin).size(2, 3)) - .layer(l -> l.weight(1).mat(GTMaterials.Cassiterite).size(1, 2)))) - .surfaceIndicatorGenerator(indicator -> indicator - .surfaceRock(GTMaterials.Cassiterite) - .placement(ABOVE).density(0.4F).radius(5))); + .layer(l -> l.weight(1).mat(GTMaterials.Cassiterite).size(1, 2))))); } } diff --git a/src/main/resources/ctnhcore.mixins.json b/src/main/resources/ctnhcore.mixins.json index b30b80d21..d98ff39df 100644 --- a/src/main/resources/ctnhcore.mixins.json +++ b/src/main/resources/ctnhcore.mixins.json @@ -44,6 +44,7 @@ "vintageimprovements.LatheMovingBlockMixin" ], "client": [ + "ftbchunks.ColorMapLoaderMixin", "legendarysurvival.ClientTemperatureEffectsMixin", "creatediesel.DistillationCategoryMixin", "emi.JemiRecipeMixin", From 64387580b15a23db90d6091ef9605c5fa15be101 Mon Sep 17 00:00:00 2001 From: ShenShang <16601765+daijugui@user.noreply.gitee.com> Date: Sat, 17 Oct 2026 00:31:35 -0700 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=E4=BF=9D=E7=95=99=E4=B8=8A=E6=B8=B8?= =?UTF-8?q?=E6=9C=88=E7=9F=B3=E7=A6=BB=E5=BF=83=E9=85=8D=E6=96=B9=E7=9A=84?= =?UTF-8?q?=E7=9F=BF=E7=89=A9=E4=BA=A7=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 采用上游恢复的六种概率矿物产物与氦-3输出,移除脱气月石的独立材料定义及生成语言条目。 --- .../resources/assets/ctnhcore/lang/en_ud.json | 1 - .../resources/assets/ctnhcore/lang/en_us.json | 1 - .../resources/assets/ctnhcore/lang/zh_cn.json | 1 - .../data/materials/StonePowderMaterials.java | 11 ----------- .../data/recipe/migrated/GtceuScriptRecipes.java | 13 +++++++++---- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/generated/resources/assets/ctnhcore/lang/en_ud.json b/src/generated/resources/assets/ctnhcore/lang/en_ud.json index 46d5e8840..dd7416e24 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_ud.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_ud.json @@ -1518,7 +1518,6 @@ "material.ctnhcore.cyanide_tailings": "sbuıןıɐ⟘ ǝpıuɐʎƆ", "material.ctnhcore.dark_steel": "ןǝǝʇS ʞɹɐᗡ", "material.ctnhcore.debrominated_water": "ɹǝʇɐM pǝʇɐuıɯoɹqǝᗡ", - "material.ctnhcore.degassed_moon_stone": "ǝuoʇS uooW pǝssɐbǝᗡ", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "uoıʇnןoS ɯnıpɐןןɐԀ ɯnuıʇɐןԀ pןo⅁ pǝʇɐɹʇıuǝᗡ", "material.ctnhcore.dense_hydrazine_mixed_fuel": "ןǝnℲ pǝxıW ǝuızɐɹpʎH ǝsuǝᗡ", "material.ctnhcore.desh": "ɥsǝᗡ", diff --git a/src/generated/resources/assets/ctnhcore/lang/en_us.json b/src/generated/resources/assets/ctnhcore/lang/en_us.json index f960d3fff..b3d72d8d8 100644 --- a/src/generated/resources/assets/ctnhcore/lang/en_us.json +++ b/src/generated/resources/assets/ctnhcore/lang/en_us.json @@ -1518,7 +1518,6 @@ "material.ctnhcore.cyanide_tailings": "Cyanide Tailings", "material.ctnhcore.dark_steel": "Dark Steel", "material.ctnhcore.debrominated_water": "Debrominated Water", - "material.ctnhcore.degassed_moon_stone": "Degassed Moon Stone", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "Denitrated Gold Platinum Palladium Solution", "material.ctnhcore.dense_hydrazine_mixed_fuel": "Dense Hydrazine Mixed Fuel", "material.ctnhcore.desh": "Desh", diff --git a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json index 785ff6b10..b71249e7c 100644 --- a/src/generated/resources/assets/ctnhcore/lang/zh_cn.json +++ b/src/generated/resources/assets/ctnhcore/lang/zh_cn.json @@ -1586,7 +1586,6 @@ "material.ctnhcore.cyanide_tailings": "氰化尾渣", "material.ctnhcore.dark_steel": "玄钢", "material.ctnhcore.debrominated_water": "脱溴盐水", - "material.ctnhcore.degassed_moon_stone": "脱气月石", "material.ctnhcore.denitrated_gold_platinum_palladium_solution": "除硝金-铂-钯酸性溶液", "material.ctnhcore.dense_hydrazine_mixed_fuel": "浓缩肼混合燃料", "material.ctnhcore.desh": "戴斯", diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java index 57fafc2b1..bc95a00ca 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/materials/StonePowderMaterials.java @@ -16,7 +16,6 @@ public class StonePowderMaterials { public static Material DIRTY_HEXAFLUOROSILICIC_ACID; public static Material DILUTE_HEXAFLUOROSILICIC_ACID; public static Material STONE_RESIDUE; - public static Material DEGASSED_MOON_STONE; public static Material MOON_ANORTHOSITE; public static Material FLUOROSILICIC_ACID; public static Material UNCOMMON_RESIDUES; @@ -59,16 +58,6 @@ public static void init() { .color(0xA1A19E) .buildAndRegister(); - // GT generates the LV mineral separation recipe; gas-bearing Moonstone remains a separate material. - // Keep Moonstone's ROUGH texture and neutral greys, darkened equally for the processed state. - DEGASSED_MOON_STONE = REGISTRATE.material(CTNHCore.id("degassed_moon_stone")) - .cnlang("脱气月石") - .dust() - .color(0x9B9B9B).secondaryColor(0x656565).iconSet(ROUGH) - .components(SiliconDioxide, 20, Alumina, 8, Quicklime, 4, Magnesia, 3, Ilmenite, 1) - .flags(DECOMPOSITION_BY_CENTRIFUGING) - .buildAndRegister(); - // Simplify anorthite-rich lunar rock into oxide groups for GT's generated mineral separation. MOON_ANORTHOSITE = REGISTRATE.material(CTNHCore.id("moon_anorthosite")) .cnlang("月球斜长岩") diff --git a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java index 11214be33..1b50743da 100644 --- a/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java +++ b/src/main/java/io/github/cpearl0/ctnhcore/data/recipe/migrated/GtceuScriptRecipes.java @@ -61,7 +61,6 @@ import static com.gregtechceu.gtceu.common.data.GTMaterials.*; import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*; import static io.github.cpearl0.ctnhcore.data.materials.AviationFabricMaterials.*; -import static io.github.cpearl0.ctnhcore.data.materials.StonePowderMaterials.DEGASSED_MOON_STONE; import static io.github.cpearl0.ctnhcore.registry.CTNHBlocks.*; import static io.github.cpearl0.ctnhcore.registry.CTNHItems.*; import static io.github.cpearl0.ctnhcore.registry.material.CTNHMaterials.*; @@ -703,11 +702,17 @@ public static void init(Consumer provider) { .outputItems(dust, PlatinumSludgeResidue) .save(provider); - // 19. Moonstone degassing: retain the solid minerals and recover helium-3 at HV. + // 19. moon_dust: 36x moon_stone_dust -> chanced outputs + helium_3 3600. EUt 480, dur 500 CENTRIFUGE_RECIPES.recipeBuilder(CTNHCore.id("moon_dust")) - .EUt(GTValues.VA[GTValues.HV]).duration(500) + .EUt(480).duration(500) .inputItems(dust, Moonstone, 36) - .outputItems(dust, DEGASSED_MOON_STONE, 36) + .chancedOutput(dust, SiliconDioxide, 32, 5000, 1000) + .chancedOutput(dust, RareEarth, 24, 3000, 1000) + .chancedOutput(dust, Olivine, 16, 2000, 1000) + .chancedOutput(dust, Manganese, 16, 1000, 1000) + .chancedOutput(dust, Scheelite, 12, 800, 1000) + // 铂金矿粉是 CTNH 在 PlatinumLineMaterials 里注册的材质,没有 gtceu:platinum_ore_dust + .chancedOutput(dust, PlatinumLineMaterials.PlatinumOre, 8, 400, 1000) .outputFluids(Helium3.getFluid(3600)) .save(provider);