diff --git a/dependencies.gradle b/dependencies.gradle index 4a6d7671e75..47526ef4efd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -90,6 +90,7 @@ dependencies { clientLocalRuntime(forge.sodium.impl) sodiumShellSource(forge.sodium.full) clientLocalRuntime(files(tasks.named('stripSodiumShellLib'))) +// clientLocalRuntime(forge.embeddium) clientLocalRuntime(forge.fabricApi.base) clientLocalRuntime(forge.fabricApi.rendering) diff --git a/gradle/scripts/moddevgradle.gradle b/gradle/scripts/moddevgradle.gradle index fc9e77cadb5..e01a3bd4a23 100644 --- a/gradle/scripts/moddevgradle.gradle +++ b/gradle/scripts/moddevgradle.gradle @@ -167,6 +167,14 @@ neoForge { // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels logLevel = org.slf4j.event.Level.INFO + // enable additional mixin validation + systemProperty 'mixin.debug.verify', 'true' + // systemProperty 'mixin.debug.countInjections', 'true' // can't have this, dependencies are lazy + systemProperty 'mixin.debug.strict.unique', 'true' + systemProperty 'mixin.checks', 'true' + // enable mixin hotswapping + systemProperty 'mixin.hotSwap', 'true' + // Disable JOML using scientific notation for its types' toString() outputs systemProperty 'joml.format', 'false' } diff --git a/src/generated/resources/assets/gtceu/blockstates/creosote.json b/src/generated/resources/assets/gtceu/blockstates/creosote.json deleted file mode 100644 index 6007668dbc2..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/creosote.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/creosote" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/heavy_oil.json b/src/generated/resources/assets/gtceu/blockstates/heavy_oil.json deleted file mode 100644 index 9e116b8ab0e..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/heavy_oil.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/heavy_oil" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/light_oil.json b/src/generated/resources/assets/gtceu/blockstates/light_oil.json deleted file mode 100644 index 63e296f72a5..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/light_oil.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/light_oil" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/natural_gas.json b/src/generated/resources/assets/gtceu/blockstates/natural_gas.json deleted file mode 100644 index 17c5f96c5ab..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/natural_gas.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/natural_gas" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/oil.json b/src/generated/resources/assets/gtceu/blockstates/oil.json deleted file mode 100644 index 29b7074d155..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/oil.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/oil" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/blockstates/raw_oil.json b/src/generated/resources/assets/gtceu/blockstates/raw_oil.json deleted file mode 100644 index 3f8268e5b27..00000000000 --- a/src/generated/resources/assets/gtceu/blockstates/raw_oil.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "variants": { - "": { - "model": "gtceu:block/raw_oil" - } - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 95ba0e036c6..73c936b63f6 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -199,7 +199,6 @@ "block.gtceu.creative_data_access_hatch": "ɥɔʇɐH ssǝɔɔⱯ ɐʇɐᗡ ǝʌıʇɐǝɹƆ", "block.gtceu.creative_energy": "ʎbɹǝuƎ ǝʌıʇɐǝɹƆ", "block.gtceu.creative_tank": "ʞuɐ⟘ ǝʌıʇɐǝɹƆ", - "block.gtceu.creosote": "ǝʇosoǝɹƆ", "block.gtceu.crushing_wheels": "sןǝǝɥM buıɥsnɹƆ", "block.gtceu.ctm_test": "ʞɔoןᗺ ʇsǝ⟘ ǝɹnʇxǝ⟘ pǝʇɔǝuuoƆ", "block.gtceu.cupronickel_coil_block": "ʞɔoןᗺ ןıoƆ ןǝʞɔıuoɹdnƆ", @@ -344,7 +343,6 @@ "block.gtceu.gregification_hazard_sign_block": "ʞɔoןᗺ ubıS pɹɐzɐH uoıʇɐɔıɟıbǝɹ⅁", "block.gtceu.heat_vent": "ʇuǝΛ ʇɐǝH", "block.gtceu.heatproof_machine_casing": "buısɐƆ ǝuıɥɔɐW ɹɐʌuI ɟooɹԀ ʇɐǝH", - "block.gtceu.heavy_oil": "ןıO ʎʌɐǝH", "block.gtceu.high_performance_computation_array": ")ⱯƆԀH( ʎɐɹɹⱯ uoıʇɐʇndɯoƆ ǝɔuɐɯɹoɟɹǝԀ ɥbıH", "block.gtceu.high_power_casing": "buısɐƆ ɹǝʍoԀ ɥbıH", "block.gtceu.high_pressure_hazard_sign_block": "ʞɔoןᗺ ubıS pɹɐzɐH ǝɹnssǝɹԀ ɥbıH", @@ -588,7 +586,6 @@ "block.gtceu.light_gray_large_metal_sheet": "ʇǝǝɥS ןɐʇǝW ǝbɹɐꞀ ʎɐɹ⅁ ʇɥbıꞀ", "block.gtceu.light_gray_metal_sheet": "ʇǝǝɥS ןɐʇǝW ʎɐɹ⅁ ʇɥbıꞀ", "block.gtceu.light_gray_studs": "spnʇS ʎɐɹ⅁ ʇɥbıꞀ", - "block.gtceu.light_oil": "ןıO ʇɥbıꞀ", "block.gtceu.lime_borderless_lamp": "dɯɐꞀ ssǝןɹǝpɹoᗺ ǝɯıꞀ", "block.gtceu.lime_lamp": "dɯɐꞀ ǝɯıꞀ", "block.gtceu.lime_large_metal_sheet": "ʇǝǝɥS ןɐʇǝW ǝbɹɐꞀ ǝɯıꞀ", @@ -924,7 +921,6 @@ "block.gtceu.mv_wiremill": "ɹ§ ןןıɯǝɹıM pǝɔuɐʌpⱯq§", "block.gtceu.mv_world_accelerator": "ɹ§ ɹoʇɐɹǝןǝɔɔⱯ pןɹoM pǝɔuɐʌpⱯq§", "block.gtceu.naquadah_coil_block": "ʞɔoןᗺ ןıoƆ ɥɐpɐnbɐN", - "block.gtceu.natural_gas": "sɐ⅁ ןɐɹnʇɐN", "block.gtceu.network_switch": "ɥɔʇıʍS ʞɹoʍʇǝN", "block.gtceu.nichrome_coil_block": "ʞɔoןᗺ ןıoƆ ǝɯoɹɥɔıN", "block.gtceu.noise_hazard_sign_block": "ʞɔoןᗺ ubıS pɹɐzɐH ǝsıoN", @@ -935,10 +931,6 @@ "block.gtceu.normal_optical_pipe": "ǝןqɐƆ ɹǝqıℲ ןɐɔıʇdO", "block.gtceu.normal_optical_pipe.tooltip": "ㄥ§ɐʇɐᗡ ɥɔɹɐǝsǝᴚɟ§ ɹo ㄥ§uoıʇɐʇndɯoƆɟ§ buıʇʇıɯsuɐɹ⟘ㄥ§", "block.gtceu.object_holder": "ɹǝpןoH ʇɔǝظqO", - "block.gtceu.oil": "ןıO", - "block.gtceu.oil_heavy": "ןıO ʎʌɐǝH", - "block.gtceu.oil_light": "ןıO ʇɥbıꞀ", - "block.gtceu.oil_medium": "ןıO ʍɐᴚ", "block.gtceu.opv_1024a_laser_source_hatch": "ɥɔʇɐH ǝɔɹnoS ɹǝsɐꞀ ɹ§Ɐǝ§ㄣᄅ0'Ɩ ɹ§ΛdOן§6§", "block.gtceu.opv_1024a_laser_target_hatch": "ɥɔʇɐH ʇǝbɹɐ⟘ ɹǝsɐꞀ ɹ§Ɐǝ§ㄣᄅ0'Ɩ ɹ§ΛdOן§6§", "block.gtceu.opv_16a_energy_converter": "ɹǝʇɹǝʌuoƆ ʎbɹǝuƎ ɹ§Ɐǝ§9Ɩ ɹ§ΛdOן§6§", @@ -1061,7 +1053,6 @@ "block.gtceu.purple_studs": "spnʇS ǝןdɹnԀ", "block.gtceu.pyrolyse_oven": "uǝʌO ǝsʎןoɹʎԀ", "block.gtceu.radioactive_hazard_sign_block": "ʞɔoןᗺ ubıS pɹɐzɐH ǝʌıʇɔɐoıpɐᴚ", - "block.gtceu.raw_oil": "ןıO ʍɐᴚ", "block.gtceu.reaction_safe_mixing_casing": "buısɐƆ buıxıW ǝɟɐS-uoıʇɔɐǝᴚ", "block.gtceu.red_borderless_lamp": "dɯɐꞀ ssǝןɹǝpɹoᗺ pǝᴚ", "block.gtceu.red_granite": "ǝʇıuɐɹ⅁ pǝᴚ", @@ -1153,6 +1144,7 @@ "block.gtceu.substation_capacitor.tooltip_empty": "uoıʇɐʇsqnS ɹǝʍoԀ ɹnoʎ uı ǝɔɐds buıןןıɟ ɹoℲㄥ§", "block.gtceu.substation_capacitor.tooltip_filled": "∩Ǝ %dɟ§ :ʎʇıɔɐdɐƆ ʎbɹǝuƎɔ§", "block.gtceu.superconducting_coil": "ʞɔoןᗺ ןıoƆ buıʇɔnpuoɔɹǝdnS", + "block.gtceu.surface_rock": "ʞɔoᴚ ǝɔɐɟɹnS %s", "block.gtceu.tempered_glass": "ssɐן⅁ pǝɹǝdɯǝ⟘", "block.gtceu.test_mui": "ınW ʇsǝ⟘", "block.gtceu.the_end_marker": "puƎ ǝɥ⟘", @@ -1743,7 +1735,6 @@ "block.gtceu.zpm_transformer_4a": "ɹǝɯɹoɟsuɐɹ⟘ )xㄣ( dɯⱯ-ıH ɹ§ǝbɐʇןoΛ WԀZɔ§", "block.gtceu.zpm_wiremill": "ɹ§III ןןıɯǝɹıM ǝʇıןƎɔ§", "block.gtceu.zpm_world_accelerator": "ɹ§III ɹoʇɐɹǝןǝɔɔⱯ pןɹoM ǝʇıןƎɔ§", - "block.gtceu.surface_rock": "ʞɔoᴚ ǝɔɐɟɹnS %s", "button.gtceu.mark_as_depleted.name": "pǝʇǝןdǝᗡ sɐ ʞɹɐW", "button.gtceu.toggle_waypoint.name": "ʇuıodʎɐM ǝןbbo⟘", "command.gtceu.cape.failure.does_not_exist": "ʇsıxǝ ʇou sǝop %s ǝdɐƆ", @@ -1837,6 +1828,7 @@ "config.gtceu.option.flintAndSteelRequireSteel": "ןǝǝʇSǝɹınbǝᴚןǝǝʇSpuⱯʇuıןɟ", "config.gtceu.option.ftbChunksIntegration": "uoıʇɐɹbǝʇuIsʞunɥƆqʇɟ", "config.gtceu.option.gameplay": "ʎɐןdǝɯɐb", + "config.gtceu.option.gasesVaporizeOnPlacement": "ʇuǝɯǝɔɐןԀuOǝzıɹodɐΛsǝsɐb", "config.gtceu.option.generateLowQualityGems": "sɯǝ⅁ʎʇıןɐnὉʍoꞀǝʇɐɹǝuǝb", "config.gtceu.option.ghostCircuit": "ʇınɔɹıƆʇsoɥb", "config.gtceu.option.gt6StylePipesCables": "sǝןqɐƆsǝdıԀǝןʎʇS9ʇb", @@ -1873,6 +1865,8 @@ "config.gtceu.option.ldFluidPipeMinDistance": "ǝɔuɐʇsıᗡuıWǝdıԀpınןℲpן", "config.gtceu.option.ldItemPipeMinDistance": "ǝɔuɐʇsıᗡuıWǝdıԀɯǝʇIpן", "config.gtceu.option.liquidBoilerBaseOutput": "ʇndʇnOǝsɐᗺɹǝןıoᗺpınbıן", + "config.gtceu.option.lowDensityFluidsFlowUp": "d∩ʍoןℲspınןℲʎʇısuǝᗡʍoן", + "config.gtceu.option.lowDensityFluidsRenderUpsideDown": "uʍoᗡǝpısd∩ɹǝpuǝᴚspınןℲʎʇısuǝᗡʍoן", "config.gtceu.option.maceratorRecyclingYield": "pןǝıʎbuıןɔʎɔǝᴚɹoʇɐɹǝɔɐɯ", "config.gtceu.option.machineSounds": "spunoSǝuıɥɔɐɯ", "config.gtceu.option.machines": "sǝuıɥɔɐɯ", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 44b7f4a6f0c..9bbb597ef16 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -199,7 +199,6 @@ "block.gtceu.creative_data_access_hatch": "Creative Data Access Hatch", "block.gtceu.creative_energy": "Creative Energy", "block.gtceu.creative_tank": "Creative Tank", - "block.gtceu.creosote": "Creosote", "block.gtceu.crushing_wheels": "Crushing Wheels", "block.gtceu.ctm_test": "Connected Texture Test Block", "block.gtceu.cupronickel_coil_block": "Cupronickel Coil Block", @@ -344,7 +343,6 @@ "block.gtceu.gregification_hazard_sign_block": "Gregification Hazard Sign Block", "block.gtceu.heat_vent": "Heat Vent", "block.gtceu.heatproof_machine_casing": "Heat Proof Invar Machine Casing", - "block.gtceu.heavy_oil": "Heavy Oil", "block.gtceu.high_performance_computation_array": "High Performance Computation Array (HPCA)", "block.gtceu.high_power_casing": "High Power Casing", "block.gtceu.high_pressure_hazard_sign_block": "High Pressure Hazard Sign Block", @@ -588,7 +586,6 @@ "block.gtceu.light_gray_large_metal_sheet": "Light Gray Large Metal Sheet", "block.gtceu.light_gray_metal_sheet": "Light Gray Metal Sheet", "block.gtceu.light_gray_studs": "Light Gray Studs", - "block.gtceu.light_oil": "Light Oil", "block.gtceu.lime_borderless_lamp": "Lime Borderless Lamp", "block.gtceu.lime_lamp": "Lime Lamp", "block.gtceu.lime_large_metal_sheet": "Lime Large Metal Sheet", @@ -924,7 +921,6 @@ "block.gtceu.mv_wiremill": "§bAdvanced Wiremill §r", "block.gtceu.mv_world_accelerator": "§bAdvanced World Accelerator §r", "block.gtceu.naquadah_coil_block": "Naquadah Coil Block", - "block.gtceu.natural_gas": "Natural Gas", "block.gtceu.network_switch": "Network Switch", "block.gtceu.nichrome_coil_block": "Nichrome Coil Block", "block.gtceu.noise_hazard_sign_block": "Noise Hazard Sign Block", @@ -935,10 +931,6 @@ "block.gtceu.normal_optical_pipe": "Optical Fiber Cable", "block.gtceu.normal_optical_pipe.tooltip": "§7Transmitting §fComputation§7 or §fResearch Data§7", "block.gtceu.object_holder": "Object Holder", - "block.gtceu.oil": "Oil", - "block.gtceu.oil_heavy": "Heavy Oil", - "block.gtceu.oil_light": "Light Oil", - "block.gtceu.oil_medium": "Raw Oil", "block.gtceu.opv_1024a_laser_source_hatch": "§9§lOpV§r 1,024§eA§r Laser Source Hatch", "block.gtceu.opv_1024a_laser_target_hatch": "§9§lOpV§r 1,024§eA§r Laser Target Hatch", "block.gtceu.opv_16a_energy_converter": "§9§lOpV§r 16§eA§r Energy Converter", @@ -1061,7 +1053,6 @@ "block.gtceu.purple_studs": "Purple Studs", "block.gtceu.pyrolyse_oven": "Pyrolyse Oven", "block.gtceu.radioactive_hazard_sign_block": "Radioactive Hazard Sign Block", - "block.gtceu.raw_oil": "Raw Oil", "block.gtceu.reaction_safe_mixing_casing": "Reaction-Safe Mixing Casing", "block.gtceu.red_borderless_lamp": "Red Borderless Lamp", "block.gtceu.red_granite": "Red Granite", @@ -1153,6 +1144,7 @@ "block.gtceu.substation_capacitor.tooltip_empty": "§7For filling space in your Power Substation", "block.gtceu.substation_capacitor.tooltip_filled": "§cEnergy Capacity: §f%d EU", "block.gtceu.superconducting_coil": "Superconducting Coil Block", + "block.gtceu.surface_rock": "%s Surface Rock", "block.gtceu.tempered_glass": "Tempered Glass", "block.gtceu.test_mui": "Test Mui", "block.gtceu.the_end_marker": "The End", @@ -1743,7 +1735,6 @@ "block.gtceu.zpm_transformer_4a": "§cZPM Voltage§r Hi-Amp (4x) Transformer", "block.gtceu.zpm_wiremill": "§cElite Wiremill III§r", "block.gtceu.zpm_world_accelerator": "§cElite World Accelerator III§r", - "block.gtceu.surface_rock": "%s Surface Rock", "button.gtceu.mark_as_depleted.name": "Mark as Depleted", "button.gtceu.toggle_waypoint.name": "Toggle Waypoint", "command.gtceu.cape.failure.does_not_exist": "Cape %s does not exist", @@ -1837,6 +1828,7 @@ "config.gtceu.option.flintAndSteelRequireSteel": "flintAndSteelRequireSteel", "config.gtceu.option.ftbChunksIntegration": "ftbChunksIntegration", "config.gtceu.option.gameplay": "gameplay", + "config.gtceu.option.gasesVaporizeOnPlacement": "gasesVaporizeOnPlacement", "config.gtceu.option.generateLowQualityGems": "generateLowQualityGems", "config.gtceu.option.ghostCircuit": "ghostCircuit", "config.gtceu.option.gt6StylePipesCables": "gt6StylePipesCables", @@ -1873,6 +1865,8 @@ "config.gtceu.option.ldFluidPipeMinDistance": "ldFluidPipeMinDistance", "config.gtceu.option.ldItemPipeMinDistance": "ldItemPipeMinDistance", "config.gtceu.option.liquidBoilerBaseOutput": "liquidBoilerBaseOutput", + "config.gtceu.option.lowDensityFluidsFlowUp": "lowDensityFluidsFlowUp", + "config.gtceu.option.lowDensityFluidsRenderUpsideDown": "lowDensityFluidsRenderUpsideDown", "config.gtceu.option.maceratorRecyclingYield": "maceratorRecyclingYield", "config.gtceu.option.machineSounds": "machineSounds", "config.gtceu.option.machines": "machines", diff --git a/src/generated/resources/assets/gtceu/models/block/creosote.json b/src/generated/resources/assets/gtceu/models/block/creosote.json deleted file mode 100644 index 5a8d6c2dfd3..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/creosote.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.creosote" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/heavy_oil.json b/src/generated/resources/assets/gtceu/models/block/heavy_oil.json deleted file mode 100644 index 684ebc6adda..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/heavy_oil.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.heavy_oil" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/light_oil.json b/src/generated/resources/assets/gtceu/models/block/light_oil.json deleted file mode 100644 index c5fe8093d62..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/light_oil.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.light_oil" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/natural_gas.json b/src/generated/resources/assets/gtceu/models/block/natural_gas.json deleted file mode 100644 index 68303424489..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/natural_gas.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.natural_gas" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/oil.json b/src/generated/resources/assets/gtceu/models/block/oil.json deleted file mode 100644 index a6e8ebcb883..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/oil.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.oil" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/block/raw_oil.json b/src/generated/resources/assets/gtceu/models/block/raw_oil.json deleted file mode 100644 index c2b5a6f2b4a..00000000000 --- a/src/generated/resources/assets/gtceu/models/block/raw_oil.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "textures": { - "particle": "gtceu:block/fluids/fluid.raw_oil" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 81e05d6450c..accf4e49463 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -8,6 +8,38 @@ "gtceu:cleanroom_glass", "gtceu:petrified_foam", "gtceu:reinforced_stone", + "gtceu:white_lamp", + "gtceu:orange_lamp", + "gtceu:magenta_lamp", + "gtceu:light_blue_lamp", + "gtceu:yellow_lamp", + "gtceu:lime_lamp", + "gtceu:pink_lamp", + "gtceu:gray_lamp", + "gtceu:light_gray_lamp", + "gtceu:cyan_lamp", + "gtceu:purple_lamp", + "gtceu:blue_lamp", + "gtceu:brown_lamp", + "gtceu:green_lamp", + "gtceu:red_lamp", + "gtceu:black_lamp", + "gtceu:white_borderless_lamp", + "gtceu:orange_borderless_lamp", + "gtceu:magenta_borderless_lamp", + "gtceu:light_blue_borderless_lamp", + "gtceu:yellow_borderless_lamp", + "gtceu:lime_borderless_lamp", + "gtceu:pink_borderless_lamp", + "gtceu:gray_borderless_lamp", + "gtceu:light_gray_borderless_lamp", + "gtceu:cyan_borderless_lamp", + "gtceu:purple_borderless_lamp", + "gtceu:blue_borderless_lamp", + "gtceu:brown_borderless_lamp", + "gtceu:green_borderless_lamp", + "gtceu:red_borderless_lamp", + "gtceu:black_borderless_lamp", "gtceu:white_studs", "gtceu:orange_studs", "gtceu:magenta_studs", diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java index 0a6ec97005e..da54b362d73 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/info/MaterialIconType.java @@ -7,6 +7,7 @@ import com.gregtechceu.gtceu.utils.GTUtil; import net.minecraft.client.Minecraft; +import net.minecraft.resources.FileToIdConverter; import net.minecraft.resources.ResourceLocation; import com.google.common.base.CaseFormat; @@ -14,6 +15,7 @@ import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import org.apache.logging.log4j.util.Strings; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -112,17 +114,15 @@ public record MaterialIconType(String name) { private static final Table ITEM_MODEL_CACHE = HashBasedTable .create(); - private static final Table ITEM_TEXTURE_CACHE = HashBasedTable - .create(); - private static final Table ITEM_TEXTURE_CACHE_SECONDARY = HashBasedTable + private static final Table> ITEM_TEXTURE_CACHE = HashBasedTable .create(); private static final Table BLOCK_MODEL_CACHE = HashBasedTable .create(); - private static final Table BLOCK_TEXTURE_CACHE = HashBasedTable - .create(); - private static final Table BLOCK_TEXTURE_CACHE_SECONDARY = HashBasedTable + private static final Table> BLOCK_TEXTURE_CACHE = HashBasedTable .create(); + public static final FileToIdConverter TEXTURE_ID_CONVERTER = new FileToIdConverter("textures", ".png"); + public MaterialIconType(String name) { this.name = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); Preconditions.checkArgument(!ICON_TYPES.containsKey(this.name), @@ -140,64 +140,54 @@ public static MaterialIconType getByName(String name) { return ICON_TYPES.get(name); } - public ResourceLocation getBlockTexturePath(@NotNull MaterialIconSet materialIconSet, boolean doReadCache) { - return getBlockTexturePath(materialIconSet, null, doReadCache); + public ResourceLocation getBlockTexturePath(@NotNull MaterialIconSet materialIconSet, boolean readCache) { + return getBlockTexturePath(materialIconSet, null, readCache); } public ResourceLocation getBlockTexturePath(@NotNull MaterialIconSet materialIconSet, @Nullable String suffix, - boolean doReadCache) { - if (doReadCache) { - if (suffix == null || suffix.isBlank()) { - if (BLOCK_TEXTURE_CACHE.contains(this, materialIconSet)) - return BLOCK_TEXTURE_CACHE.get(this, materialIconSet); - } else { - if (BLOCK_TEXTURE_CACHE_SECONDARY.contains(this, materialIconSet)) - return BLOCK_TEXTURE_CACHE_SECONDARY.get(this, materialIconSet); + boolean readCache) { + suffix = Strings.isBlank(suffix) ? "" : "_" + suffix; + + if (readCache) { + Map suffixMap = BLOCK_TEXTURE_CACHE.get(this, materialIconSet); + if (suffixMap != null && suffixMap.containsKey(suffix)) { + return suffixMap.get(suffix); } } - suffix = Strings.isBlank(suffix) ? "" : "_" + suffix; - MaterialIconSet iconSet = materialIconSet; // noinspection ConstantConditions if (!GTCEu.isClientSide() || Minecraft.getInstance() == null || Minecraft.getInstance().getResourceManager() == null) return GTModels.BLANK_TEXTURE; // check minecraft for null for CI environments - if (!iconSet.isRootIconset) { - while (iconSet != null && !iconSet.isRootIconset) { - ResourceLocation location = iconSet.id.withPath(String - .format("textures/block/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); - if (GTUtil.resourceExists(location)) - break; - iconSet = iconSet.parentIconset; - } + while (iconSet != null && !iconSet.isRootIconset) { + ResourceLocation location = iconSet.id.withPath(String + .format("textures/block/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); + + if (GTUtil.resourceExists(location)) break; + else iconSet = iconSet.parentIconset; } Objects.requireNonNull(iconSet); - ResourceLocation location = iconSet.id.withPath( - String.format("textures/block/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); - - if (!suffix.isEmpty() && !GTUtil.resourceExists(location)) { - return GTModels.BLANK_TEXTURE; - } - location = iconSet.id + ResourceLocation location = iconSet.id .withPath(String.format("block/material_sets/%s/%s%s", iconSet.getName(), this.name, suffix)); - if (suffix.isEmpty()) { - BLOCK_TEXTURE_CACHE.put(this, materialIconSet, location); - } else { - BLOCK_TEXTURE_CACHE_SECONDARY.put(this, materialIconSet, location); + if (!GTUtil.resourceExists(TEXTURE_ID_CONVERTER.idToFile(location))) { + location = GTModels.BLANK_TEXTURE; } + BLOCK_TEXTURE_CACHE.row(this).computeIfAbsent(materialIconSet, $ -> new HashMap<>()) + .put(suffix, location); + return location; } - @NotNull - public ResourceLocation getBlockModelPath(@NotNull MaterialIconSet materialIconSet, boolean doReadCache) { - if (doReadCache) { - if (BLOCK_MODEL_CACHE.contains(this, materialIconSet)) { - return BLOCK_MODEL_CACHE.get(this, materialIconSet); + public @NotNull ResourceLocation getBlockModelPath(@NotNull MaterialIconSet materialIconSet, boolean readCache) { + if (readCache) { + ResourceLocation cachedValue = BLOCK_MODEL_CACHE.get(this, materialIconSet); + if (cachedValue != null) { + return cachedValue; } } @@ -208,9 +198,9 @@ public ResourceLocation getBlockModelPath(@NotNull MaterialIconSet materialIconS while (iconSet != null && !iconSet.isRootIconset) { ResourceLocation location = iconSet.id .withPath(String.format("models/block/material_sets/%s/%s.json", iconSet.getName(), this.name)); - if (GTUtil.resourceExists(location)) - break; - iconSet = iconSet.parentIconset; + + if (GTUtil.resourceExists(location)) break; + else iconSet = iconSet.parentIconset; } } @@ -218,31 +208,27 @@ public ResourceLocation getBlockModelPath(@NotNull MaterialIconSet materialIconS ResourceLocation location = iconSet.id .withPath(String.format("block/material_sets/%s/%s", iconSet.getName(), this.name)); - ITEM_MODEL_CACHE.put(this, materialIconSet, location); + + BLOCK_MODEL_CACHE.put(this, materialIconSet, location); return location; } - @NotNull - public ResourceLocation getItemModelPath(@NotNull MaterialIconSet materialIconSet, boolean doReadCache) { - if (doReadCache) { - if (ITEM_MODEL_CACHE.contains(this, materialIconSet)) { - return ITEM_MODEL_CACHE.get(this, materialIconSet); + public @NotNull ResourceLocation getItemModelPath(@NotNull MaterialIconSet materialIconSet, boolean readCache) { + if (readCache) { + ResourceLocation cachedValue = ITEM_MODEL_CACHE.get(this, materialIconSet); + if (cachedValue != null) { + return cachedValue; } } MaterialIconSet iconSet = materialIconSet; - // noinspection ConstantConditions - if (!iconSet.isRootIconset && GTCEu.isClientSide() && Minecraft.getInstance() != null && - Minecraft.getInstance().getResourceManager() != null) { // check minecraft for null for CI environments - while (iconSet != null && !iconSet.isRootIconset) { - ResourceLocation location = iconSet.id - .withPath(String.format("models/item/material_sets/%s/%s.json", iconSet.getName(), this.name)); + while (iconSet != null && !iconSet.isRootIconset) { + ResourceLocation location = iconSet.id + .withPath(String.format("models/item/material_sets/%s/%s.json", iconSet.getName(), this.name)); - if (GTUtil.resourceExists(location)) - break; - iconSet = iconSet.parentIconset; - } + if (GTUtil.resourceExists(location)) break; + else iconSet = iconSet.parentIconset; } Objects.requireNonNull(iconSet); @@ -255,56 +241,42 @@ public ResourceLocation getItemModelPath(@NotNull MaterialIconSet materialIconSe return location; } - @Nullable - public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIconSet, boolean doReadCache) { - return getItemTexturePath(materialIconSet, null, doReadCache); + public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIconSet, boolean readCache) { + return getItemTexturePath(materialIconSet, null, readCache); } - @Nullable - public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIconSet, String suffix, - boolean doReadCache) { - if (doReadCache) { - if (suffix == null || suffix.isBlank()) { - if (ITEM_TEXTURE_CACHE.contains(this, materialIconSet)) - return ITEM_TEXTURE_CACHE.get(this, materialIconSet); - } else { - if (ITEM_TEXTURE_CACHE_SECONDARY.contains(this, materialIconSet)) - return ITEM_TEXTURE_CACHE_SECONDARY.get(this, materialIconSet); + public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIconSet, @Nullable String suffix, + boolean readCache) { + suffix = Strings.isBlank(suffix) ? "" : "_" + suffix; + + if (readCache) { + Map suffixMap = ITEM_TEXTURE_CACHE.get(this, materialIconSet); + if (suffixMap != null && suffixMap.containsKey(suffix)) { + return suffixMap.get(suffix); } } - suffix = suffix == null || suffix.isBlank() ? "" : "_" + suffix; - MaterialIconSet iconSet = materialIconSet; - // noinspection ConstantConditions - if (!iconSet.isRootIconset && GTCEu.isClientSide() && Minecraft.getInstance() != null && - Minecraft.getInstance().getResourceManager() != null) { // check minecraft for null for CI environments - while (iconSet != null && !iconSet.isRootIconset) { - ResourceLocation location = iconSet.id.withPath( - String.format("textures/item/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); + while (iconSet != null && !iconSet.isRootIconset) { + ResourceLocation location = iconSet.id.withPath( + String.format("textures/item/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); - if (GTUtil.resourceExists(location)) - break; - iconSet = iconSet.parentIconset; - } + if (GTUtil.resourceExists(location)) break; + else iconSet = iconSet.parentIconset; } Objects.requireNonNull(iconSet); ResourceLocation location = iconSet.id.withPath( - String.format("textures/item/material_sets/%s/%s%s.png", iconSet.getName(), this.name, suffix)); + String.format("item/material_sets/%s/%s%s", iconSet.getName(), this.name, suffix)); - if (!suffix.isEmpty() && !GTUtil.resourceExists(location)) { - return null; - } - location = iconSet.id - .withPath(String.format("item/material_sets/%s/%s%s", iconSet.getName(), this.name, suffix)); - if (suffix.isEmpty()) { - ITEM_TEXTURE_CACHE.put(this, materialIconSet, location); - } else { - ITEM_TEXTURE_CACHE_SECONDARY.put(this, materialIconSet, location); + if (!GTUtil.resourceExists(TEXTURE_ID_CONVERTER.idToFile(location))) { + location = null; } + ITEM_TEXTURE_CACHE.row(this).computeIfAbsent(materialIconSet, $ -> new HashMap<>()) + .put(suffix, location); + return location; } @@ -313,6 +285,14 @@ public ResourceLocation getItemTexturePath(@NotNull MaterialIconSet materialIcon return this.name; } + @ApiStatus.Internal + public static void invalidateCaches() { + ITEM_MODEL_CACHE.clear(); + ITEM_TEXTURE_CACHE.clear(); + BLOCK_MODEL_CACHE.clear(); + BLOCK_TEXTURE_CACHE.clear(); + } + private static class KJSCallWrapper { private static void postEvent() { diff --git a/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidBuilder.java b/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidBuilder.java index 347670df3c4..273d72b90f7 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidBuilder.java +++ b/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidBuilder.java @@ -2,28 +2,29 @@ import com.gregtechceu.gtceu.api.data.chemical.material.Material; import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags; +import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconSet; +import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconType; import com.gregtechceu.gtceu.api.data.chemical.material.properties.BlastProperty; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttribute; -import com.gregtechceu.gtceu.api.fluids.store.FluidStorage; import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKey; import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys; import com.gregtechceu.gtceu.api.registry.registrate.GTClientFluidTypeExtensions; import com.gregtechceu.gtceu.api.registry.registrate.GTRegistrate; +import com.gregtechceu.gtceu.common.block.GTLiquidBlock; +import com.gregtechceu.gtceu.common.data.models.GTModels; import com.gregtechceu.gtceu.common.item.GTBucketItem; +import com.gregtechceu.gtceu.config.ConfigHolder; import com.gregtechceu.gtceu.utils.GTUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; +import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; import net.minecraft.world.level.material.Fluid; -import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; import net.neoforged.neoforge.common.SoundActions; -import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.BaseFlowingFluid; import net.neoforged.neoforge.fluids.FluidType; import com.google.common.base.Preconditions; @@ -46,6 +47,7 @@ import static com.gregtechceu.gtceu.api.fluids.FluidConstants.*; +@SuppressWarnings("unused") @Accessors(fluent = true, chain = true) public class FluidBuilder { @@ -88,9 +90,12 @@ public class FluidBuilder { private boolean hasCustomStill = false; @Getter private boolean hasCustomFlowing = false; + @Setter + private @Nullable MaterialIconType customIconType = null; + @Setter + private @Nullable MaterialIconSet customIconSet = null; - @Getter - private boolean hasFluidBlock = false; + private boolean hasFluidBlock = ConfigHolder.INSTANCE.gameplay.allFluidsHaveBlocks; private boolean hasBucket = true; public FluidBuilder() {} @@ -130,6 +135,16 @@ public FluidBuilder disableColor() { return this; } + /** + * Forcibly enables coloring the fluid. Use when you want to use a custom fluid texture and also tint it. + * + * @return this + */ + public FluidBuilder forceEnableColor() { + this.isColorEnabled = true; + return this; + } + /** * @param density the density in g/cm^3 * @return this @@ -252,6 +267,16 @@ public FluidBuilder block() { return this; } + /** + * Disables the auto-generated fluid block for the fluid + * + * @return this + */ + public FluidBuilder disableBlock() { + this.hasFluidBlock = false; + return this; + } + /** * Disables the auto-generated fluid bucket for the fluid * @@ -286,34 +311,41 @@ public Supplier build(Material material, FluidStorageKey key, G determineLuminosity(material); determineViscosity(material); - final String langKey = this.translation != null ? this.translation : key.getTranslationKeyFor(material); // noinspection DataFlowIssue var builder = registrate.fluid(this.name, this.still, this.flowing, - (p, $1, $2) -> makeFluidType(registrate, p, material, key, langKey), + (p, $1, $2) -> makeFluidType(registrate, p, material, key), (p) -> new GTFluid.Flowing(this.state, this.burnTime, p)) .source((p) -> new GTFluid.Source(this.state, this.burnTime, p)) - .setData(ProviderType.LANG, NonNullBiConsumer.noop()); + .properties(p -> this.setupFluidTypeProperties(p, material)) + .fluidProperties(p -> this.setupFluidProperties(p, material)) + .setData(ProviderType.LANG, NonNullBiConsumer.noop()) + .renderType(() -> RenderType::translucent); if (this.hasFluidBlock) { - builder.block() + // noinspection Convert2MethodRef + builder.block(GTLiquidBlock::new) + .setData(ProviderType.LANG, NonNullBiConsumer.noop()) + .setData(ProviderType.BLOCKSTATE, NonNullBiConsumer.noop()) + .properties(p -> p.liquid()) .color(() -> () -> (state, level, pos, index) -> { - return IClientFluidTypeExtensions.of(state.getFluidState()) - .getTintColor(state.getFluidState(), level, pos); + if (this.isColorEnabled) { + return index == 0 ? this.color : material.getMaterialARGB(index); + } else { + return INFER_COLOR; + } }) .register(); } else { - // noinspection DataFlowIssue - builder.noBlock().fluidProperties(p -> p.block(null)); + builder.noBlock(); } if (this.hasBucket) { - builder.bucket((fluid, properties) -> new GTBucketItem(fluid, properties, material, langKey)) + builder.bucket((fluid, properties) -> new GTBucketItem(fluid, properties, material)) .properties(p -> p.craftRemainder(Items.BUCKET).stacksTo(1)) .setData(ProviderType.LANG, NonNullBiConsumer.noop()) .setData(ProviderType.ITEM_MODEL, NonNullBiConsumer.noop()) .color(() -> () -> GTBucketItem::color) .register(); } else { - // noinspection DataFlowIssue - builder.noBucket().fluidProperties(p -> p.bucket(null)); + builder.noBucket(); } builder.onRegister(fluid -> { @@ -331,18 +363,42 @@ private void determineName(Material material, @Nullable FluidStorageKey key) { @ApiStatus.Internal public void determineTextures(Material material, FluidStorageKey key) { + MaterialIconType iconType = customIconType != null ? customIconType : key.getIconType(); + MaterialIconSet iconSet = customIconSet != null ? customIconSet : material.getMaterialIconSet(); + + boolean usesSameTextureForStillAndFlowing = false; if (hasCustomStill || material.isNull()) { - still = ResourceLocation.fromNamespaceAndPath(material.getModid(), "block/fluids/fluid." + name); + still = ResourceLocation.fromNamespaceAndPath(material.getModid(), "block/fluids/fluid." + name + "_still"); + if (!GTUtil.resourceExists(MaterialIconType.TEXTURE_ID_CONVERTER.idToFile(still))) { + still = ResourceLocation.fromNamespaceAndPath(material.getModid(), "block/fluids/fluid." + name); + usesSameTextureForStillAndFlowing = true; + } } else { - still = key.getIconType().getBlockTexturePath(material.getMaterialIconSet(), true); + still = iconType.getBlockTexturePath(iconSet, "still", true); + if (still.equals(GTModels.BLANK_TEXTURE)) { + still = iconType.getBlockTexturePath(iconSet, null, true); + usesSameTextureForStillAndFlowing = true; + } } if (hasCustomFlowing) { flowing = ResourceLocation.fromNamespaceAndPath(material.getModid(), "block/fluids/fluid." + name + "_flow"); - } else { - // FIXME this is actually wrong, flowing fluids should have 32x32 textures (double the size of still ones). + + if (!GTUtil.resourceExists(MaterialIconType.TEXTURE_ID_CONVERTER.idToFile(flowing))) { + // this is technically wrong, flowing fluids should have 32x32 textures (double the size of still ones) + // it'll look weird if the still texture isn't a single color (note: gases are, so those are fine) + flowing = still; + } + } else if (usesSameTextureForStillAndFlowing) { + // same note as above flowing = still; + } else { + flowing = iconType.getBlockTexturePath(iconSet, "flow", true); + if (flowing.equals(GTModels.BLANK_TEXTURE)) { + // same note as above + flowing = still; + } } } @@ -381,7 +437,7 @@ private void determineTemperature(Material material) { private void determineColor(Material material) { if (color != INFER_COLOR) return; - if (isColorEnabled && !material.isNull()) { + if (isColorEnabled && !material.isNull() && material.hasFluidColor()) { color = GTUtil.convertRGBtoARGB(material.getMaterialRGB()); } } @@ -427,56 +483,45 @@ private void determineViscosity(Material material) { }; } - private FluidType makeFluidType(AbstractRegistrate owner, FluidType.Properties properties, - Material material, FluidStorageKey key, String langKey) { - properties.sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL) + private FluidType.Properties setupFluidTypeProperties(FluidType.Properties properties, Material material) { + final boolean canSwim = this.density >= MIN_SWIMMABLE_DENSITY && this.viscosity <= MAX_SWIMMABLE_VISCOSITY; + return properties.sound(SoundActions.BUCKET_FILL, SoundEvents.BUCKET_FILL) .sound(SoundActions.BUCKET_EMPTY, SoundEvents.BUCKET_EMPTY) .sound(SoundActions.FLUID_VAPORIZE, SoundEvents.FIRE_EXTINGUISH) .temperature(this.temperature) .density(this.density) .lightLevel(this.luminosity) - .viscosity(this.viscosity); - FluidType type = new FluidType(properties) { - - @Override - public String getDescriptionId() { - return material.getUnlocalizedName(); - } + .viscosity(this.viscosity) + .motionScale(0.014D * ((double) DEFAULT_LIQUID_VISCOSITY / this.viscosity)) + .canSwim(canSwim) + .supportsBoating(canSwim); + } - @Override - public Component getDescription() { - return Component.translatable(langKey, material.getLocalizedName()); - } + @SuppressWarnings("DataFlowIssue") + private BaseFlowingFluid.Properties setupFluidProperties(BaseFlowingFluid.Properties properties, + Material material) { + if (!this.hasFluidBlock) properties.block(null); + if (!this.hasBucket) properties.bucket(null); - @Override - public Component getDescription(FluidStack stack) { - return this.getDescription(); - } + // limit flow rate a maximum to 1 tick per step + // (0 or negative values don't cause issues AFAIK, but they aren't good either.) + return properties.tickRate(Math.max(this.viscosity / 200, 1)); + } - @Override - public boolean isVaporizedOnPlacement(Level level, BlockPos pos, FluidStack stack) { - FluidStorage fluidStorage = material.getProperty(PropertyKey.FLUID); - // always vaporize plasmas and gases - FluidStorage.FluidEntry plasmaEntry = fluidStorage.getEntry(FluidStorageKeys.PLASMA); - if (plasmaEntry != null) { - FluidBuilder plasmaBuilder = plasmaEntry.getBuilder(); - return plasmaBuilder != null && plasmaBuilder.hasFluidBlock(); - } - FluidStorage.FluidEntry gasEntry = fluidStorage.getEntry(FluidStorageKeys.GAS); - if (gasEntry != null) { - var gasBuilder = gasEntry.getBuilder(); - return gasBuilder != null && gasBuilder.hasFluidBlock(); - } + private FluidType makeFluidType(AbstractRegistrate owner, FluidType.Properties properties, + Material material, FluidStorageKey key) { + // sadly, we have to apply this here instead of in setupFluidTypeProperties because Registrate overwrites + // whatever we assign there. + final String langKey = this.translation != null ? this.translation : key.getTranslationKeyFor(material); + properties.descriptionId(langKey); - return false; - } - }; + FluidType type = new GTFluidType(properties, material); OneTimeEventReceiver.addModListener(owner, RegisterClientExtensionsEvent.class, event -> { final int color = isColorEnabled ? this.color : INFER_COLOR; if (still == null || flowing == null) { this.determineTextures(material, key); } - event.registerFluidType(new GTClientFluidTypeExtensions(still, flowing, color), type); + event.registerFluidType(new GTClientFluidTypeExtensions(type, still, flowing, color), type); }); return type; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidConstants.java b/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidConstants.java index ece429185d2..f87bb8a4d4c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidConstants.java +++ b/src/main/java/com/gregtechceu/gtceu/api/fluids/FluidConstants.java @@ -29,6 +29,8 @@ public final class FluidConstants { public static final int DEFAULT_PLASMA_DENSITY = -100000; public static final int DEFAULT_MOLTEN_DENSITY = 1500; + public static final int MIN_SWIMMABLE_DENSITY = 500; + /** * Viscosity for sticky materials */ @@ -39,6 +41,8 @@ public final class FluidConstants { public static final int DEFAULT_PLASMA_VISCOSITY = 10; public static final int DEFAULT_MOLTEN_VISCOSITY = 2000; + public static final int MAX_SWIMMABLE_VISCOSITY = 1500; + /** * Threshold for fluids to be considered cryogenic. *

diff --git a/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluid.java b/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluid.java index 91bf3eb9bf8..db627651566 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluid.java +++ b/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluid.java @@ -2,31 +2,52 @@ import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttribute; import com.gregtechceu.gtceu.api.fluids.attribute.IAttributedFluid; +import com.gregtechceu.gtceu.config.ConfigHolder; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; +import net.minecraft.world.level.block.IceBlock; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.Shapes; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.neoforged.neoforge.event.EventHooks; import net.neoforged.neoforge.fluids.BaseFlowingFluid; +import com.google.common.collect.Maps; +import com.mojang.datafixers.util.Pair; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import it.unimi.dsi.fastutil.shorts.Short2BooleanMap; +import it.unimi.dsi.fastutil.shorts.Short2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; import lombok.Getter; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Map; +// TODO implement burning/acid/etc. damage when standing in a fluid block public abstract class GTFluid extends BaseFlowingFluid implements IAttributedFluid { + private static final double MAX_FLUID_HEIGHT = 8.0D / 9.0D; + @Getter private final Collection attributes = new ObjectLinkedOpenHashSet<>(); @Getter - private final FluidState state; + private final com.gregtechceu.gtceu.api.fluids.FluidState state; @Getter private final int burnTime; - public GTFluid(FluidState state, int burnTime, BaseFlowingFluid.Properties properties) { + public GTFluid(com.gregtechceu.gtceu.api.fluids.FluidState state, int burnTime, + BaseFlowingFluid.Properties properties) { super(properties); this.state = state; this.burnTime = burnTime; @@ -37,75 +58,362 @@ public void addAttribute(FluidAttribute attribute) { attributes.add(attribute); } + // region up-flowing gas handling + // all of these should have early return conditions that invoke the superclass's method if the config is disabled or + // the fluid is "heavier than air". + + /** + * {@return {@code true} if this fluid should flow up instead of down} + */ + protected boolean shouldFlowUpward() { + if (!ConfigHolder.INSTANCE.gameplay.lowDensityFluidsFlowUp) { + return false; + } + return this.getFluidType().isLighterThanAir(); + } + @Override - protected boolean canBeReplacedWith(net.minecraft.world.level.material.FluidState state, BlockGetter level, + protected boolean canBeReplacedWith(FluidState state, BlockGetter level, BlockPos pos, Fluid fluid, Direction direction) { - return direction == Direction.DOWN && !isSame(fluid); + if (!shouldFlowUpward()) { + return super.canBeReplacedWith(state, level, pos, fluid, direction); + } + + // same implementation was WaterFluid. LavaFluid has a different one, but we don't need to change this rn. + // super method uses Direction.DOWN here + return direction == Direction.UP && !isSame(fluid); + } + + @Override + public Vec3 getFlow(BlockGetter level, BlockPos pos, FluidState myState) { + if (!shouldFlowUpward()) { + return super.getFlow(level, pos, myState); + } + + double xMotion = 0.0D; + double zMotion = 0.0D; + + BlockPos.MutableBlockPos cursor = new BlockPos.MutableBlockPos(); + for (Direction dir : Direction.Plane.HORIZONTAL) { + cursor.setWithOffset(pos, dir); + FluidState otherState = level.getFluidState(cursor); + if (!this.affectsFlow(otherState)) { + continue; + } + float otherFluidHeight = otherState.getOwnHeight(); + double speedMultiplier = 0.0D; + + if (otherFluidHeight == 0.0f) { + // source block + + // noinspection deprecation + if (!level.getBlockState(cursor).blocksMotion()) { + FluidState aboveState = level.getFluidState(cursor.above()); + if (this.affectsFlow(aboveState)) { + otherFluidHeight = aboveState.getOwnHeight(); + if (otherFluidHeight > 0.0f) { + speedMultiplier = myState.getOwnHeight() - (otherFluidHeight - MAX_FLUID_HEIGHT); + } + } + } + } else if (otherFluidHeight > 0.0f) { + speedMultiplier = myState.getOwnHeight() - otherFluidHeight; + } + + if (speedMultiplier != 0.0D) { + xMotion += dir.getStepX() * speedMultiplier; + zMotion += dir.getStepZ() * speedMultiplier; + } + } + + Vec3 flowVector = new Vec3(xMotion, 0.0D, zMotion); + if (myState.getValue(FALLING)) { + for (Direction dir : Direction.Plane.HORIZONTAL) { + cursor.setWithOffset(pos, dir); + if (this.isSolidFace(level, cursor, dir) || this.isSolidFace(level, cursor.below(), dir)) { + // make it flow UP instead of DOWN :tr: + flowVector = flowVector.normalize().add(0.0D, 6.0D, 0.0D); + break; + } + } + } + + return flowVector.normalize(); + } + + @Override + protected boolean isSolidFace(BlockGetter level, BlockPos neighborPos, Direction side) { + if (!shouldFlowUpward()) { + return super.isSolidFace(level, neighborPos, side); + } + + BlockState neighborBlock = level.getBlockState(neighborPos); + if (neighborBlock.getFluidState().getType().isSame(this)) { + return false; + } else if (side == Direction.DOWN) { + return true; + } else if (neighborBlock.getBlock() instanceof IceBlock) { + return false; + } else { + return neighborBlock.isFaceSturdy(level, neighborPos, side); + } + } + + @Override + protected void spread(Level level, BlockPos pos, FluidState state) { + // we can safely do this here because the parent method does the same + if (state.isEmpty()) { + return; + } + if (!shouldFlowUpward()) { + super.spread(level, pos, state); + return; + } + + BlockState blockState = level.getBlockState(pos); + BlockPos spreadPos = pos.above(); + BlockState spreadState = level.getBlockState(spreadPos); + FluidState spreadFluid = this.getNewLiquid(level, spreadPos, spreadState); + if (this.canSpreadTo(level, pos, blockState, Direction.UP, spreadPos, spreadState, + level.getFluidState(spreadPos), spreadFluid.getType())) { + this.spreadTo(level, spreadPos, spreadState, Direction.UP, spreadFluid); + if (this.sourceNeighborCount(level, pos) >= 3) { + this.spreadToSides(level, pos, state, blockState); + } + } else if (state.isSource() || + !this.isWaterHole(level, spreadFluid.getType(), pos, blockState, spreadPos, spreadState)) { + this.spreadToSides(level, pos, state, blockState); + } + } + + @Override + protected FluidState getNewLiquid(Level level, BlockPos pos, BlockState blockState) { + if (!shouldFlowUpward()) { + return super.getNewLiquid(level, pos, blockState); + } + + int highestAdjacentLevel = 0; + int adjacentSourceCount = 0; + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos spreadPos = pos.relative(direction); + BlockState spreadState = level.getBlockState(spreadPos); + FluidState spreadStateFluid = spreadState.getFluidState(); + if (spreadStateFluid.getType().isSame(this) && + this.canPassThroughWall(direction, level, pos, blockState, spreadPos, spreadState)) { + if (spreadStateFluid.isSource() && EventHooks.canCreateFluidSource(level, spreadPos, spreadState)) { + adjacentSourceCount++; + } + + highestAdjacentLevel = Math.max(highestAdjacentLevel, spreadStateFluid.getAmount()); + } + } + + if (adjacentSourceCount >= 2) { + // >=2 adjacent source blocks can create a new source block if canConvertToSource is true for them + BlockState aboveBlock = level.getBlockState(pos.above()); + FluidState aboveFluid = aboveBlock.getFluidState(); + // noinspection deprecation + if (aboveBlock.isSolid() || this.isSourceBlockOfThisType(aboveFluid)) { + return this.getSource(false); + } + } + + BlockPos spreadPos = pos.below(); + BlockState spreadState = level.getBlockState(spreadPos); + FluidState spreadStateFluid = spreadState.getFluidState(); + if (!spreadStateFluid.isEmpty() && spreadStateFluid.getType().isSame(this) && + this.canPassThroughWall(Direction.DOWN, level, pos, blockState, spreadPos, spreadState)) { + return this.getFlowing(8, true); + } else { + int actualLevel = highestAdjacentLevel - this.getDropOff(level); + return actualLevel <= 0 ? Fluids.EMPTY.defaultFluidState() : this.getFlowing(actualLevel, false); + } } @Override - public int getTickDelay(LevelReader level) { - return 5; + protected int getSlopeDistance(LevelReader level, BlockPos spreadPos, int distance, Direction currentDirection, + BlockState currentSpreadState, BlockPos sourcePos, + Short2ObjectMap> stateCache, + Short2BooleanMap waterHoleCache) { + if (!shouldFlowUpward()) { + return super.getSlopeDistance(level, spreadPos, distance, currentDirection, currentSpreadState, + sourcePos, stateCache, waterHoleCache); + } + + int lowestDistance = 1000; + + for (Direction spreadDirection : Direction.Plane.HORIZONTAL) { + if (spreadDirection == currentDirection) { + continue; + } + BlockPos nextSpreadPos = spreadPos.relative(spreadDirection); + short cacheKey = getCacheKey(sourcePos, nextSpreadPos); + Pair pair = stateCache.computeIfAbsent(cacheKey, $ -> { + BlockState blockstate1 = level.getBlockState(nextSpreadPos); + return Pair.of(blockstate1, blockstate1.getFluidState()); + }); + BlockState spreadBlock = pair.getFirst(); + FluidState spreadFluid = pair.getSecond(); + + if (!this.canPassThrough(level, this.getFlowing(), spreadPos, currentSpreadState, spreadDirection, + nextSpreadPos, spreadBlock, spreadFluid)) { + continue; + } + + boolean hasWaterHole = waterHoleCache.computeIfAbsent(cacheKey, $ -> { + BlockPos abovePos = nextSpreadPos.above(); + BlockState aboveState = level.getBlockState(abovePos); + return this.isWaterHole(level, this.getFlowing(), nextSpreadPos, spreadBlock, abovePos, aboveState); + }); + if (hasWaterHole) { + return distance; + } + if (distance >= this.getSlopeFindDistance(level)) { + continue; + } + + int newDistance = this.getSlopeDistance(level, nextSpreadPos, distance + 1, spreadDirection.getOpposite(), + spreadBlock, sourcePos, stateCache, waterHoleCache); + if (newDistance < lowestDistance) { + lowestDistance = newDistance; + } + } + + return lowestDistance; } @Override - protected float getExplosionResistance() { - return 10; + public boolean isWaterHole(BlockGetter level, Fluid fluid, BlockPos pos, BlockState state, BlockPos spreadPos, + BlockState spreadState) { + if (!shouldFlowUpward()) { + return super.isWaterHole(level, fluid, pos, state, spreadPos, spreadState); + } + + // inverted direction + if (!this.canPassThroughWall(Direction.UP, level, pos, state, spreadPos, spreadState)) { + return false; + } else if (spreadState.getFluidState().getType().isSame(this)) { + return true; + } else { + return this.canHoldFluid(level, spreadPos, spreadState, fluid); + } } @Override - protected int getSlopeFindDistance(LevelReader level) { - return 4; + protected Map getSpread(Level level, BlockPos pos, BlockState state) { + int lowestDistance = 1000; + Map result = Maps.newEnumMap(Direction.class); + Short2ObjectMap> stateCache = new Short2ObjectOpenHashMap<>(); + Short2BooleanMap waterHoleCache = new Short2BooleanOpenHashMap(); + + for (Direction spreadDirection : Direction.Plane.HORIZONTAL) { + BlockPos spreadPos = pos.relative(spreadDirection); + short cacheKey = getCacheKey(pos, spreadPos); + Pair pair = stateCache.computeIfAbsent(cacheKey, $ -> { + BlockState spreadState = level.getBlockState(spreadPos); + return Pair.of(spreadState, spreadState.getFluidState()); + }); + BlockState spreadBlock = pair.getFirst(); + FluidState spreadFluid = pair.getSecond(); + FluidState newFluid = this.getNewLiquid(level, spreadPos, spreadBlock); + + if (!this.canPassThrough(level, newFluid.getType(), pos, state, spreadDirection, spreadPos, spreadBlock, + spreadFluid)) { + continue; + } + + boolean hasWaterHole = waterHoleCache.computeIfAbsent(cacheKey, $ -> { + BlockPos abovePos = spreadPos.above(); + BlockState aboveState = level.getBlockState(abovePos); + return this.isWaterHole(level, this.getFlowing(), spreadPos, spreadBlock, abovePos, aboveState); + }); + int slopeDistance = 0; + if (!hasWaterHole) { + slopeDistance = this.getSlopeDistance(level, spreadPos, 1, spreadDirection.getOpposite(), spreadBlock, + pos, + stateCache, waterHoleCache); + } + + if (slopeDistance <= lowestDistance) { + if (slopeDistance < lowestDistance) { + result.clear(); + } + + result.put(spreadDirection, newFluid); + lowestDistance = slopeDistance; + } + } + + return result; + } + + protected static boolean hasSameBelow(FluidState fluidState, BlockGetter level, BlockPos pos) { + return fluidState.getType().isSame(level.getFluidState(pos.below()).getType()); } @Override - protected int getDropOff(LevelReader level) { - return 1; + public float getHeight(FluidState state, BlockGetter level, BlockPos pos) { + if (!shouldFlowUpward()) { + return super.getHeight(state, level, pos); + } + return hasSameBelow(state, level, pos) ? 1.0f : state.getOwnHeight(); } @Override - public boolean isSame(Fluid fluid) { - boolean still = this.getSource() == fluid; - boolean flowing = this.getFlowing() == fluid; - return still || flowing; + public VoxelShape getShape(FluidState state, BlockGetter level, BlockPos pos) { + if (!shouldFlowUpward()) { + return super.getShape(state, level, pos); + } + if (state.getAmount() == FluidState.AMOUNT_MAX && hasSameBelow(state, level, pos)) { + return Shapes.block(); + } + // we know the fluid should flow up and that it doesn't have the same block below it, so we can safely skip + // calling FluidState#getHeight here and shortcut to getOwnHeight + return this.shapes.computeIfAbsent(state, + fluidState -> Shapes.box(0.0D, 1.0D - fluidState.getOwnHeight(), 0.0D, 1.0D, 1.0D, 1.0D)); } + // endregion upside down gas handling + public static class Source extends GTFluid { - public Source(FluidState state, int burnTime, BaseFlowingFluid.Properties properties) { + public Source(com.gregtechceu.gtceu.api.fluids.FluidState state, int burnTime, + BaseFlowingFluid.Properties properties) { super(state, burnTime, properties); } @Override - public int getAmount(net.minecraft.world.level.material.FluidState state) { + public int getAmount(FluidState state) { return 8; } @Override - public boolean isSource(net.minecraft.world.level.material.FluidState state) { + public boolean isSource(FluidState state) { return true; } } public static class Flowing extends GTFluid { - public Flowing(FluidState state, int burnTime, BaseFlowingFluid.Properties properties) { + public Flowing(com.gregtechceu.gtceu.api.fluids.FluidState state, int burnTime, + BaseFlowingFluid.Properties properties) { super(state, burnTime, properties); registerDefaultState(getStateDefinition().any().setValue(LEVEL, 7)); } - protected void createFluidStateDefinition(StateDefinition.@NotNull Builder builder) { + protected void createFluidStateDefinition(StateDefinition.@NotNull Builder builder) { super.createFluidStateDefinition(builder); builder.add(LEVEL); } @Override - public int getAmount(net.minecraft.world.level.material.FluidState state) { + public int getAmount(FluidState state) { return state.getValue(LEVEL); } @Override - public boolean isSource(net.minecraft.world.level.material.FluidState state) { + public boolean isSource(FluidState state) { return false; } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluidType.java b/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluidType.java new file mode 100644 index 00000000000..48b46533919 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/fluids/GTFluidType.java @@ -0,0 +1,59 @@ +package com.gregtechceu.gtceu.api.fluids; + +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.fluids.store.FluidStorage; +import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys; +import com.gregtechceu.gtceu.config.ConfigHolder; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidType; + +public class GTFluidType extends FluidType { + + private final Material material; + + public GTFluidType(Properties properties, Material material) { + super(properties); + this.material = material; + } + + @Override + public String getDescriptionId() { + return material.getUnlocalizedName(); + } + + @Override + public Component getDescription() { + return Component.translatable(super.getDescriptionId(), material.getLocalizedName()); + } + + @Override + public Component getDescription(FluidStack stack) { + return Component.translatable(super.getDescriptionId(stack), material.getLocalizedName()); + } + + @Override + public boolean isVaporizedOnPlacement(Level level, BlockPos pos, FluidStack stack) { + if (!ConfigHolder.INSTANCE.gameplay.gasesVaporizeOnPlacement) { + return false; + } + + FluidStorage fluidStorage = material.getProperty(PropertyKey.FLUID); + // always vaporize plasmas and gases + Fluid plasma = fluidStorage.get(FluidStorageKeys.PLASMA); + if (plasma != null) { + return !plasma.defaultFluidState().createLegacyBlock().isEmpty(); + } + Fluid gas = fluidStorage.get(FluidStorageKeys.GAS); + if (gas != null) { + return !gas.defaultFluidState().createLegacyBlock().isEmpty(); + } + + return false; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTClientFluidTypeExtensions.java b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTClientFluidTypeExtensions.java index 0e121db8ed3..ee4a1d7b0b4 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTClientFluidTypeExtensions.java +++ b/src/main/java/com/gregtechceu/gtceu/api/registry/registrate/GTClientFluidTypeExtensions.java @@ -1,11 +1,18 @@ package com.gregtechceu.gtceu.api.registry.registrate; import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.client.renderer.fluid.InvertedFluidRenderer; import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidType; +import com.mojang.blaze3d.vertex.VertexConsumer; import lombok.Getter; import lombok.Setter; import org.jetbrains.annotations.Nullable; @@ -14,24 +21,34 @@ public class GTClientFluidTypeExtensions implements IClientFluidTypeExtensions { public static final ResourceLocation FLUID_SCREEN_OVERLAY = GTCEu.id("textures/misc/fluid_screen_overlay.png"); - public GTClientFluidTypeExtensions(@Nullable ResourceLocation stillTexture, + public GTClientFluidTypeExtensions(FluidType fluidType, + @Nullable ResourceLocation stillTexture, @Nullable ResourceLocation flowingTexture, int tintColor) { + this.fluidType = fluidType; this.stillTexture = stillTexture; this.flowingTexture = flowingTexture; this.tintColor = tintColor; } + private final FluidType fluidType; @Getter @Setter @Nullable private ResourceLocation flowingTexture, stillTexture; @Getter - @Setter - private int tintColor; + private final int tintColor; @Override public ResourceLocation getRenderOverlayTexture(Minecraft mc) { return FLUID_SCREEN_OVERLAY; } + + @Override + public boolean renderFluid(FluidState fluidState, BlockAndTintGetter level, BlockPos pos, VertexConsumer consumer, + BlockState blockState) { + // use inverted rendering :3 + // the method checks all conditions by itself; we don't need to do anything special here + return InvertedFluidRenderer.maybeRenderFluidInverted(fluidType, fluidState, blockState, level, pos, consumer); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java index 793dfb933b3..f90f7226881 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/client/ClientProxy.java @@ -3,6 +3,7 @@ import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.api.GTValues; import com.gregtechceu.gtceu.api.cosmetics.event.RegisterGTCapesEvent; +import com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialIconType; import com.gregtechceu.gtceu.api.item.IComponentItem; import com.gregtechceu.gtceu.api.item.IGTTool; import com.gregtechceu.gtceu.client.model.item.CustomItemRendererWrapperModel; @@ -190,6 +191,7 @@ public int getTintColor(@NotNull FluidStack stack) { @SubscribeEvent(priority = EventPriority.HIGHEST) public static void preRegisterDynamicAssets(RegisterDynamicResourcesEvent event) { PipeModel.DYNAMIC_MODELS.clear(); + MaterialIconType.invalidateCaches(); } @SubscribeEvent diff --git a/src/main/java/com/gregtechceu/gtceu/client/bloom/BloomRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/bloom/BloomRenderer.java index 1e681964976..e20d92a43cc 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/bloom/BloomRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/bloom/BloomRenderer.java @@ -60,8 +60,7 @@ public class BloomRenderer { @Accessors(fluent = true) @Getter @ApiStatus.Internal - static final ThreadLocal>> bloomChunkContext = ThreadLocal - .withInitial(ScopedValue.Object::new); + static final ScopedValue.Object> bloomChunkContext = new ScopedValue.Object<>(); @ApiStatus.Internal static void renderBloom(Camera camera, PoseStack poseStack, Frustum frustum, Matrix4f frustumMatrix, @@ -199,7 +198,7 @@ public static void copyBloomQuad(BakedQuad quad, int[] packedLights, @Nullable R } if (TextureMetadataHelper.hasBloom(quad, packedLights)) { - Supplier currentVertexConsumer = bloomChunkContext().get().getValue(); + Supplier currentVertexConsumer = bloomChunkContext().getValue(); if (currentVertexConsumer == null) return; drawConsumer.accept(currentVertexConsumer.get()); diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/FluidBlockRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/FluidBlockRenderer.java index 0ee215e894f..a0d47d5f43c 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/block/FluidBlockRenderer.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/block/FluidBlockRenderer.java @@ -59,6 +59,8 @@ public void drawBlocks(Set offsets, PoseStack poseStack, VertexConsume int combinedOverlay, int combinedLight) { var fluidClientInfo = IClientFluidTypeExtensions.of(fluid); var sprite = texture.map(fluidClientInfo); + if (sprite == null) return; + float u0 = sprite.getU0(), v0 = sprite.getV0(), u1 = sprite.getU1(), v1 = sprite.getV1(); int color = fluidClientInfo.getTintColor(); @@ -95,6 +97,8 @@ public void drawPlane(Direction face, Collection offsets, int combinedOverlay, BlockPos origin, @Nullable BlockAndTintGetter level) { var fluidClientInfo = IClientFluidTypeExtensions.of(fluid); var sprite = texture.map(fluidClientInfo); + if (sprite == null) return; + float u0 = sprite.getU0(), v0 = sprite.getV0(), u1 = sprite.getU1(), v1 = sprite.getV1(); int color = fluidClientInfo.getTintColor(); Vector3fc normal = getNormal(face); @@ -114,6 +118,8 @@ public void drawPlane(Direction face, Collection offsets, PoseStack po Fluid fluid, RenderUtil.FluidTextureType texture, int combinedOverlay, int combinedLight) { var fluidClientInfo = IClientFluidTypeExtensions.of(fluid); var sprite = texture.map(fluidClientInfo); + if (sprite == null) return; + float u0 = sprite.getU0(), v0 = sprite.getV0(), u1 = sprite.getU1(), v1 = sprite.getV1(); int color = fluidClientInfo.getTintColor(); Vector3fc normal = getNormal(face); @@ -133,6 +139,8 @@ public void drawFace(Direction face, PoseStack.Pose pose, VertexConsumer consume int combinedOverlay, int combinedLight) { var fluidClientInfo = IClientFluidTypeExtensions.of(fluid); var sprite = texture.map(fluidClientInfo); + if (sprite == null) return; + float u0 = sprite.getU0(), v0 = sprite.getV0(), u1 = sprite.getU1(), v1 = sprite.getV1(); int color = fluidClientInfo.getTintColor(); Vector3fc normal = getNormal(face); diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/InvertedFluidRenderer.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/InvertedFluidRenderer.java new file mode 100644 index 00000000000..f2fd7f91fc2 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/InvertedFluidRenderer.java @@ -0,0 +1,78 @@ +package com.gregtechceu.gtceu.client.renderer.fluid; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.GTValues; +import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.integration.embeddium.GTEmbeddiumCompat; +import com.gregtechceu.gtceu.integration.sodium.GTSodiumCompat; +import com.gregtechceu.gtceu.utils.ScopedValue; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.neoforged.neoforge.fluids.FluidType; + +import com.mojang.blaze3d.vertex.VertexConsumer; +import lombok.experimental.UtilityClass; + +import java.util.concurrent.atomic.AtomicBoolean; + +import static net.minecraft.core.SectionPos.SECTION_MASK; + +@UtilityClass +public class InvertedFluidRenderer { + + public static final ScopedValue.Boolean INVERTED_FLUID_RENDERING = new ScopedValue.Boolean(false); + + private static final ThreadLocal posScratch = ThreadLocal + .withInitial(BlockPos.MutableBlockPos::new); + private static final AtomicBoolean CAN_RENDER_USING_SODIUM_EMBEDDIUM = new AtomicBoolean( + GTCEu.Mods.isSodiumEmbeddiumLoaded()); + + public static boolean maybeRenderFluidInverted(FluidType fluidType, FluidState fluidState, BlockState blockState, + BlockAndTintGetter level, BlockPos pos, + VertexConsumer vertexConsumer) { + // this ends up calling itself intentionally; we set a state where we flip the fluid blocks' vertices + if (INVERTED_FLUID_RENDERING.isActive()) { + // exit early on the loop back so the fluid renderer thinks it can continue along as normal + return false; + } + // config isn't enabled -> use normal rendering + if (!ConfigHolder.INSTANCE.gameplay.lowDensityFluidsFlowUp || + !ConfigHolder.INSTANCE.client.lowDensityFluidsRenderUpsideDown) { + return false; + } + // fluid isn't lighter than air -> use normal rendering + if (!fluidType.isLighterThanAir()) { + return false; + } + + try (var $ = INVERTED_FLUID_RENDERING.setActive()) { + BlockPos.MutableBlockPos offset = posScratch.get(); + offset.set(pos.getX() & SECTION_MASK, pos.getY() & SECTION_MASK, pos.getZ() & SECTION_MASK); + + if (CAN_RENDER_USING_SODIUM_EMBEDDIUM.get()) { + + boolean didRender = false; + if (GTCEu.isModLoaded(GTValues.MODID_SODIUM)) { + didRender = GTSodiumCompat.renderFluidBlock(blockState, fluidState, level, pos, offset); + } else if (GTCEu.isModLoaded(GTValues.MODID_EMBEDDIUM)) { + didRender = GTEmbeddiumCompat.renderFluidBlock(blockState, fluidState, level, pos, offset); + } + if (didRender) { + return true; + } else { + CAN_RENDER_USING_SODIUM_EMBEDDIUM.set(false); + } + } + + // this part of the function is only ran if sodium/embeddium isn't installed or something went wrong with + // rendering the fluid with them. + Minecraft.getInstance().getBlockRenderer().renderLiquid(pos, level, vertexConsumer, blockState, fluidState); + } + + return true; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/package-info.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/package-info.java new file mode 100644 index 00000000000..59888706149 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/fluid/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package com.gregtechceu.gtceu.client.renderer.fluid; + +import org.jetbrains.annotations.NotNullByDefault; diff --git a/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/QuantumTankFluidRender.java b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/QuantumTankFluidRender.java index f097574497d..8fab183c288 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/QuantumTankFluidRender.java +++ b/src/main/java/com/gregtechceu/gtceu/client/renderer/machine/impl/QuantumTankFluidRender.java @@ -101,6 +101,7 @@ public void renderTank(PoseStack poseStack, MultiBufferSource buffer, Direction var ext = IClientFluidTypeExtensions.of(fluid.getFluid()); var fluidSprite = RenderUtil.FluidTextureType.STILL.map(ext, fluid); + if (fluidSprite == null) return; EnumSet sidesToRender = EnumSet.of(frontFacing); VertexConsumer builder = buffer.getBuffer(Sheets.translucentCullBlockSheet()); diff --git a/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java b/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java index 9a03b464c98..1b940377311 100644 --- a/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/client/util/RenderUtil.java @@ -25,17 +25,18 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; import net.minecraft.world.phys.Vec3; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.client.model.data.ModelData; +import net.neoforged.neoforge.client.textures.FluidSpriteCache; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.crafting.SizedFluidIngredient; @@ -49,7 +50,6 @@ import java.lang.Math; import java.util.*; -import java.util.function.BiFunction; import static net.minecraft.util.FastColor.ARGB32.*; @@ -58,37 +58,77 @@ public class RenderUtil { public enum FluidTextureType { - STILL((fluidTypeExtensions, fluidStack) -> { - if (!fluidStack.isEmpty()) return fluidTypeExtensions.getStillTexture(fluidStack); - else return fluidTypeExtensions.getStillTexture(); - }), - FLOWING((fluidTypeExtensions, fluidStack) -> { - if (!fluidStack.isEmpty()) return fluidTypeExtensions.getFlowingTexture(fluidStack); - else return fluidTypeExtensions.getFlowingTexture(); - }), - OVERLAY((fluidTypeExtensions, fluidStack) -> { - if (!fluidStack.isEmpty()) return fluidTypeExtensions.getOverlayTexture(fluidStack); - else return fluidTypeExtensions.getOverlayTexture(); - }); - - private static final ResourceLocation WATER_STILL = ResourceLocation.withDefaultNamespace("block/water_still"); - - private final BiFunction mapper; - - FluidTextureType(BiFunction mapper) { - this.mapper = mapper; - } + STILL { + + @Override + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, FluidStack stack) { + if (!stack.isEmpty()) return fluidTypeExtensions.getStillTexture(stack); + else return fluidTypeExtensions.getStillTexture(); + } + + @Override + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, + FluidState state, BlockAndTintGetter getter, BlockPos pos) { + if (!state.isEmpty()) return fluidTypeExtensions.getStillTexture(state, getter, pos); + else return fluidTypeExtensions.getStillTexture(); + } + }, + FLOWING { + + @Override + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, FluidStack stack) { + if (!stack.isEmpty()) return fluidTypeExtensions.getFlowingTexture(stack); + else return fluidTypeExtensions.getFlowingTexture(); + } + + @Override + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, + FluidState state, BlockAndTintGetter getter, BlockPos pos) { + if (!state.isEmpty()) return fluidTypeExtensions.getFlowingTexture(state, getter, pos); + else return fluidTypeExtensions.getFlowingTexture(); + } + }, + OVERLAY { + + @Override + @Nullable + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, FluidStack stack) { + if (!stack.isEmpty()) return fluidTypeExtensions.getOverlayTexture(stack); + else return fluidTypeExtensions.getOverlayTexture(); + } + + @Override + @Nullable + ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, + FluidState state, BlockAndTintGetter getter, BlockPos pos) { + if (!state.isEmpty()) return fluidTypeExtensions.getOverlayTexture(state, getter, pos); + else return fluidTypeExtensions.getOverlayTexture(); + } + }; + + abstract @Nullable ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, + FluidStack stack); - public TextureAtlasSprite map(IClientFluidTypeExtensions fluidTypeExtensions) { + abstract @Nullable ResourceLocation getFluidTexture(IClientFluidTypeExtensions fluidTypeExtensions, + FluidState state, BlockAndTintGetter getter, BlockPos pos); + + public @Nullable TextureAtlasSprite map(IClientFluidTypeExtensions fluidTypeExtensions) { return map(fluidTypeExtensions, FluidStack.EMPTY); } - public TextureAtlasSprite map(IClientFluidTypeExtensions fluidTypeExtensions, FluidStack fluidStack) { - ResourceLocation texture = mapper.apply(fluidTypeExtensions, fluidStack); - if (texture == null) texture = STILL.mapper.apply(fluidTypeExtensions, fluidStack); - if (texture == null) texture = WATER_STILL; + public @Nullable TextureAtlasSprite map(IClientFluidTypeExtensions fluidTypeExtensions, FluidStack stack) { + ResourceLocation texture = getFluidTexture(fluidTypeExtensions, stack); + if (texture == null) return null; + + return FluidSpriteCache.getSprite(texture); + } + + public @Nullable TextureAtlasSprite map(IClientFluidTypeExtensions fluidTypeExtensions, + FluidState state, BlockAndTintGetter getter, BlockPos pos) { + ResourceLocation texture = getFluidTexture(fluidTypeExtensions, state, getter, pos); + if (texture == null) return null; - return Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture); + return FluidSpriteCache.getSprite(texture); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/block/GTLiquidBlock.java b/src/main/java/com/gregtechceu/gtceu/common/block/GTLiquidBlock.java new file mode 100644 index 00000000000..52ae20210c6 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/block/GTLiquidBlock.java @@ -0,0 +1,23 @@ +package com.gregtechceu.gtceu.common.block; + +import com.gregtechceu.gtceu.api.fluids.GTFluid; + +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.level.block.LiquidBlock; + +public class GTLiquidBlock extends LiquidBlock { + + public GTLiquidBlock(GTFluid fluid, Properties properties) { + super(fluid, properties); + } + + @Override + public String getDescriptionId() { + return this.fluid.getFluidType().getDescriptionId(); + } + + @Override + public MutableComponent getName() { + return this.fluid.getFluidType().getDescription().copy(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/blockentity/FluidPipeBlockEntity.java b/src/main/java/com/gregtechceu/gtceu/common/blockentity/FluidPipeBlockEntity.java index ebb47d345d5..6ae97de3ee8 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/blockentity/FluidPipeBlockEntity.java +++ b/src/main/java/com/gregtechceu/gtceu/common/blockentity/FluidPipeBlockEntity.java @@ -253,7 +253,7 @@ public void checkAndDestroy(@NotNull FluidStack stack) { FluidPipeProperties prop = getNodeData(); boolean burning = prop.getMaxFluidTemperature() < fluid.getFluidType().getTemperature(stack); - boolean leaking = !prop.isGasProof() && fluid.getFluidType().getDensity(stack) < 0; + boolean leaking = !prop.isGasProof() && fluid.getFluidType().isLighterThanAir(); boolean shattering = !prop.isCryoProof() && fluid.getFluidType().getTemperature(stack) < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; boolean corroding = false; diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java index bd36ec0108a..c48467d7ece 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/ElementMaterials.java @@ -989,7 +989,7 @@ public static void register() { Neutronium = new Material.Builder(GTCEu.id("neutronium")) .ingot(6) - .liquid(new FluidBuilder().temperature(100_000)) + .liquid(new FluidBuilder().block().temperature(100_000).density(-1000)) .color(0xFFFFFF).secondaryColor(0x000000) .appendFlags(EXT_METAL, GENERATE_BOLT_SCREW, GENERATE_FRAME, GENERATE_GEAR, GENERATE_LONG_ROD) .element(GTElements.Nt) diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java b/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java index 92d8f38fe5f..ede18ba9f99 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/models/GTModels.java @@ -16,13 +16,16 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.models.BlockModelGenerators; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.GsonHelper; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.client.model.generators.ConfiguredModel; import net.neoforged.neoforge.client.model.generators.ModelFile; import net.neoforged.neoforge.client.model.generators.ModelProvider; @@ -332,28 +335,56 @@ public static void registerMaterialFluidModels() { MixinHelpers.addFluidTexture(material, fluidEntry); } - // bucket models. Fluid fluid = storage.get(key); - if (fluid instanceof GTFluid gtFluid) { - // read the base bucket model JSON - JsonObject original; - try (BufferedReader reader = Minecraft.getInstance().getResourceManager() - .openAsReader(GTCEu.id("models/item/bucket/bucket.json"))) { - original = GsonHelper.parse(reader, true); - } catch (IOException e) { - throw new RuntimeException(e); - } - - JsonObject newJson = original.deepCopy(); - newJson.addProperty("fluid", BuiltInRegistries.FLUID.getKey(gtFluid).toString()); - if (gtFluid.getFluidType().isLighterThanAir()) { - newJson.addProperty("flip_gas", true); - } - if (gtFluid.getFluidType().getLightLevel() > 0) { - newJson.addProperty("apply_fluid_luminosity", true); - } - - GTDynamicResourcePack.addItemModel(BuiltInRegistries.ITEM.getKey(gtFluid.getBucket()), newJson); + if (!(fluid instanceof GTFluid gtFluid)) { + continue; + } + // bucket models + // read the base bucket model JSON + JsonObject original; + try (BufferedReader reader = Minecraft.getInstance().getResourceManager() + .openAsReader(GTCEu.id("models/item/bucket/bucket.json"))) { + original = GsonHelper.parse(reader, true); + } catch (IOException e) { + throw new RuntimeException(e); + } + + JsonObject newJson = original.deepCopy(); + newJson.addProperty("fluid", BuiltInRegistries.FLUID.getKey(gtFluid).toString()); + if (gtFluid.getFluidType().isLighterThanAir()) { + newJson.addProperty("flip_gas", true); + } + if (gtFluid.getFluidType().getLightLevel() > 0) { + newJson.addProperty("apply_fluid_luminosity", true); + } + + GTDynamicResourcePack.addItemModel(BuiltInRegistries.ITEM.getKey(gtFluid.getBucket()), newJson); + + // --- separator --- + + // block models + BlockState fluidBlockState = fluid.defaultFluidState().createLegacyBlock(); + if (!fluidBlockState.isAir()) { + Block fluidBlock = fluidBlockState.getBlock(); + ResourceLocation blockId = BuiltInRegistries.BLOCK.getKey(fluidBlock); + ResourceLocation modelId = blockId.withPrefix("block/"); + + GTDynamicResourcePack.addBlockState(blockId, + BlockModelGenerators.createSimpleBlock(fluidBlock, modelId)); + + ResourceLocation stillTexture = IClientFluidTypeExtensions.of(fluid).getStillTexture(); + GTDynamicResourcePack.addBlockModel(modelId, () -> { + JsonObject root = new JsonObject(); + + JsonObject textures = new JsonObject(); + // noinspection ConstantValue + if (stillTexture != null) { + textures.addProperty("particle", stillTexture.toString()); + } + + root.add("textures", textures); + return root; + }); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/GTBucketItem.java b/src/main/java/com/gregtechceu/gtceu/common/item/GTBucketItem.java index f217cbb5126..e1bc93e8d7f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/GTBucketItem.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/GTBucketItem.java @@ -15,12 +15,10 @@ public class GTBucketItem extends BucketItem { final Material material; - final String langKey; - public GTBucketItem(Fluid fluid, Properties properties, Material material, String langKey) { + public GTBucketItem(Fluid fluid, Properties properties, Material material) { super(fluid, properties); this.material = material; - this.langKey = langKey; } public static int color(ItemStack itemStack, int index) { @@ -39,8 +37,7 @@ public String getDescriptionId() { @Override public Component getDescription() { - Component materialName = material.getLocalizedName(); - return Component.translatable("item.gtceu.bucket", Component.translatable(this.langKey, materialName)); + return Component.translatable(getDescriptionId(), this.content.getFluidType().getDescription()); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java index 2bba245aa32..af292b38199 100644 --- a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java +++ b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java @@ -818,6 +818,25 @@ public static class GameplayConfigs { "Default: 0.001" }) public float environmentalHazardDecayRate = 0.001f; @Configurable + @Configurable.Comment({ + "Whether or not low density fluid blocks (such as gases and plasmas) should flow up or not.", + "May cause bugs or odd interactions with other mods. Disable this if that happens to you.", + "Default: true" }) + @Configurable.Synchronized + public boolean lowDensityFluidsFlowUp = true; + @Configurable + @Configurable.Comment({ + "Whether or not gases and plasmas should vaporize when placed from a bucket (like water does in the Nether).", + "Default: true" }) + @Configurable.Synchronized + public boolean gasesVaporizeOnPlacement = true; + @Configurable + @Configurable.Comment({ + "Whether or not ALL GT fluids have blocks by default. Individual fluids can override this option.", + "Default: false" }) + @Configurable.UpdateRestriction(UpdateRestrictions.GAME_RESTART) + public boolean allFluidsHaveBlocks = false; + @Configurable @Configurable.Comment({ "List of domains that are allowed in the image module" }) public String[] allowedImageDomains = new String[] { "imgur.com", "discord.com", "github.com", "raw.githubusercontent.com" }; @@ -860,6 +879,14 @@ public static class ClientConfigs { @Configurable.Range(min = 1, max = 999) public int inWorldPreviewDuration = 10; @Configurable + @Configurable.Comment({ "If enabled, low density fluid blocks (such as gases and plasmas) render upside down.", + "May cause weird visuals or crashes with other mods, so try disabling this if you're having issues.", + "This config doesn't do anything if gameplay.lowDensityFluidsFlowUp is disabled.", + "Note that things may look especially weird if that config is enabled but this one isn't.", + "Default: true" }) + @Configurable.Synchronized + public boolean lowDensityFluidsRenderUpsideDown = true; + @Configurable public ArmorHud armorHud = new ArmorHud(); @Configurable public RendererOptions renderer = new RendererOptions(); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/WorldLoaderMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/WorldLoaderMixin.java index 0ecae28b9cd..e4a8ff3a3db 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/WorldLoaderMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/WorldLoaderMixin.java @@ -20,8 +20,7 @@ public class WorldLoaderMixin { @Inject(method = "load", at = @At(value = "INVOKE", - target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;", - shift = At.Shift.BEFORE)) + target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/world/flag/FeatureFlagSet;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) private static void gtceu$postKJSVeinEvents(CallbackInfoReturnable> cir, @Local(ordinal = 1) LayeredRegistryAccess layered) { MixinHelpers.postKJSVeinEvents(layered.compositeAccess()); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/AbstractWidgetMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/AbstractWidgetMixin.java deleted file mode 100644 index abb3918d7d1..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/AbstractWidgetMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.gregtechceu.gtceu.core.mixins.client; - -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.gui.components.AbstractWidget; - -import brachy.modularui.overlay.OverlayStack; -import org.objectweb.asm.Opcodes; -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; - -/** - * This mixin fixes some visual bugs that can happen with overlays. - */ -@Mixin(AbstractWidget.class) -public abstract class AbstractWidgetMixin { - - @Shadow - protected boolean isHovered; - - @Inject(method = "render", - at = @At(value = "FIELD", - opcode = Opcodes.PUTFIELD, - target = "Lnet/minecraft/client/gui/components/AbstractWidget;isHovered:Z")) - public void gtceu$fixHoveredState(GuiGraphics guiGraphics, int mouseX, int mouseY, - float partialTick, CallbackInfo ci) { - // fixes buttons being hovered when an overlay element is already hovered - this.isHovered &= !OverlayStack.isHoveringOverlay(); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GameRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GameRendererMixin.java deleted file mode 100644 index 9073c7bc439..00000000000 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GameRendererMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.gregtechceu.gtceu.core.mixins.client; - -import com.gregtechceu.gtceu.core.IGameRenderer; - -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GameRenderer; - -import com.mojang.blaze3d.vertex.PoseStack; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(GameRenderer.class) -public abstract class GameRendererMixin implements IGameRenderer { - - @Shadow - @Final - Minecraft minecraft; - - @Shadow - protected abstract double getFov(Camera activeRenderInfo, float partialTicks, boolean useFOVSetting); - - @Shadow - @Final - private Camera mainCamera; - - @Shadow - protected abstract void bobHurt(PoseStack poseStack, float partialTicks); - - @Shadow - protected abstract void bobView(PoseStack poseStack, float partialTicks); - - @Override - public double gtceu$getFov(float partialTicks) { - return getFov(mainCamera, partialTicks, true); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GuiGraphicsMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GuiGraphicsMixin.java index 182f57a05bd..3b6048e39f5 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GuiGraphicsMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/GuiGraphicsMixin.java @@ -1,42 +1,20 @@ package com.gregtechceu.gtceu.core.mixins.client; import com.gregtechceu.gtceu.client.util.RenderUtil; -import com.gregtechceu.gtceu.config.ConfigHolder; -import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.FormattedText; -import net.minecraft.util.FormattedCharSequence; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.inventory.tooltip.TooltipComponent; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import brachy.modularui.drawable.text.FontRenderHelper; -import brachy.modularui.screen.RichTooltip; -import brachy.modularui.screen.viewport.GuiContext; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.sugar.Local; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; @Mixin(GuiGraphics.class) public abstract class GuiGraphicsMixin { - @Shadow(remap = false) - private ItemStack tooltipStack; - @WrapMethod(method = "renderItem(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;IIII)V") private void gtceu$renderResearchItemContent(@Nullable LivingEntity entity, @Nullable Level level, ItemStack stack, int x, int y, int seed, int z, @@ -46,85 +24,4 @@ public abstract class GuiGraphicsMixin { original.call(entity, level, stack, x, y, seed, z); } } - - @Inject(method = "renderTooltip(Lnet/minecraft/client/gui/Font;Ljava/util/List;Ljava/util/Optional;II)V", - at = @At(value = "HEAD"), - cancellable = true) - private void gtceu$replaceWithRichTooltip(Font font, List tooltipLines, - Optional visualComponent, int mouseX, int mouseY, - CallbackInfo ci) { - // funny cast to get from List to List - // I just don't want to copy the list unnecessarily - // this is safe because Component extends FormattedText - // noinspection unchecked - gtceu$drawRichTooltip(font, (List) (List) tooltipLines, visualComponent, mouseX, mouseY, ci); - } - - @Inject( - method = { - "renderTooltip(Lnet/minecraft/client/gui/Font;Ljava/util/List;Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;II)V", - "renderTooltip(Lnet/minecraft/client/gui/Font;Ljava/util/List;II)V" - }, - at = @At(value = "HEAD"), - cancellable = true) - private void gtceu$replaceWithRichTooltip(CallbackInfo ci, - @Local(argsOnly = true) Font font, - @Local(argsOnly = true) List tooltipLines, - @Local(ordinal = 0, argsOnly = true) int mouseX, - @Local(ordinal = 1, argsOnly = true) int mouseY) { - List text = tooltipLines.stream() - .map(FontRenderHelper::getComponentFromCharSequence) - .collect(Collectors.toList()); - gtceu$drawRichTooltip(font, text, Optional.empty(), mouseX, mouseY, ci); - } - - @Inject(method = "renderComponentTooltip*", - at = @At( - value = "INVOKE", - target = "Lnet/neoforged/neoforge/client/ClientHooks;gatherTooltipComponents(Lnet/minecraft/world/item/ItemStack;Ljava/util/List;IIILnet/minecraft/client/gui/Font;)Ljava/util/List;", - remap = false), - cancellable = true) - private void gtceu$replaceWithRichTooltip2(CallbackInfo ci, - @Local(argsOnly = true) Font font, - @Local(argsOnly = true) List tooltipLines, - @Local(ordinal = 0, argsOnly = true) int mouseX, - @Local(ordinal = 1, argsOnly = true) int mouseY) { - gtceu$drawRichTooltip(font, tooltipLines, Optional.empty(), mouseX, mouseY, ci); - } - - @Unique - private void gtceu$drawRichTooltip(Font font, List textLines, - Optional tooltipComponent, int mouseX, int mouseY, - CallbackInfo ci) { - if (!ConfigHolder.INSTANCE.client.ui.replaceVanillaTooltips || textLines.isEmpty()) { - return; - } - - RichTooltip tooltip = new RichTooltip(); - tooltip.parent(area -> RichTooltip.findIngredientArea(area, mouseX, mouseY)); - // Other positions don't really work due to the lack of GuiContext in non-modular uis - tooltip.add((Component) textLines.getFirst()).newLine(); - // vanilla inserts the bundle tooltip here so we need to do it as the 2nd item too - tooltipComponent.ifPresent(component -> tooltip.addLine(component.toString())); - - if (!this.tooltipStack.isEmpty()) { - tooltip.spaceLine(); - } - for (int i = 1, n = textLines.size(); i < n; i++) { - tooltip.add((Component) textLines.get(i)).newLine(); - } - - GuiContext context = GuiContext.getDefault(); - GuiGraphics lastGraphics = context.getGraphics(); - - context.setOverrideFont(font); - context.setGraphics((GuiGraphics) (Object) this); - tooltip.draw(context, this.tooltipStack); - - context.setGraphics(lastGraphics); - // the override font is removed at the end of RichTooltip#draw; no need to duplicate that here - - // Cancel vanilla tooltip rendering - ci.cancel(); - } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LiquidBlockRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LiquidBlockRendererMixin.java new file mode 100644 index 00000000000..d1b8bb68956 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/LiquidBlockRendererMixin.java @@ -0,0 +1,145 @@ +package com.gregtechceu.gtceu.core.mixins.client; + +import com.gregtechceu.gtceu.client.renderer.fluid.InvertedFluidRenderer; + +import net.minecraft.client.renderer.block.LiquidBlockRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(value = LiquidBlockRenderer.class, remap = false) +public class LiquidBlockRendererMixin { + + @ModifyArg(method = "tesselate", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/block/LiquidBlockRenderer;vertex(Lcom/mojang/blaze3d/vertex/VertexConsumer;FFFFFFFFFI)V"), + index = 2, + require = 16) + private float gtceu$invertFluidFlowDirection(float originalY, + @Local(ordinal = 14) float sectionY) { + // sadly we can't cache this in the vanilla fluid renderer because it's a singleton instance + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + return sectionY + (1.0f - (originalY - sectionY)); + } else { + return originalY; + } + } + + @ModifyArgs(method = "isFaceOccludedByState", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/phys/shapes/Shapes;box(DDDDDD)Lnet/minecraft/world/phys/shapes/VoxelShape;")) + private static void gtceu$invertExposedSideCheckDirection(Args args) { + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + // set minY to original maxY + double maxY = args.get(4); + args.set(1, maxY); + // set maxY to 1 + args.set(4, 1.0D); + } + } + + // this direction replacement injection is split into 2 because we don't want to replace the UP shade query. + // this one handles everything up to (and including) the first level.getShade call + @ModifyExpressionValue(method = "tesselate", + at = { + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;UP:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC), + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;DOWN:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC) + }, + slice = @Slice(to = @At(value = "INVOKE", + target = "Lnet/minecraft/world/level/BlockAndTintGetter;getShade(Lnet/minecraft/core/Direction;Z)F", + ordinal = 0)), + require = 5) + private Direction gtceu$invertFluidCulling(Direction original) { + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + return original.getOpposite(); + } else { + return original; + } + } + + // and this handles the one instance of Direction.UP after those. + @Definition(id = "isFaceOccludedByNeighbor", + method = "Lnet/minecraft/client/renderer/block/LiquidBlockRenderer;isFaceOccludedByNeighbor(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;FLnet/minecraft/world/level/block/state/BlockState;)Z") + @Definition(id = "UP", field = "Lnet/minecraft/core/Direction;UP:Lnet/minecraft/core/Direction;") + @Expression("isFaceOccludedByNeighbor(?, ?, UP, ?, ?)") + @ModifyArg(method = "tesselate", at = @At("MIXINEXTRAS:EXPRESSION")) + private Direction gtceu$invertFluidCulling2(Direction original) { + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + return original.getOpposite(); + } else { + return original; + } + } + + @Definition(id = "vertex", + method = "Lnet/minecraft/client/renderer/block/LiquidBlockRenderer;vertex(Lcom/mojang/blaze3d/vertex/VertexConsumer;FFFFFFFFFI)V") + @Definition(id = "sectionX", local = @Local(type = float.class, ordinal = 13)) + @Definition(id = "sectionZ", local = @Local(type = float.class, ordinal = 15)) + @Expression({ + "this.vertex(?, sectionX, ?, sectionZ, ?, ?, ?, ?, ?, ?, ?)", + "this.vertex(?, sectionX + 1.0, ?, sectionZ + 1.0, ?, ?, ?, ?, ?, ?, ?)", + }) + @ModifyArgs(method = "tesselate", + at = @At("MIXINEXTRAS:EXPRESSION"), + slice = @Slice( + from = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;getU0()F"), + to = @At(value = "INVOKE", + target = "Lnet/minecraft/client/renderer/block/LiquidBlockRenderer;getLightColor(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/core/BlockPos;)I", + ordinal = 2)), + require = 2, + allow = 2) + private void gtceu$invertBottomQuadsOrder(Args args, + @Local(ordinal = 13) float localXOffset, + @Local(ordinal = 15) float localZOffset) { + // swap the 1st and 3rd vertex's position to invert the quad's orientation + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + float x = args.get(1); + float z = args.get(3); + if (x == localXOffset && z == localZOffset) { + args.set(1, x + 1.0F); + args.set(3, z + 1.0F); + } else { + args.set(1, x - 1.0F); + args.set(3, z - 1.0F); + } + } + } + + @WrapOperation(method = { "tesselate", "getHeight*", "getLightColor" }, + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;above()Lnet/minecraft/core/BlockPos;"), + require = 3) + private BlockPos gtceu$invertFluidLightCheckAbove(BlockPos pos, Operation original) { + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + return pos.below(); + } else { + return original.call(pos); + } + } + + @WrapOperation(method = "tesselate", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;below()Lnet/minecraft/core/BlockPos;")) + private BlockPos gtceu$invertFluidLightCheckBelow(BlockPos pos, Operation original) { + if (InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive()) { + return pos.above(); + } else { + return original.call(pos); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/MinecraftAccessor.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/MinecraftAccessor.java new file mode 100644 index 00000000000..d3e2de5be11 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/MinecraftAccessor.java @@ -0,0 +1,13 @@ +package com.gregtechceu.gtceu.core.mixins.client; + +import net.minecraft.client.Minecraft; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Minecraft.class) +public interface MinecraftAccessor { + + @Accessor("gameThread") + Thread gtceu$getGameThread(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java index e06a756efb9..1516fcfe4fe 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/TextureAtlasMixin.java @@ -41,8 +41,8 @@ public class TextureAtlasMixin implements SpriteFinder.SpriteFinderAccess { @Unique private SpriteFinder gtceu$spriteFinder = null; - @Inject(at = @At("TAIL"), method = "upload") - private void uploadHook(SpriteLoader.Preparations preparations, CallbackInfo info) { + @Inject(method = "upload", at = @At("TAIL")) + private void gtceu$clearSpriteFinder(SpriteLoader.Preparations preparations, CallbackInfo info) { gtceu$spriteFinder = null; } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/LightPipelineAwareModelBlockRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/LightPipelineAwareModelBlockRendererMixin.java index 0d657fb6358..a5a9b795dd5 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/LightPipelineAwareModelBlockRendererMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/LightPipelineAwareModelBlockRendererMixin.java @@ -27,7 +27,7 @@ public class LightPipelineAwareModelBlockRendererMixin { @Definition(id = "pos", local = @Local(type = BlockPos.class, argsOnly = true)) @Definition(id = "state", local = @Local(type = BlockState.class, argsOnly = true)) @Expression("@(?).setup(level, pos, state)") - @ModifyExpressionValue(method = "render", at = @At(value = "MIXINEXTRAS:EXPRESSION")) + @ModifyExpressionValue(method = "render", at = @At(value = "MIXINEXTRAS:EXPRESSION"), require = 4) private static QuadLighter gtceu$setQuadLighterRenderType(QuadLighter lighter, @Local(argsOnly = true) RenderType renderType) { ((QuadLighterExt) lighter).gtceu$setRenderType(renderType); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/ModelBlockRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/ModelBlockRendererMixin.java index efa2d04ac4b..b68faae75f3 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/ModelBlockRendererMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/ModelBlockRendererMixin.java @@ -26,19 +26,18 @@ public class ModelBlockRendererMixin { @Unique - private static final ThreadLocal> gtceu$currentRenderType = ThreadLocal - .withInitial(ScopedValue.Object::new); + private static final ScopedValue.Object gtceu$currentRenderType = new ScopedValue.Object<>(); @WrapMethod(method = { "tesselateWithAO(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZLnet/minecraft/util/RandomSource;JILnet/neoforged/neoforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V", "tesselateWithoutAO(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZLnet/minecraft/util/RandomSource;JILnet/neoforged/neoforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V" - }, remap = false) + }, remap = false, require = 2) private void gtceu$copyBloomQuads$1(BlockAndTintGetter level, BakedModel model, BlockState state, BlockPos pos, PoseStack poseStack, VertexConsumer consumer, boolean checkSides, RandomSource random, long seed, int packedOverlay, ModelData modelData, RenderType renderType, Operation original) { - try (var $ = gtceu$currentRenderType.get().with(renderType)) { + try (var $ = gtceu$currentRenderType.with(renderType)) { original.call(level, model, state, pos, poseStack, consumer, checkSides, random, seed, packedOverlay, modelData, renderType); } @@ -56,7 +55,7 @@ public class ModelBlockRendererMixin { if (!BloomShaderManager.isBloomActive()) return; - RenderType renderType = gtceu$currentRenderType.get().getValue(); + RenderType renderType = gtceu$currentRenderType.getValue(); BloomRenderer.copyBloomQuad(quad, lightmap, renderType, bloomVertexConsumer -> { original.call(bloomVertexConsumer, pose, quad, brightness, red, green, blue, alpha, lightmap, overlay, readAlpha); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/SectionCompilerMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/SectionCompilerMixin.java index 051ac8c2ddd..d1089324460 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/SectionCompilerMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/bloom/SectionCompilerMixin.java @@ -51,7 +51,7 @@ protected abstract BufferBuilder getOrBeginLayer(Map } }; // intentionally no try-with-resource statement; closed in 'gtceu$clearBloomContextData' - BloomRenderer.bloomChunkContext().get().with(provider); + BloomRenderer.bloomChunkContext().with(provider); } @Inject(method = "compile(Lnet/minecraft/core/SectionPos;Lnet/minecraft/client/renderer/chunk/RenderChunkRegion;Lcom/mojang/blaze3d/vertex/VertexSorting;Lnet/minecraft/client/renderer/SectionBufferBuilderPack;Ljava/util/List;)Lnet/minecraft/client/renderer/chunk/SectionCompiler$Results;", @@ -66,6 +66,6 @@ protected abstract BufferBuilder getOrBeginLayer(Map BloomRenderer.SafeMode.bakeBloomChunkBuffers(sectionPos, vertexSorting); } - BloomRenderer.bloomChunkContext().get().close(); + BloomRenderer.bloomChunkContext().close(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/embeddium/EmbeddiumFluidRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/embeddium/EmbeddiumFluidRendererMixin.java new file mode 100644 index 00000000000..4cac7eac462 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/embeddium/EmbeddiumFluidRendererMixin.java @@ -0,0 +1,156 @@ +package com.gregtechceu.gtceu.core.mixins.client.embeddium; + +import com.gregtechceu.gtceu.client.renderer.fluid.InvertedFluidRenderer; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import org.embeddedt.embeddium.impl.model.quad.properties.ModelQuadFacing; +import org.embeddedt.embeddium.impl.render.chunk.compile.pipeline.FluidRenderer; +import org.objectweb.asm.Opcodes; +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.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyArgs; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(value = FluidRenderer.class, remap = false) +public class EmbeddiumFluidRendererMixin { + + @Unique + private boolean gtceu$drawingUpsideDownFluid = false; + + @Inject(method = "render", at = @At("HEAD")) + private void gtceu$cacheInvertedState(CallbackInfo ci) { + gtceu$drawingUpsideDownFluid = InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive(); + } + + @Inject(method = "render", at = @At("RETURN")) + private void gtceu$resetInvertedState(CallbackInfo ci) { + gtceu$drawingUpsideDownFluid = false; + } + + @ModifyArg(method = "render", + at = @At(value = "INVOKE", + target = "Lorg/embeddedt/embeddium/impl/render/chunk/compile/pipeline/FluidRenderer;setVertex(Lorg/embeddedt/embeddium/impl/model/quad/ModelQuadViewMutable;IFFFFF)V"), + index = 3, + require = 16) + private float gtceu$invertFluidFlowDirection(float originalY) { + if (gtceu$drawingUpsideDownFluid) { + return 1.0f - originalY; + } else { + return originalY; + } + } + + @Definition(id = "shouldRenderBackwardUpFace", + method = "Lnet/minecraft/world/level/material/FluidState;shouldRenderBackwardUpFace(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z") + @Definition(id = "scratchPos", + field = "Lorg/embeddedt/embeddium/impl/render/chunk/compile/pipeline/FluidRenderer;scratchPos:Lnet/minecraft/core/BlockPos$MutableBlockPos;") + @Definition(id = "set", + method = "Lnet/minecraft/core/BlockPos$MutableBlockPos;set(III)Lnet/minecraft/core/BlockPos$MutableBlockPos;") + @Expression("?.shouldRenderBackwardUpFace(?, @(this.scratchPos.set(?, ? + 1, ?)))") + @ModifyArg(method = "render", at = @At("MIXINEXTRAS:EXPRESSION"), index = 1) + private int gtceu$invertFluidBackwardUpFaceCheckDirection(int posY) { + if (gtceu$drawingUpsideDownFluid) { + // `posY - 2` because the original function already did `posY + 1` + return posY - 2; + } else { + return posY; + } + } + + @ModifyArgs(method = "isSideExposed", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/phys/shapes/Shapes;box(DDDDDD)Lnet/minecraft/world/phys/shapes/VoxelShape;")) + private void gtceu$invertFluidBackwardUpFaceCheckDirection(Args args) { + if (gtceu$drawingUpsideDownFluid) { + // set minY to original maxY + double maxY = args.get(4); + args.set(1, maxY); + // set maxY to 1 + args.set(4, 1.0D); + } + } + + @ModifyExpressionValue(method = { "render", "fluidCornerHeight", "isSideExposed" }, + at = { + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;UP:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC), + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;DOWN:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC) + }, + require = 9) + private Direction gtceu$invertFluidCulling(Direction original) { + if (gtceu$drawingUpsideDownFluid) { + return original.getOpposite(); + } else { + return original; + } + } + + @ModifyExpressionValue(method = "render", + at = { + @At(value = "FIELD", + target = "Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;POS_Y:Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;", + opcode = Opcodes.GETSTATIC), + @At(value = "FIELD", + target = "Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;NEG_Y:Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;", + opcode = Opcodes.GETSTATIC) + }, + require = 3) + private ModelQuadFacing gtceu$invertFluidFaceOrientation(ModelQuadFacing original) { + if (gtceu$drawingUpsideDownFluid) { + return original.getOpposite(); + } else { + return original; + } + } + + @Definition(id = "NEG_Y", field = "Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;NEG_Y") + @Definition(id = "writeQuad", + method = "Lorg/embeddedt/embeddium/impl/render/chunk/compile/pipeline/FluidRenderer;writeQuad(Lorg/embeddedt/embeddium/impl/render/chunk/compile/buffers/ChunkModelBuilder;Lorg/embeddedt/embeddium/impl/render/chunk/terrain/material/Material;Lnet/minecraft/core/BlockPos;Lorg/embeddedt/embeddium/impl/model/quad/ModelQuadView;Lorg/embeddedt/embeddium/impl/model/quad/properties/ModelQuadFacing;Z)V") + @Expression("this.writeQuad(?, ?, ?, ?, NEG_Y, false)") + @ModifyArg(method = "render", at = @At("MIXINEXTRAS:EXPRESSION"), allow = 1) + private boolean gtceu$invertBottomQuadsOrder(boolean flip) { + if (gtceu$drawingUpsideDownFluid) { + return !flip; + } else { + return flip; + } + } + + @WrapOperation(method = "*", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;above()Lnet/minecraft/core/BlockPos;"), + require = 0) + private BlockPos gtceu$invertFluidLightCheckAbove(BlockPos pos, Operation original) { + if (gtceu$drawingUpsideDownFluid) { + return pos.below(); + } else { + return original.call(pos); + } + } + + @WrapOperation(method = "*", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;below()Lnet/minecraft/core/BlockPos;"), + require = 0) + private BlockPos gtceu$invertFluidLightCheckBelow(BlockPos pos, Operation original) { + if (gtceu$drawingUpsideDownFluid) { + return pos.above(); + } else { + return original.call(pos); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/BlockOcclusionCacheMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/BlockOcclusionCacheMixin.java new file mode 100644 index 00000000000..91a8d8cd9d3 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/BlockOcclusionCacheMixin.java @@ -0,0 +1,37 @@ +package com.gregtechceu.gtceu.core.mixins.client.sodium; + +import com.gregtechceu.gtceu.core.util.extensions.sodium.BlockOcclusionCacheExt; + +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; +import net.minecraft.core.Direction; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(value = BlockOcclusionCache.class, remap = false) +public class BlockOcclusionCacheMixin implements BlockOcclusionCacheExt { + + @Unique + boolean gtceu$drawingUpsideDownFluid = false; + + @ModifyExpressionValue(method = "shouldDrawFullBlockFluidSide", + at = @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;UP:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC, + remap = true)) + private Direction gtceu$invertFluidCulling(Direction original) { + if (gtceu$drawingUpsideDownFluid) { + return original.getOpposite(); + } else { + return original; + } + } + + @Override + public void gtceu$drawingUpsideDownFluid(boolean drawingUpsideDownFluid) { + this.gtceu$drawingUpsideDownFluid = drawingUpsideDownFluid; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/ChunkBuilderMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/ChunkBuilderMixin.java new file mode 100644 index 00000000000..1f2cae61987 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/ChunkBuilderMixin.java @@ -0,0 +1,48 @@ +package com.gregtechceu.gtceu.core.mixins.client.sodium; + +import com.gregtechceu.gtceu.integration.sodium.GlobalChunkBuildContext; + +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildContext; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.executor.ChunkBuilder; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.executor.ChunkJob; +import net.caffeinemc.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; +import net.minecraft.client.multiplayer.ClientLevel; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +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.CallbackInfo; + +// priority 0 to always apply our mixin first to try and avoid bugs with gtceu$wrapThread +@Mixin(value = ChunkBuilder.class, remap = false, priority = 0) +public class ChunkBuilderMixin { + + @Inject(method = "", at = @At("HEAD")) + private static void gtceu$markAsMainThread(ClientLevel level, ChunkVertexType vertexType, CallbackInfo ci) { + GlobalChunkBuildContext.setMainThread(); + } + + @WrapOperation(method = "", at = @At(value = "NEW", target = "java/lang/Thread")) + private static Thread gtceu$wrapThread(Runnable task, String name, Operation original, + @Local(name = "context") ChunkBuildContext context) { + return new GlobalChunkBuildContext.WorkerThread(task, name, context); + } + + @Inject(method = "tryStealTask", + at = @At(value = "INVOKE", + target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJob;execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;)V")) + private static void gtceu$captureLocalContext(ChunkJob job, CallbackInfo ci, + @Local(name = "localContext") ChunkBuildContext localContext) { + GlobalChunkBuildContext.bindMainThread(localContext); + } + + @Inject(method = "tryStealTask", + at = @At(value = "INVOKE", + target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;cleanup()V")) + private static void gtceu$clearLocalContext(ChunkJob job, CallbackInfo ci) { + GlobalChunkBuildContext.bindMainThread(null); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/FluidRendererImplAccessor.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/FluidRendererImplAccessor.java new file mode 100644 index 00000000000..93861929eb9 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/FluidRendererImplAccessor.java @@ -0,0 +1,22 @@ +package com.gregtechceu.gtceu.core.mixins.client.sodium; + +import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; +import net.caffeinemc.mods.sodium.neoforge.render.FluidRendererImpl; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = FluidRendererImpl.class, remap = false) +public interface FluidRendererImplAccessor { + + // coerced to the accessor because the class is private + @Accessor("CURRENT_DEFAULT_CONTEXT") + ThreadLocal getCurrentDefaultContext(); + + @Mixin(targets = "net.caffeinemc.mods.sodium.neoforge.render.FluidRendererImpl$DefaultRenderContext", remap = false) + interface DefaultRenderContextAccessor { + + @Accessor("collector") + TranslucentGeometryCollector gtceu$getCollector(); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/SodiumDefaultFluidRendererMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/SodiumDefaultFluidRendererMixin.java new file mode 100644 index 00000000000..746f89f3c5e --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/client/sodium/SodiumDefaultFluidRendererMixin.java @@ -0,0 +1,160 @@ +package com.gregtechceu.gtceu.core.mixins.client.sodium; + +import com.gregtechceu.gtceu.client.renderer.fluid.InvertedFluidRenderer; +import com.gregtechceu.gtceu.core.util.extensions.sodium.BlockOcclusionCacheExt; + +import net.caffeinemc.mods.sodium.client.model.quad.properties.ModelQuadFacing; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.BlockOcclusionCache; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.DefaultFluidRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; + +import com.llamalad7.mixinextras.expression.Definition; +import com.llamalad7.mixinextras.expression.Expression; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +@Mixin(value = DefaultFluidRenderer.class, remap = false) +public class SodiumDefaultFluidRendererMixin { + + @Shadow + @Final + private BlockOcclusionCache occlusionCache; + @Unique + private boolean gtceu$drawingUpsideDownFluid = false; + + @Inject(method = "render", at = @At("HEAD")) + private void gtceu$cacheInvertedState(CallbackInfo ci) { + gtceu$drawingUpsideDownFluid = InvertedFluidRenderer.INVERTED_FLUID_RENDERING.isActive(); + ((BlockOcclusionCacheExt) this.occlusionCache) + .gtceu$drawingUpsideDownFluid(this.gtceu$drawingUpsideDownFluid); + } + + @Inject(method = "render", at = @At("RETURN")) + private void gtceu$resetInvertedState(CallbackInfo ci) { + gtceu$drawingUpsideDownFluid = false; + ((BlockOcclusionCacheExt) this.occlusionCache).gtceu$drawingUpsideDownFluid(false); + } + + @ModifyArg(method = "render", + at = @At(value = "INVOKE", + target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer;setVertex(Lnet/caffeinemc/mods/sodium/client/model/quad/ModelQuadViewMutable;IFFFFF)V"), + index = 3, + require = 16) + private float gtceu$invertFluidFlowDirection(float originalY) { + if (gtceu$drawingUpsideDownFluid) { + return 1.0f - originalY; + } else { + return originalY; + } + } + + @Definition(id = "shouldRenderBackwardUpFace", + method = "Lnet/minecraft/world/level/material/FluidState;shouldRenderBackwardUpFace(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z") + @Definition(id = "scratchPos", + field = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer;scratchPos:Lnet/minecraft/core/BlockPos$MutableBlockPos;") + @Definition(id = "set", + method = "Lnet/minecraft/core/BlockPos$MutableBlockPos;set(III)Lnet/minecraft/core/BlockPos$MutableBlockPos;") + @Expression("?.shouldRenderBackwardUpFace(?, @(this.scratchPos.set(?, ? + 1, ?)))") + @ModifyArg(method = "render", at = @At("MIXINEXTRAS:EXPRESSION"), index = 1) + private int gtceu$invertFluidBackwardUpFaceCheckDirection(int posY) { + if (gtceu$drawingUpsideDownFluid) { + // `posY - 2` because the original function already did `posY + 1` + return posY - 2; + } else { + return posY; + } + } + + @ModifyArgs(method = "isSideExposed", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/phys/shapes/Shapes;box(DDDDDD)Lnet/minecraft/world/phys/shapes/VoxelShape;")) + private void gtceu$invertExposedSideCheckDirection(Args args) { + if (gtceu$drawingUpsideDownFluid) { + // set minY to original maxY + double maxY = args.get(4); + args.set(1, maxY); + // set maxY to 1 + args.set(4, 1.0D); + } + } + + @ModifyExpressionValue(method = { "render", "fluidCornerHeight", "isSideExposed" }, + at = { + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;UP:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC), + @At(value = "FIELD", + target = "Lnet/minecraft/core/Direction;DOWN:Lnet/minecraft/core/Direction;", + opcode = Opcodes.GETSTATIC) + }, + require = 8) + private Direction gtceu$invertFluidCulling(Direction original) { + if (gtceu$drawingUpsideDownFluid) { + return original.getOpposite(); + } else { + return original; + } + } + + @ModifyExpressionValue(method = "render", + at = { + @At(value = "FIELD", + target = "Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;POS_Y:Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;", + opcode = Opcodes.GETSTATIC), + @At(value = "FIELD", + target = "Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;NEG_Y:Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;", + opcode = Opcodes.GETSTATIC) + }, + require = 5) + private ModelQuadFacing gtceu$invertFluidFaceOrientation(ModelQuadFacing original) { + if (gtceu$drawingUpsideDownFluid) { + return original.getOpposite(); + } else { + return original; + } + } + + @Definition(id = "NEG_Y", field = "Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;NEG_Y") + @Definition(id = "writeQuad", + method = "Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/pipeline/DefaultFluidRenderer;writeQuad(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/buffers/ChunkModelBuilder;Lnet/caffeinemc/mods/sodium/client/render/chunk/translucent_sorting/TranslucentGeometryCollector;Lnet/caffeinemc/mods/sodium/client/render/chunk/terrain/material/Material;Lnet/minecraft/core/BlockPos;Lnet/caffeinemc/mods/sodium/client/model/quad/ModelQuadView;Lnet/caffeinemc/mods/sodium/client/model/quad/properties/ModelQuadFacing;Z)V") + @Expression("this.writeQuad(?, ?, ?, ?, ?, NEG_Y, false)") + @ModifyArg(method = "render", at = @At("MIXINEXTRAS:EXPRESSION"), allow = 1) + private boolean gtceu$invertBottomQuadsOrder(boolean flip) { + if (gtceu$drawingUpsideDownFluid) { + return !flip; + } else { + return flip; + } + } + + @WrapOperation(method = "*", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;above()Lnet/minecraft/core/BlockPos;"), + require = 0) + private BlockPos gtceu$invertFluidLightCheckAbove(BlockPos pos, Operation original) { + if (gtceu$drawingUpsideDownFluid) { + return pos.below(); + } else { + return original.call(pos); + } + } + + @WrapOperation(method = "*", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/core/BlockPos;below()Lnet/minecraft/core/BlockPos;"), + require = 0) + private BlockPos gtceu$invertFluidLightCheckBelow(BlockPos pos, Operation original) { + if (gtceu$drawingUpsideDownFluid) { + return pos.above(); + } else { + return original.call(pos); + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/ftbchunks/FTBChunksClientMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/ftbchunks/FTBChunksClientMixin.java index 265564f5f82..7b2e6cce836 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/ftbchunks/FTBChunksClientMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/ftbchunks/FTBChunksClientMixin.java @@ -39,7 +39,7 @@ public class FTBChunksClientMixin { to = @At(value = "INVOKE", target = "Ldev/ftb/mods/ftbchunks/api/client/icon/MapIcon;draw(Ldev/ftb/mods/ftbchunks/api/client/icon/MapType;Lnet/minecraft/client/gui/GuiGraphics;IIIIZI)V"))) private void gtceu$injectRenderHud(GuiGraphics graphics, DeltaTracker tickDelta, CallbackInfo ci, - @Local MapIcon icon) { + @Local(name = "icon") MapIcon icon) { if (gtceu$iconCheck) { RenderSystem.enableDepthTest(); RenderSystem.depthFunc(GL11.GL_GEQUAL); @@ -56,8 +56,8 @@ public class FTBChunksClientMixin { remap = false) private void gtceu$saveLocals(GuiGraphics graphics, DeltaTracker tickDelta, CallbackInfo ci, @Local(name = "icon") MapIcon icon, - @Local(ordinal = 6, name = "minimapRotation") float minimapRotation, - @Local(ordinal = 1, name = "d") double d) { + @Local(name = "minimapRotation") float minimapRotation, + @Local(name = "d") double d) { gtceu$iconCheck = icon instanceof FluidVeinIcon; gtceu$d = d; gtceu$minimapRotation = minimapRotation; @@ -84,7 +84,7 @@ public class FTBChunksClientMixin { shift = At.Shift.AFTER), remap = false) private void gtceu$injectRenderHudPost(GuiGraphics graphics, DeltaTracker tickDelta, CallbackInfo ci, - @Local MapIcon icon) { + @Local(name = "icon") MapIcon icon) { if (gtceu$iconCheck) { RenderSystem.disableDepthTest(); RenderSystem.depthFunc(GL11.GL_LEQUAL); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/MapElementRenderHandlerBuilderMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/MapElementRenderHandlerBuilderMixin.java index 3ff60bda225..37c43b0355e 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/MapElementRenderHandlerBuilderMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/MapElementRenderHandlerBuilderMixin.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.ModifyArg; import xaero.map.element.MapElementRenderHandler; import xaero.map.element.MapElementRenderer; @@ -14,7 +14,9 @@ @Mixin(value = MapElementRenderHandler.Builder.class, remap = false) public class MapElementRenderHandlerBuilderMixin { - @ModifyVariable(method = "build", at = @At(value = "LOAD", ordinal = 3)) + @ModifyArg(method = "build", + at = @At(value = "INVOKE", + target = "Lxaero/map/element/MapElementRenderHandler;(Ljava/util/List;Lxaero/map/element/render/ElementRenderLocation;)V")) private List> gtceu$addOreRenderer(List> value) { if (ConfigHolder.INSTANCE.compat.minimap.toggle.xaerosMapIntegration) { value.add(OreVeinElementRenderer.Builder.begin().build()); diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/WorldMapSessionMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/WorldMapSessionMixin.java index b532b0590bf..a0a4e43d657 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/WorldMapSessionMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/xaeroworldmap/WorldMapSessionMixin.java @@ -10,7 +10,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import xaero.map.WorldMapSession; import xaero.map.highlight.HighlighterRegistry; @@ -20,10 +19,9 @@ public abstract class WorldMapSessionMixin { @Inject( method = "init", - at = @At(value = "INVOKE", target = "Lxaero/map/highlight/HighlighterRegistry;end()V"), - locals = LocalCapture.CAPTURE_FAILSOFT) - private void cadmus$registerHighlighters(ClientPacketListener connection, long biomeZoomSeed, CallbackInfo ci, - @Local HighlighterRegistry highlightRegistry) { + at = @At(value = "INVOKE", target = "Lxaero/map/highlight/HighlighterRegistry;end()V")) + private void gtceu$registerHighlighters(ClientPacketListener connection, long biomeZoomSeed, CallbackInfo ci, + @Local(name = "highlightRegistry") HighlighterRegistry highlightRegistry) { if (!ConfigHolder.INSTANCE.compat.minimap.toggle.xaerosMapIntegration) return; highlightRegistry.register(new FluidChunkHighlighter()); } diff --git a/src/main/java/com/gregtechceu/gtceu/core/util/extensions/sodium/BlockOcclusionCacheExt.java b/src/main/java/com/gregtechceu/gtceu/core/util/extensions/sodium/BlockOcclusionCacheExt.java new file mode 100644 index 00000000000..59657b46ccc --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/util/extensions/sodium/BlockOcclusionCacheExt.java @@ -0,0 +1,9 @@ +package com.gregtechceu.gtceu.core.util.extensions.sodium; + +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +public interface BlockOcclusionCacheExt { + + void gtceu$drawingUpsideDownFluid(boolean drawingUpsideDownFluid); +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 3e328cd1a37..96776d93877 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -610,12 +610,6 @@ public static void init(RegistrateLangProvider provider) { replace(provider, "item.gtceu.bucket", "%s Bucket"); - replace(provider, "block.gtceu.oil_heavy", "Heavy Oil"); - replace(provider, "block.gtceu.oil_light", "Light Oil"); - replace(provider, "block.gtceu.oil_medium", "Raw Oil"); - replace(provider, "block.gtceu.oil", "Oil"); - replace(provider, "block.gtceu.creosote", "Creosote"); - replace(provider, GTBlocks.BATTERY_EMPTY_TIER_I.get().getDescriptionId(), "Empty Tier I Capacitor"); replace(provider, GTBlocks.BATTERY_LAPOTRONIC_EV.get().getDescriptionId(), "EV Lapotronic Capacitor"); replace(provider, GTBlocks.BATTERY_LAPOTRONIC_IV.get().getDescriptionId(), "IV Lapotronic Capacitor"); diff --git a/src/main/java/com/gregtechceu/gtceu/integration/embeddium/GTEmbeddiumCompat.java b/src/main/java/com/gregtechceu/gtceu/integration/embeddium/GTEmbeddiumCompat.java index 86ab7c6608e..1098ef20d4f 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/embeddium/GTEmbeddiumCompat.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/embeddium/GTEmbeddiumCompat.java @@ -1,13 +1,48 @@ package com.gregtechceu.gtceu.integration.embeddium; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.client.renderer.GTRenderTypes; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; + +import org.embeddedt.embeddium.impl.render.chunk.compile.ChunkBuildContext; +import org.embeddedt.embeddium.impl.render.chunk.compile.GlobalChunkBuildContext; +import org.embeddedt.embeddium.impl.render.chunk.compile.pipeline.FluidRenderer; import org.embeddedt.embeddium.impl.render.chunk.terrain.TerrainRenderPass; import org.embeddedt.embeddium.impl.render.chunk.terrain.material.Material; import org.embeddedt.embeddium.impl.render.chunk.terrain.material.parameters.AlphaCutoffParameter; +import org.embeddedt.embeddium.impl.world.WorldSlice; public class GTEmbeddiumCompat { public static final TerrainRenderPass BLOOM_RENDER_PASS = new TerrainRenderPass(GTRenderTypes.bloom(), false, true); public static final Material BLOOM_MATERIAL = new Material(BLOOM_RENDER_PASS, AlphaCutoffParameter.ZERO, true); + + /** + * Render a fluid state using Embeddium's fluid renderer. {@return {@code true} if rendering was successful} + */ + public static boolean renderFluidBlock(BlockState blockState, FluidState fluidState, + BlockAndTintGetter level, BlockPos blockPos, BlockPos offset) { + try { + if (!(level instanceof WorldSlice levelSlice)) { + return false; + } + ChunkBuildContext buildContext = GlobalChunkBuildContext.get(); + if (buildContext == null) { + return false; + } + + FluidRenderer fluidRenderer = buildContext.cache.getFluidRenderer(); + + fluidRenderer.render(levelSlice, fluidState, blockPos, offset, buildContext.buffers); + return true; + } catch (Exception e) { + GTCEu.LOGGER.error("Something went wrong with rendering a fluid block using Embeddium's fluid renderer."); + GTCEu.LOGGER.error(e); + return false; + } + } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/sodium/GTSodiumCompat.java b/src/main/java/com/gregtechceu/gtceu/integration/sodium/GTSodiumCompat.java index d1fdd39b5c1..649bd3f889b 100644 --- a/src/main/java/com/gregtechceu/gtceu/integration/sodium/GTSodiumCompat.java +++ b/src/main/java/com/gregtechceu/gtceu/integration/sodium/GTSodiumCompat.java @@ -1,17 +1,27 @@ package com.gregtechceu.gtceu.integration.sodium; +import com.gregtechceu.gtceu.GTCEu; import com.gregtechceu.gtceu.client.renderer.GTRenderTypes; import com.gregtechceu.gtceu.client.util.TextureMetadataHelper; import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.core.mixins.client.sodium.FluidRendererImplAccessor; import com.gregtechceu.gtceu.utils.TriState; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildContext; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.pipeline.FluidRenderer; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.Material; import net.caffeinemc.mods.sodium.client.render.chunk.terrain.material.parameters.AlphaCutoffParameter; +import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.TranslucentGeometryCollector; import net.caffeinemc.mods.sodium.client.render.texture.SpriteFinderCache; +import net.caffeinemc.mods.sodium.client.world.LevelSlice; import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; public class GTSodiumCompat { @@ -51,4 +61,36 @@ public static boolean isEmissive(QuadView quad, int[] ambientPackedLights) { } return false; } + + /** + * Render a fluid state using Sodium's fluid renderer. {@return {@code true} if rendering was successful} + */ + public static boolean renderFluidBlock(BlockState blockState, FluidState fluidState, + BlockAndTintGetter level, BlockPos blockPos, BlockPos offset) { + try { + if (!(level instanceof LevelSlice levelSlice)) { + return false; + } + ChunkBuildContext buildContext = GlobalChunkBuildContext.get(); + if (buildContext == null) { + return false; + } + + FluidRenderer fluidRenderer = buildContext.cache.getFluidRenderer(); + if (!(fluidRenderer instanceof FluidRendererImplAccessor accessor)) { + GTCEu.LOGGER.error( + "Sodium's fluid renderer doesn't have our accessor. Maybe it was replaced with a different type?" + + "\n Using slower vanilla fluid renderer implementation."); + return false; + } + TranslucentGeometryCollector collector = accessor.getCurrentDefaultContext().get().gtceu$getCollector(); + + fluidRenderer.render(levelSlice, blockState, fluidState, blockPos, offset, collector, buildContext.buffers); + return true; + } catch (Exception e) { + GTCEu.LOGGER.error("Something went wrong with rendering a fluid block using Sodium's fluid renderer."); + GTCEu.LOGGER.error(e); + return false; + } + } } diff --git a/src/main/java/com/gregtechceu/gtceu/integration/sodium/GlobalChunkBuildContext.java b/src/main/java/com/gregtechceu/gtceu/integration/sodium/GlobalChunkBuildContext.java new file mode 100644 index 00000000000..bee0e1a1cad --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/integration/sodium/GlobalChunkBuildContext.java @@ -0,0 +1,49 @@ +package com.gregtechceu.gtceu.integration.sodium; + +import com.gregtechceu.gtceu.core.mixins.client.MinecraftAccessor; + +import net.caffeinemc.mods.sodium.client.render.chunk.compile.ChunkBuildContext; +import net.minecraft.client.Minecraft; + +import org.jetbrains.annotations.Nullable; + +public final class GlobalChunkBuildContext { + + private static ChunkBuildContext mainThreadContext; + private static final Thread mainThread = ((MinecraftAccessor) Minecraft.getInstance()).gtceu$getGameThread(); + + private GlobalChunkBuildContext() {} + + public static void setMainThread() { + if (mainThread != Thread.currentThread()) { + throw new IllegalStateException("Global chunk build context captured wrong thread"); + } + } + + @Nullable + public static ChunkBuildContext get() { + Thread thread = Thread.currentThread(); + // Main thread first, because it's the most common case + if (thread == mainThread) { + return mainThreadContext; + } else if (thread instanceof WorkerThread holder) { + return holder.context; + } else { + return null; + } + } + + public static void bindMainThread(ChunkBuildContext context) { + mainThreadContext = context; + } + + public static class WorkerThread extends Thread { + + private final ChunkBuildContext context; + + public WorkerThread(Runnable runnable, String name, ChunkBuildContext context) { + super(runnable, name); + this.context = context; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java index e38648964e9..2098ac1cd72 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java @@ -687,7 +687,7 @@ public static VoxelShape rotateVoxelShape(VoxelShape shape, Direction dir) { } public static boolean resourceExists(@NotNull ResourceLocation rs) { - if (GTCEu.isClientSide()) { + if (GTCEu.isClientSide() && !GTCEu.isDataGen()) { return Minecraft.getInstance().getResourceManager().getResource(rs).isPresent(); } else { return false; diff --git a/src/main/java/com/gregtechceu/gtceu/utils/ScopedValue.java b/src/main/java/com/gregtechceu/gtceu/utils/ScopedValue.java index 7a8c4ee75d7..791e4604c79 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/ScopedValue.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/ScopedValue.java @@ -1,7 +1,5 @@ package com.gregtechceu.gtceu.utils; -import lombok.Getter; -import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.Nullable; /** @@ -14,50 +12,65 @@ public abstract class ScopedValue implements AutoCloseable { * * @param The type of the object. */ - @RequiredArgsConstructor public static final class Object extends ScopedValue { - private final @Nullable T initialValue; - - /** - * Current value in this scope - */ - @Getter - private @Nullable T value; + private final ThreadLocal<@Nullable T> value; public Object() { this(null); } + public Object(@Nullable T initialValue) { + this.value = ThreadLocal.withInitial(() -> initialValue); + } + + /** + * {@return Current value in this scope} + */ + public @Nullable T getValue() { + return this.value.get(); + } + /** * Set {@code current} to {@code value} within this scope. * * @return this */ public Object with(T value) { - this.value = value; + this.value.set(value); return this; } @Override public void close() { - this.value = this.initialValue; + this.value.remove(); } } /** * Scoped boolean value. Resets to {@link #initialValue} when exiting scope. */ - @RequiredArgsConstructor public static final class Boolean extends ScopedValue { private final boolean initialValue; + private final ThreadLocal value; + + public Boolean() { + this(false); + } + + public Boolean(boolean initialValue) { + this.initialValue = initialValue; + this.value = ThreadLocal.withInitial(() -> this.initialValue); + } + /** - * Current value in this scope + * {@return Current value in this scope} */ - @Getter - private boolean active; + public boolean isActive() { + return this.value.get(); + } /** * Set {@code current} to {@code value} within this scope. @@ -65,7 +78,7 @@ public static final class Boolean extends ScopedValue { * @return this */ public Boolean with(boolean value) { - this.active = value; + this.value.set(value); return this; } @@ -74,13 +87,13 @@ public Boolean with(boolean value) { * * @return this */ - public Boolean active() { + public Boolean setActive() { return with(!this.initialValue); } @Override public void close() { - this.active = this.initialValue; + this.value.remove(); } } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index c92be40a59a..cff181d09cc 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -38,3 +38,16 @@ public net.minecraft.client.resources.model.ModelBakery getModel(Lnet/minecraft/ # for AE2 to be able to load (idk why but it needs these?) public net.minecraft.world.level.block.Blocks always(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z # always public net.minecraft.world.level.block.Blocks never(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z # never + +# for up-flowing fluids +protected net.minecraft.world.level.material.FlowingFluid canPassThroughWall(Lnet/minecraft/core/Direction;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z +protected net.minecraft.world.level.material.FlowingFluid spreadToSides(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/material/FluidState;Lnet/minecraft/world/level/block/state/BlockState;)V +protected net.minecraft.world.level.material.FlowingFluid isWaterHole(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/world/level/material/Fluid;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z +protected net.minecraft.world.level.material.FlowingFluid affectsFlow(Lnet/minecraft/world/level/material/FluidState;)Z +protected net.minecraft.world.level.material.FlowingFluid canHoldFluid(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/material/Fluid;)Z +protected net.minecraft.world.level.material.FlowingFluid hasSameAbove(Lnet/minecraft/world/level/material/FluidState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z +protected net.minecraft.world.level.material.FlowingFluid sourceNeighborCount(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;)I +protected net.minecraft.world.level.material.FlowingFluid isSourceBlockOfThisType(Lnet/minecraft/world/level/material/FluidState;)Z +protected net.minecraft.world.level.material.FlowingFluid getCacheKey(Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/BlockPos;)S +protected net.minecraft.world.level.material.FlowingFluid canPassThrough(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/world/level/material/Fluid;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/Direction;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/material/FluidState;)Z +protected net.minecraft.world.level.material.FlowingFluid shapes diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid.png.mcmeta deleted file mode 100644 index 04867655f01..00000000000 --- a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid.png.mcmeta +++ /dev/null @@ -1,45 +0,0 @@ -{ - "animation": { - "frametime": 2, - "frames": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 18, - 17, - 16, - 15, - 14, - 13, - 12, - 11, - 10, - 9, - 8, - 7, - 6, - 5, - 4, - 3, - 2, - 1 - ] - } -} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png new file mode 100644 index 00000000000..ff3201bb383 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png.mcmeta new file mode 100644 index 00000000000..5b2883f70dc --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_flow.png.mcmeta @@ -0,0 +1,37 @@ +{ + "animation": { + "frametime": 1, + "frames": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 14, + 13, + 12, + 11, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1 + ] + } +} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid.png b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_still.png similarity index 100% rename from src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid.png rename to src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_still.png diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_still.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_still.png.mcmeta new file mode 100644 index 00000000000..05495bfe0b2 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/liquid_still.png.mcmeta @@ -0,0 +1,45 @@ +{ + "animation": { + "frametime": 2, + "frames": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1 + ] + } +} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png deleted file mode 100644 index 85c70f67658..00000000000 Binary files a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png and /dev/null differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png.mcmeta deleted file mode 100644 index 7ceb3639415..00000000000 --- a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten.png.mcmeta +++ /dev/null @@ -1,45 +0,0 @@ -{ - "animation": { - "frametime": 2, - "frames": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 18, - 17, - 16, - 15, - 14, - 13, - 12, - 11, - 10, - 9, - 8, - 7, - 6, - 5, - 4, - 3, - 2, - 1 - ] - } -} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png new file mode 100644 index 00000000000..9fe925aee1b Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png.mcmeta new file mode 100644 index 00000000000..e72658ac7bd --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_flow.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 3 + } +} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png new file mode 100644 index 00000000000..fe3a5400f41 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png.mcmeta new file mode 100644 index 00000000000..df2316e9430 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/dull/molten_still.png.mcmeta @@ -0,0 +1,45 @@ +{ + "animation": { + "frametime": 2, + "frames": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 18, + 17, + 16, + 15, + 14, + 13, + 12, + 11, + 10, + 9, + 8, + 7, + 6, + 5, + 4, + 3, + 2, + 1 + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png deleted file mode 100644 index 9a4148f6b65..00000000000 Binary files a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png and /dev/null differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png.mcmeta deleted file mode 100644 index 0df7234a792..00000000000 --- a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid.png.mcmeta +++ /dev/null @@ -1,5 +0,0 @@ -{ - "animation":{ - "frametime":2 - } -} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png new file mode 100644 index 00000000000..018c9278dd8 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png.mcmeta new file mode 100644 index 00000000000..94e665b63c0 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_flow.png.mcmeta @@ -0,0 +1,3 @@ +{ + "animation": {} +} \ No newline at end of file diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png new file mode 100644 index 00000000000..9b168f898a1 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png.mcmeta new file mode 100644 index 00000000000..36578bcced2 --- /dev/null +++ b/src/main/resources/assets/gtceu/textures/block/material_sets/fluid/liquid_still.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png b/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png deleted file mode 100644 index ee40545a46a..00000000000 Binary files a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png and /dev/null differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png.mcmeta deleted file mode 100644 index 04867655f01..00000000000 --- a/src/main/resources/assets/gtceu/textures/block/material_sets/paper/fluid.png.mcmeta +++ /dev/null @@ -1,45 +0,0 @@ -{ - "animation": { - "frametime": 2, - "frames": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 18, - 17, - 16, - 15, - 14, - 13, - 12, - 11, - 10, - 9, - 8, - 7, - 6, - 5, - 4, - 3, - 2, - 1 - ] - } -} diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png b/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png deleted file mode 100644 index ee40545a46a..00000000000 Binary files a/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png and /dev/null differ diff --git a/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png.mcmeta deleted file mode 100644 index 04867655f01..00000000000 --- a/src/main/resources/assets/gtceu/textures/block/material_sets/powder/fluid.png.mcmeta +++ /dev/null @@ -1,45 +0,0 @@ -{ - "animation": { - "frametime": 2, - "frames": [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 18, - 17, - 16, - 15, - 14, - 13, - 12, - 11, - 10, - 9, - 8, - 7, - 6, - 5, - 4, - 3, - 2, - 1 - ] - } -} diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json index a1bb6d015af..c75e83187fe 100644 --- a/src/main/resources/gtceu.mixins.json +++ b/src/main/resources/gtceu.mixins.json @@ -20,6 +20,8 @@ "client.ItemEntityMixin", "client.KeyboardHandlerMixin", "client.LevelRendererMixin", + "client.LiquidBlockRendererMixin", + "client.MinecraftAccessor", "client.ModelBakerImplMixin", "client.ModelBakeryAccessor", "client.ModelManagerMixin", diff --git a/src/main/resources/mixin_configs/gtceu-embeddium.mixins.json b/src/main/resources/mixin_configs/gtceu-embeddium.mixins.json index f415d6f84ee..61b07b89b9c 100644 --- a/src/main/resources/mixin_configs/gtceu-embeddium.mixins.json +++ b/src/main/resources/mixin_configs/gtceu-embeddium.mixins.json @@ -9,6 +9,7 @@ "compatibilityLevel": "JAVA_21", "plugin": "com.gregtechceu.gtceu.core.mixins.GTMixinPlugin", "client": [ + "client.embeddium.EmbeddiumFluidRendererMixin", "client.bloom.normal.embeddium.BlockRendererMixin", "client.bloom.normal.embeddium.DefaultMaterialsMixin", "client.bloom.normal.embeddium.DefaultTerrainRenderPassesMixin", diff --git a/src/main/resources/mixin_configs/gtceu-sodium.mixins.json b/src/main/resources/mixin_configs/gtceu-sodium.mixins.json index bb249c12762..df77c2a4242 100644 --- a/src/main/resources/mixin_configs/gtceu-sodium.mixins.json +++ b/src/main/resources/mixin_configs/gtceu-sodium.mixins.json @@ -9,6 +9,11 @@ "compatibilityLevel": "JAVA_21", "plugin": "com.gregtechceu.gtceu.core.mixins.GTMixinPlugin", "client": [ + "client.sodium.BlockOcclusionCacheMixin", + "client.sodium.ChunkBuilderMixin", + "client.sodium.FluidRendererImplAccessor", + "client.sodium.FluidRendererImplAccessor$DefaultRenderContextAccessor", + "client.sodium.SodiumDefaultFluidRendererMixin", "client.bloom.normal.sodium.BlockRendererMixin", "client.bloom.normal.sodium.DefaultMaterialsMixin", "client.bloom.normal.sodium.DefaultTerrainRenderPassesMixin", diff --git a/src/main/resources/mixin_configs/gtceu-xaerominimap.mixins.json b/src/main/resources/mixin_configs/gtceu-xaerominimap.mixins.json index ecf7dff4640..75b274653b4 100644 --- a/src/main/resources/mixin_configs/gtceu-xaerominimap.mixins.json +++ b/src/main/resources/mixin_configs/gtceu-xaerominimap.mixins.json @@ -9,7 +9,6 @@ "compatibilityLevel": "JAVA_21", "plugin": "com.gregtechceu.gtceu.core.mixins.GTMixinPlugin", "client": [ - "client.AbstractWidgetMixin", "xaerominimap.HighlighterRegistryMixin", "xaerominimap.MinimapFBORendererMixin" ],