From c3062101e82cc6745c5d38b39b8d67aa8acc3b47 Mon Sep 17 00:00:00 2001 From: screret <68943070+screret@users.noreply.github.com> Date: Wed, 29 May 2024 09:19:29 +0300 Subject: [PATCH] more bearable & gradual hazard effects (#1329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remake hazard logic to be more bearable (needs someone else to tweak it, I just made the framework) oops, I forgot to commit at all. * it works, needs balancing still * update REI * make Nq, Nt radioactive * rename GT poison to weak_poison * optimize fluid -> material mapping * make UnificationEntry able to have a nullable TagPrefix for stuff that might somehow need it?? * fix fluid buckets not applying hazard effects * make QuarkTech eating take the offhand items into account when doing the automatic eating * remove unused code in TagPrefixItem * nerf the default poison hazard (it was way too strong) * make parent hazards only apply if this material doesn't already have a hazard property set * add lower-tier variants of hazmat for head (face mask) & chest (rubber gloves) * run datagen * actually save the amounts of hazards the player is carrying instead of just forgetting them * damage hazmat if you're carrying hazardous materials * I forgot to add the tag to the tag * apply spotless * omfg it forgot the annotation * how did spotless miss this the first time?? * add paracetamol pills as a temporary antidote for all ailments, more coming soon * run datagen, spotless * oops. wrong lang key. also paracetamol wasn't edible. * add evaporation plant for: iodine process, bromine process (from brine) * add Prussian blue, part 2 of RadAway:tm: * add Diethylenetriaminepentaacetic acid, the 3rd and final part of RadAway * holy shit RadAway™ * datagen * remove some unused files * reviews * run datagen + spotless --- settings.gradle | 2 +- .../compass/nodes/generation/blackstone.json | 127 ++++++++++ .../compass/nodes/generation/endstone.json | 4 +- .../assets/gtceu/compass/nodes/misc/mold.json | 3 +- .../resources/assets/gtceu/lang/en_ud.json | 71 +++++- .../resources/assets/gtceu/lang/en_us.json | 72 +++++- .../assets/gtceu/models/item/face_mask.json | 6 + .../gtceu/models/item/paracetamol_pill.json | 6 + .../gtceu/models/item/pill_casting_mold.json | 6 + .../gtceu/models/item/rad_away_pill.json | 6 + .../gtceu/models/item/rubber_gloves.json | 6 + .../forge/tags/blocks/mineable/wrench.json | 1 + .../blocks/stainless_evaporation_casing.json | 21 ++ .../data/gtceu/tags/items/ppe_armor.json | 16 ++ .../tags/blocks/mineable/pickaxe.json | 1 + .../api/capability/GTCapabilityHelper.java | 7 + .../api/capability/IHazardEffectTracker.java | 34 +++ .../api/capability/forge/GTCapability.java | 5 + .../api/data/chemical/ChemicalHelper.java | 36 ++- .../api/data/chemical/material/Material.java | 147 ++++++++--- .../material/properties/HazardProperty.java | 229 +++++++++++++++--- .../material/stack/UnificationEntry.java | 4 +- .../gtceu/api/item/TagPrefixItem.java | 9 +- .../gtceu/api/item/forge/GTBucketItem.java | 21 +- .../gregtechceu/gtceu/common/CommonProxy.java | 2 + .../gtceu/common/ServerCommands.java | 46 ---- .../capability/HazardEffectTracker.java | 224 +++++++++++++++++ .../gtceu/common/commands/ServerCommands.java | 127 ++++++++++ .../commands/arguments/MaterialArgument.java | 45 ++++ .../commands/arguments/MaterialParser.java | 100 ++++++++ .../gtceu/common/data/GTBlocks.java | 3 + .../gtceu/common/data/GTCommandArguments.java | 27 +++ .../gtceu/common/data/GTItems.java | 63 ++++- .../gtceu/common/data/GTMachines.java | 27 +++ .../gtceu/common/data/GTMaterials.java | 42 ++++ .../gtceu/common/data/GTMobEffects.java | 24 ++ .../gtceu/common/data/GTRecipeTypes.java | 5 + .../data/materials/ElementMaterials.java | 46 ++-- .../data/materials/FirstDegreeMaterials.java | 173 ++++++++++++- .../gtceu/common/data/materials/GTFoods.java | 3 + .../data/materials/HigherDegreeMaterials.java | 35 +++ .../materials/OrganicChemistryMaterials.java | 43 +++- .../data/materials/SecondDegreeMaterials.java | 43 ++++ .../UnknownCompositionMaterials.java | 3 +- .../gtceu/common/effect/GTPoisonEffect.java | 29 +++ .../gtceu/common/item/AntidoteBehavior.java | 84 +++++++ .../common/item/armor/GTArmorMaterials.java | 12 + .../gtceu/common/item/armor/HazmatSuit.java | 5 +- .../common/item/armor/QuarkTechSuite.java | 43 ++-- .../gtceu/config/ConfigHolder.java | 4 + .../gtceu/core/mixins/EntityMixin.java | 25 ++ .../gtceu/core/mixins/GuiHeartTypeMixin.java | 21 ++ .../gtceu/core/mixins/InventoryMixin.java | 99 +++++++- .../gtceu/data/lang/LangHandler.java | 49 ++-- .../recipe/misc/CraftingRecipeLoader.java | 7 + .../data/recipe/misc/MachineRecipeLoader.java | 19 ++ .../recipe/misc/MetaTileEntityLoader.java | 4 + .../serialized/chemistry/AntidoteRecipes.java | 181 ++++++++++++++ .../serialized/chemistry/BrineRecipes.java | 108 +++++++++ .../chemistry/ChemistryRecipes.java | 2 + .../serialized/chemistry/MixerRecipes.java | 7 + .../serialized/chemistry/ReactorRecipes.java | 12 +- .../gtceu/forge/ForgeCommonEventListener.java | 62 ++++- .../gtceu/integration/emi/GTEMIPlugin.java | 2 +- .../emi/recipe/Ae2PatternTerminalHandler.java | 1 - .../integration/kjs/GregTechKubeJSPlugin.java | 2 + .../com/gregtechceu/gtceu/utils/GTUtil.java | 19 -- .../gtceu/textures/armor/bad_hazmat_1.png | Bin 0 -> 8399 bytes .../machine_casing_stainless_evaporation.png | Bin 0 -> 929 bytes ...ne_casing_stainless_evaporation.png.mcmeta | 5 + ...chine_casing_stainless_evaporation_ctm.png | Bin 0 -> 3249 bytes .../assets/gtceu/textures/item/face_mask.png | Bin 0 -> 1203 bytes .../gtceu/textures/item/paracetamol_pill.png | Bin 0 -> 1566 bytes .../gtceu/textures/item/pill_casting_mold.png | Bin 0 -> 5233 bytes .../gtceu/textures/item/rad_away_pill.png | Bin 0 -> 5506 bytes .../gtceu/textures/item/rubber_gloves.png | Bin 0 -> 1203 bytes .../gtceu/textures/mob_effect/weak_poison.png | Bin 0 -> 10303 bytes src/main/resources/gtceu.mixins.json | 3 +- 78 files changed, 2451 insertions(+), 275 deletions(-) create mode 100644 src/generated/resources/assets/gtceu/compass/nodes/generation/blackstone.json create mode 100644 src/generated/resources/assets/gtceu/models/item/face_mask.json create mode 100644 src/generated/resources/assets/gtceu/models/item/paracetamol_pill.json create mode 100644 src/generated/resources/assets/gtceu/models/item/pill_casting_mold.json create mode 100644 src/generated/resources/assets/gtceu/models/item/rad_away_pill.json create mode 100644 src/generated/resources/assets/gtceu/models/item/rubber_gloves.json create mode 100644 src/generated/resources/data/gtceu/loot_tables/blocks/stainless_evaporation_casing.json create mode 100644 src/generated/resources/data/gtceu/tags/items/ppe_armor.json create mode 100644 src/main/java/com/gregtechceu/gtceu/api/capability/IHazardEffectTracker.java delete mode 100644 src/main/java/com/gregtechceu/gtceu/common/ServerCommands.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/capability/HazardEffectTracker.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/commands/ServerCommands.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialArgument.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/data/GTCommandArguments.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/effect/GTPoisonEffect.java create mode 100644 src/main/java/com/gregtechceu/gtceu/common/item/AntidoteBehavior.java create mode 100644 src/main/java/com/gregtechceu/gtceu/core/mixins/GuiHeartTypeMixin.java create mode 100644 src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/AntidoteRecipes.java create mode 100644 src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/BrineRecipes.java create mode 100644 src/main/resources/assets/gtceu/textures/armor/bad_hazmat_1.png create mode 100644 src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png create mode 100644 src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta create mode 100644 src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation_ctm.png create mode 100644 src/main/resources/assets/gtceu/textures/item/face_mask.png create mode 100644 src/main/resources/assets/gtceu/textures/item/paracetamol_pill.png create mode 100644 src/main/resources/assets/gtceu/textures/item/pill_casting_mold.png create mode 100644 src/main/resources/assets/gtceu/textures/item/rad_away_pill.png create mode 100644 src/main/resources/assets/gtceu/textures/item/rubber_gloves.png create mode 100644 src/main/resources/assets/gtceu/textures/mob_effect/weak_poison.png diff --git a/settings.gradle b/settings.gradle index 72d2c1d699..59708265d9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,7 +19,7 @@ dependencyResolutionManagement { // Mod Dependencies Versions // Common def jeiVersion = "15.2.0.27" - def reiVersion = "12.0.684" + def reiVersion = "12.1.725" def emiVersion = "1.0.30" def ae2Version = "15.0.18" def kjsVersion = "2001.6.4-build.120" diff --git a/src/generated/resources/assets/gtceu/compass/nodes/generation/blackstone.json b/src/generated/resources/assets/gtceu/compass/nodes/generation/blackstone.json new file mode 100644 index 0000000000..e7aaf5e64b --- /dev/null +++ b/src/generated/resources/assets/gtceu/compass/nodes/generation/blackstone.json @@ -0,0 +1,127 @@ +{ + "button_texture": { + "type": "item", + "res": "gtceu:blackstone_aluminium_ore" + }, + "items": [ + "gtceu:blackstone_aluminium_ore", + "gtceu:blackstone_beryllium_ore", + "gtceu:blackstone_cobalt_ore", + "gtceu:blackstone_copper_ore", + "gtceu:blackstone_gold_ore", + "gtceu:blackstone_iron_ore", + "gtceu:blackstone_lead_ore", + "gtceu:blackstone_lithium_ore", + "gtceu:blackstone_molybdenum_ore", + "gtceu:blackstone_neodymium_ore", + "gtceu:blackstone_nickel_ore", + "gtceu:blackstone_palladium_ore", + "gtceu:blackstone_platinum_ore", + "gtceu:blackstone_plutonium_ore", + "gtceu:blackstone_silver_ore", + "gtceu:blackstone_sulfur_ore", + "gtceu:blackstone_thorium_ore", + "gtceu:blackstone_tin_ore", + "gtceu:blackstone_naquadah_ore", + "gtceu:blackstone_almandine_ore", + "gtceu:blackstone_asbestos_ore", + "gtceu:blackstone_hematite_ore", + "gtceu:blackstone_blue_topaz_ore", + "gtceu:blackstone_goethite_ore", + "gtceu:blackstone_calcite_ore", + "gtceu:blackstone_cassiterite_ore", + "gtceu:blackstone_cassiterite_sand_ore", + "gtceu:blackstone_chalcopyrite_ore", + "gtceu:blackstone_chromite_ore", + "gtceu:blackstone_cinnabar_ore", + "gtceu:blackstone_coal_ore", + "gtceu:blackstone_cobaltite_ore", + "gtceu:blackstone_cooperite_ore", + "gtceu:blackstone_diamond_ore", + "gtceu:blackstone_emerald_ore", + "gtceu:blackstone_galena_ore", + "gtceu:blackstone_garnierite_ore", + "gtceu:blackstone_green_sapphire_ore", + "gtceu:blackstone_grossular_ore", + "gtceu:blackstone_ilmenite_ore", + "gtceu:blackstone_bauxite_ore", + "gtceu:blackstone_lazurite_ore", + "gtceu:blackstone_magnesite_ore", + "gtceu:blackstone_magnetite_ore", + "gtceu:blackstone_molybdenite_ore", + "gtceu:blackstone_powellite_ore", + "gtceu:blackstone_pyrite_ore", + "gtceu:blackstone_pyrolusite_ore", + "gtceu:blackstone_pyrope_ore", + "gtceu:blackstone_rock_salt_ore", + "gtceu:blackstone_ruby_ore", + "gtceu:blackstone_salt_ore", + "gtceu:blackstone_saltpeter_ore", + "gtceu:blackstone_sapphire_ore", + "gtceu:blackstone_scheelite_ore", + "gtceu:blackstone_sodalite_ore", + "gtceu:blackstone_tantalite_ore", + "gtceu:blackstone_spessartine_ore", + "gtceu:blackstone_sphalerite_ore", + "gtceu:blackstone_stibnite_ore", + "gtceu:blackstone_tetrahedrite_ore", + "gtceu:blackstone_topaz_ore", + "gtceu:blackstone_tungstate_ore", + "gtceu:blackstone_uraninite_ore", + "gtceu:blackstone_wulfenite_ore", + "gtceu:blackstone_yellow_limonite_ore", + "gtceu:blackstone_nether_quartz_ore", + "gtceu:blackstone_certus_quartz_ore", + "gtceu:blackstone_quartzite_ore", + "gtceu:blackstone_graphite_ore", + "gtceu:blackstone_bornite_ore", + "gtceu:blackstone_chalcocite_ore", + "gtceu:blackstone_realgar_ore", + "gtceu:blackstone_bastnasite_ore", + "gtceu:blackstone_pentlandite_ore", + "gtceu:blackstone_spodumene_ore", + "gtceu:blackstone_lepidolite_ore", + "gtceu:blackstone_glauconite_sand_ore", + "gtceu:blackstone_malachite_ore", + "gtceu:blackstone_mica_ore", + "gtceu:blackstone_barite_ore", + "gtceu:blackstone_alunite_ore", + "gtceu:blackstone_talc_ore", + "gtceu:blackstone_soapstone_ore", + "gtceu:blackstone_kyanite_ore", + "gtceu:blackstone_pyrochlore_ore", + "gtceu:blackstone_oilsands_ore", + "gtceu:blackstone_olivine_ore", + "gtceu:blackstone_opal_ore", + "gtceu:blackstone_amethyst_ore", + "gtceu:blackstone_lapis_ore", + "gtceu:blackstone_apatite_ore", + "gtceu:blackstone_tricalcium_phosphate_ore", + "gtceu:blackstone_red_garnet_ore", + "gtceu:blackstone_yellow_garnet_ore", + "gtceu:blackstone_vanadium_magnetite_ore", + "gtceu:blackstone_pollucite_ore", + "gtceu:blackstone_bentonite_ore", + "gtceu:blackstone_fullers_earth_ore", + "gtceu:blackstone_pitchblende_ore", + "gtceu:blackstone_monazite_ore", + "gtceu:blackstone_trona_ore", + "gtceu:blackstone_gypsum_ore", + "gtceu:blackstone_zeolite_ore", + "gtceu:blackstone_redstone_ore", + "gtceu:blackstone_electrotine_ore", + "gtceu:blackstone_diatomite_ore", + "gtceu:blackstone_granitic_mineral_sand_ore", + "gtceu:blackstone_garnet_sand_ore", + "gtceu:blackstone_basaltic_mineral_sand_ore" + ], + "page": "gtceu:generation/blackstone", + "position": [ + -50, + 150 + ], + "pre_nodes": [ + "gtceu:generation/ore" + ], + "section": "gtceu:generation" +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/compass/nodes/generation/endstone.json b/src/generated/resources/assets/gtceu/compass/nodes/generation/endstone.json index ae8d8fec67..f3b450c854 100644 --- a/src/generated/resources/assets/gtceu/compass/nodes/generation/endstone.json +++ b/src/generated/resources/assets/gtceu/compass/nodes/generation/endstone.json @@ -117,8 +117,8 @@ ], "page": "gtceu:generation/endstone", "position": [ - -50, - 100 + -250, + 200 ], "pre_nodes": [ "gtceu:generation/ore" diff --git a/src/generated/resources/assets/gtceu/compass/nodes/misc/mold.json b/src/generated/resources/assets/gtceu/compass/nodes/misc/mold.json index 8bcc191d5c..95deb56cd4 100644 --- a/src/generated/resources/assets/gtceu/compass/nodes/misc/mold.json +++ b/src/generated/resources/assets/gtceu/compass/nodes/misc/mold.json @@ -16,7 +16,8 @@ "gtceu:anvil_casting_mold", "gtceu:name_casting_mold", "gtceu:small_gear_casting_mold", - "gtceu:rotor_casting_mold" + "gtceu:rotor_casting_mold", + "gtceu:pill_casting_mold" ], "page": "gtceu:misc/mold", "position": [ diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 027b85f1b6..4c073f9bb2 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -239,6 +239,7 @@ "block.gtceu.ev_transformer_4a": "ɹǝɯɹoɟsuɐɹ⟘ )xㄣ( dɯⱯ-ıH ǝbɐʇןoΛ ǝɯǝɹʇxƎ", "block.gtceu.ev_wiremill": "ɹ§III ןןıɯǝɹıM pǝɔuɐʌpⱯϛ§", "block.gtceu.ev_world_accelerator": "ɹ§III ɹoʇɐɹǝןǝɔɔⱯ pןɹoM pǝɔuɐʌpⱯϛ§", + "block.gtceu.evaporation_plant": "ɹǝʍo⟘ uoıʇɐɹodɐʌƎ", "block.gtceu.explosion_hazard_sign_block": "ʞɔoןᗺ ubıS pɹɐzɐH uoısoןdxƎ", "block.gtceu.explosive.breaking_tooltip": "dn ʞɔɐq ʞɔıd oʇ ǝuıɯ ʞɐǝus 'pǝuıɯ uǝɥʍ uoısoןdxǝ sǝɯıɹԀ", "block.gtceu.explosive.lighting_tooltip": "ǝuoʇspǝᴚ ɥʇıʍ ʇıן ǝq ʇouuɐƆ", @@ -952,6 +953,7 @@ "block.gtceu.square_marble_bricks": "sʞɔıɹᗺ ǝןqɹɐW ǝɹɐnbS", "block.gtceu.square_red_granite_bricks": "sʞɔıɹᗺ ǝʇıuɐɹ⅁ pǝᴚ ǝɹɐnbS", "block.gtceu.stable_machine_casing": "buısɐƆ ǝuıɥɔɐW ɯnıuɐʇı⟘ ǝןqɐʇS", + "block.gtceu.stainless_evaporation_casing": "buısɐƆ uoıʇɐɹodɐʌƎ ssǝןuıɐʇS", "block.gtceu.stainless_steel_crate": "ǝʇɐɹƆ ןǝǝʇS ssǝןuıɐʇS", "block.gtceu.stainless_steel_drum": "ɯnɹᗡ ןǝǝʇS ssǝןuıɐʇS", "block.gtceu.stainless_steel_gearbox": "buısɐƆ xoqɹɐǝ⅁ ןǝǝʇS ssǝןuıɐʇS", @@ -1645,6 +1647,7 @@ "compass.node.gtceu.ev/large_miner": "ɹǝuıW ǝbɹɐꞀ", "compass.node.gtceu.generation/andesite": "ǝʇısǝpuⱯ", "compass.node.gtceu.generation/basalt": "ʇןɐsɐᗺ", + "compass.node.gtceu.generation/blackstone": "ǝuoʇsʞɔɐןᗺ", "compass.node.gtceu.generation/deepslate": "ǝʇɐןsdǝǝᗡ", "compass.node.gtceu.generation/diorite": "ǝʇıɹoıᗡ", "compass.node.gtceu.generation/endstone": "ǝuoʇspuƎ", @@ -2008,6 +2011,7 @@ "compass.section.gtceu.uv": "ǝbɐʇןoΛ Λ∩Ɛ§", "compass.section.gtceu.zpm": "ǝbɐʇןoΛ WԀZɔ§", "config.gtceu.option.addLoot": "ʇooꞀppɐ", + "config.gtceu.option.ae2": "ᄅǝɐ", "config.gtceu.option.allUniqueStoneTypes": "sǝdʎ⟘ǝuoʇSǝnbıu∩ןןɐ", "config.gtceu.option.animationTime": "ǝɯı⟘uoıʇɐɯıuɐ", "config.gtceu.option.armorHud": "pnHɹoɯɹɐ", @@ -2036,6 +2040,7 @@ "config.gtceu.option.enableTieredCasings": "sbuısɐƆpǝɹǝı⟘ǝןqɐuǝ", "config.gtceu.option.enableWorldAccelerators": "sɹoʇɐɹǝןǝɔɔⱯpןɹoMǝןqɐuǝ", "config.gtceu.option.energy": "ʎbɹǝuǝ", + "config.gtceu.option.energyConsumption": "uoıʇdɯnsuoƆʎbɹǝuǝ", "config.gtceu.option.energyUsageMultiplier": "ɹǝıןdıʇןnWǝbɐs∩ʎbɹǝuǝ", "config.gtceu.option.euToPlatformRatio": "oıʇɐᴚɯɹoɟʇɐןԀo⟘nǝ", "config.gtceu.option.flintAndSteelRequireSteel": "ןǝǝʇSǝɹınbǝᴚןǝǝʇSpuⱯʇuıןɟ", @@ -2059,6 +2064,7 @@ "config.gtceu.option.hazardsEnabled": "pǝןqɐuƎspɹɐzɐɥ", "config.gtceu.option.hideFacadesInJEI": "IƎſuIsǝpɐɔɐℲǝpıɥ", "config.gtceu.option.hideFilledCellsInJEI": "IƎſuIsןןǝƆpǝןןıℲǝpıɥ", + "config.gtceu.option.hideOreProcessingDiagrams": "sɯɐɹbɐıᗡbuıssǝɔoɹԀǝɹOǝpıɥ", "config.gtceu.option.highTierContent": "ʇuǝʇuoƆɹǝı⟘ɥbıɥ", "config.gtceu.option.hudLocation": "uoıʇɐɔoꞀpnɥ", "config.gtceu.option.hudOffsetX": "XʇǝsɟɟOpnɥ", @@ -2071,6 +2077,9 @@ "config.gtceu.option.machineSounds": "spunoSǝuıɥɔɐɯ", "config.gtceu.option.machines": "sǝuıɥɔɐɯ", "config.gtceu.option.machinesEmissiveTextures": "sǝɹnʇxǝ⟘ǝʌıssıɯƎsǝuıɥɔɐɯ", + "config.gtceu.option.nanoSaber": "ɹǝqɐSouɐu", + "config.gtceu.option.nanoSaberBaseDamage": "ǝbɐɯɐᗡǝsɐᗺɹǝqɐSouɐu", + "config.gtceu.option.nanoSaberDamageBoost": "ʇsooᗺǝbɐɯɐᗡɹǝqɐSouɐu", "config.gtceu.option.nativeEUToPlatformNative": "ǝʌıʇɐNɯɹoɟʇɐןԀo⟘∩Ǝǝʌıʇɐu", "config.gtceu.option.nerfPaperCrafting": "buıʇɟɐɹƆɹǝdɐԀɟɹǝu", "config.gtceu.option.nerfWoodCrafting": "buıʇɟɐɹƆpooMɟɹǝu", @@ -2099,9 +2108,18 @@ "config.gtceu.option.toolCraftingSounds": "spunoSbuıʇɟɐɹƆןooʇ", "config.gtceu.option.toolUseSounds": "spunoSǝs∩ןooʇ", "config.gtceu.option.tools": "sןooʇ", + "config.gtceu.option.universalHazards": "spɹɐzɐHןɐsɹǝʌıun", "config.gtceu.option.useVBO": "OᗺΛǝsn", + "config.gtceu.option.voltageTierAdvImpeller": "ɹǝןןǝdɯIʌpⱯɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierAdvNanoSuit": "ʇınSouɐNʌpⱯɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierAdvQuarkTech": "ɥɔǝ⟘ʞɹɐnὉʌpⱯɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierImpeller": "ɹǝןןǝdɯIɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierNanoSuit": "ʇınSouɐNɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierNightVision": "uoısıΛʇɥbıNɹǝı⟘ǝbɐʇןoʌ", + "config.gtceu.option.voltageTierQuarkTech": "ɥɔǝ⟘ʞɹɐnὉɹǝı⟘ǝbɐʇןoʌ", "config.gtceu.option.worldAcceleratorBlacklist": "ʇsıןʞɔɐןᗺɹoʇɐɹǝןǝɔɔⱯpןɹoʍ", "config.gtceu.option.worldgen": "uǝbpןɹoʍ", + "config.gtceu.option.zombieSpawnWithSabers": "sɹǝqɐSɥʇıMuʍɐdSǝıqɯoz", "config.jade.plugin_gtceu.controllable_provider": "ǝןqɐןןoɹʇuoƆ ]nƎƆ⟘⅁[", "config.jade.plugin_gtceu.electric_container_provider": "ɹǝuıɐʇuoƆ ɔıɹʇɔǝןƎ ]nƎƆ⟘⅁[", "config.jade.plugin_gtceu.recipe_logic_provider": "ɔıboꞀ ǝdıɔǝᴚ ]nƎƆ⟘⅁[", @@ -2307,6 +2325,7 @@ "death.attack.gtceu.wrench_hv": "%s ʎq pǝuǝsooן ǝɹǝʍ sǝdıd s,%s", "death.attack.gtceu.wrench_iv": "%s ʎq suɐןd ɹıǝɥʇ oʇuı uʍoɹɥʇ ɥɔuǝɹM ʎǝʞuoW ɐ pɐɥ %s", "death.attack.gtceu.wrench_lv": "%s ʎq pǝuǝsooן ǝɹǝʍ sǝdıd s,%s", + "effect.gtceu.weak_poison": "uosıoԀ ʞɐǝM", "enchantment.damage.disjunction": "uoıʇɔunظsıᗡ", "enchantment.disjunction": "uoıʇɔunظsıᗡ", "enchantment.gtceu.disjunction.desc": "˙sqoɯ pǝʇɐןǝɹ-ɹǝpuƎ oʇ ssǝuʍoןS puɐ ssǝuʞɐǝM sǝıןddⱯ", @@ -2406,6 +2425,7 @@ "gtceu.electric_furnace": "ǝɔɐuɹnℲ ɔıɹʇɔǝןƎ", "gtceu.electrolyzer": "ɹǝzʎןoɹʇɔǝןƎ", "gtceu.electromagnetic_separator": "ɹoʇɐɹɐdǝS ɔıʇǝubɐɯoɹʇɔǝןƎ", + "gtceu.evaporation": "uoıʇɐɹodɐʌƎ", "gtceu.extractor": "ɹoʇɔɐɹʇxƎ", "gtceu.extruder": "ɹǝpnɹʇxƎ", "gtceu.fermenter": "ɹǝʇuǝɯɹǝℲ", @@ -2526,6 +2546,10 @@ "gtceu.gui.title_bar.page_switcher": "sǝbɐԀ", "gtceu.gui.toggle_view.disabled": ")spınןℲ( ʍǝıΛ ǝןbbo⟘", "gtceu.gui.toggle_view.enabled": ")sɯǝʇI( ʍǝıΛ ǝןbbo⟘", + "gtceu.hazard.antidote.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ ǝʇopıʇuⱯɐ§", + "gtceu.hazard.antidote.description.time_removed": "ǝɯıʇ ,sʇuǝɯןıɐ ʇuǝɹɹnɔ ɟo %ss sǝʌoɯǝᴚ", + "gtceu.hazard.antidote.description.time_removed.all": "ןןɐ", + "gtceu.hazard.antidote.description_shift": ":sǝdʎʇ sǝɹnƆɐ§", "gtceu.hazard.contact_poison": "uosıoԀ ʇɔɐʇuoƆϛ§", "gtceu.hazard.corrosive": "ǝʌısoɹɹoƆ9§", "gtceu.hazard.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ S∩OᗡᴚⱯZⱯHɔ§ן§", @@ -3857,6 +3881,7 @@ "item.gtceu.exquisite_glass_gem": "ןɐʇsʎɹƆ ssɐן⅁ ǝʇısınbxƎ", "item.gtceu.facade_cover": "ǝpɐɔɐℲ ɹǝʌoƆ %s", "item.gtceu.facade_cover.tooltip": "˙ㄥ§ɹǝʌoƆɟ§ ʇıɟʇnO ǝʌıʇɐɹoɔǝᗡㄥ§", + "item.gtceu.face_mask": "ʞsɐW ǝɔɐℲ", "item.gtceu.fertilizer": "ɹǝzıןıʇɹǝℲ", "item.gtceu.fiber_reinforced_circuit_board": "pɹɐoᗺ ʇınɔɹıƆ pǝɔɹoɟuıǝᴚ-ɹǝqıℲ", "item.gtceu.fiber_reinforced_circuit_board.tooltip": "pɹɐoᗺ ǝɯǝɹʇxƎ uⱯㄥ§", @@ -4192,6 +4217,7 @@ "item.gtceu.osmium_credit.tooltip": "sʇıpǝɹƆ 960ㄣㄥ§", "item.gtceu.palladium_raw_dust": "ɹǝpʍoԀ ɯnıpɐןןɐԀ ʍɐᴚ", "item.gtceu.paper_dust": "pɐɥƆ", + "item.gtceu.paracetamol_pill": "ןןıԀ ןoɯɐʇǝɔɐɹɐԀ", "item.gtceu.petri_dish": "ɥsıᗡ ıɹʇǝԀ", "item.gtceu.petri_dish.tooltip": "sןןǝƆ buıʇɐʌıʇןnɔ ɹoℲㄥ§", "item.gtceu.phenolic_circuit_board": "pɹɐoᗺ ʇınɔɹıƆ ɔıןouǝɥԀ", @@ -4203,6 +4229,7 @@ "item.gtceu.phosphorus_wafer": "ɹǝɟɐM pǝdop-snɹoɥdsoɥԀ", "item.gtceu.phosphorus_wafer.tooltip": "ʇınɔɹıƆ ʍɐᴚㄥ§", "item.gtceu.pickaxe_extruder_mold.tooltip": "sǝxɐʞɔıԀ buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", + "item.gtceu.pill_casting_mold": ")ןןıԀ( pןoW buıʇsɐƆ", "item.gtceu.pink_dye_spray_can": ")ʞuıԀ( uɐƆ ʎɐɹdS", "item.gtceu.pink_glass_lens": ")ʞuıԀ( suǝꞀ ssɐן⅁", "item.gtceu.pipe.huge_extruder_mold.tooltip": "sǝdıԀ ʞɔoןᗺ ןןnɟ buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", @@ -4271,6 +4298,7 @@ "item.gtceu.quarktech_helmet": "ʇǝɯןǝH ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "item.gtceu.quarktech_leggings": "sbuıbbǝꞀ ǝʇınS ™ɥɔǝ⟘ʞɹɐnὉ", "item.gtceu.quartz_sand_dust": "puɐS zʇɹɐnὉ", + "item.gtceu.rad_away_pill": "ןןıԀ ™ʎɐʍⱯpɐᴚ", "item.gtceu.ram_chip": "dıɥƆ WⱯᴚ", "item.gtceu.ram_chip.tooltip": "ʎɹoɯǝW ssǝɔɔⱯ ɯopuɐᴚㄥ§", "item.gtceu.ram_wafer": "ɹǝɟɐM WⱯᴚ", @@ -4304,6 +4332,7 @@ "item.gtceu.rotor_casting_mold.tooltip": "sɹoʇoᴚ buıʞɐɯ ɹoɟ pןoWㄥ§", "item.gtceu.rotor_extruder_mold": ")ɹoʇoᴚ( pןoW ɹǝpnɹʇxƎ", "item.gtceu.rotor_extruder_mold.tooltip": "sɹoʇoᴚ buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", + "item.gtceu.rubber_gloves": "sǝʌoן⅁ ɹǝqqnᴚ", "item.gtceu.salt_dust": "ʇןɐS", "item.gtceu.saw_extruder_mold.tooltip": "sʍɐS buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", "item.gtceu.shovel_extruder_mold.tooltip": "sןǝʌoɥS buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", @@ -4650,7 +4679,10 @@ "ldlib.gui.editor.register.editor.gtceu.template_tab": "sǝʇɐןdɯǝʇ", "mataarmor.hud.supply_mode": "%s :ǝpoW ʎןddnS", "material.gtceu.acetic_acid": "pıɔⱯ ɔıʇǝɔⱯ", + "material.gtceu.acetic_anhydride": "ǝpıɹpʎɥuⱯ ɔıʇǝɔⱯ", "material.gtceu.acetone": "ǝuoʇǝɔⱯ", + "material.gtceu.acidic_bromine_exhaust": "ʇsnɐɥxƎ ǝuıɯoɹᗺ ɔıpıɔⱯ", + "material.gtceu.acidic_bromine_solution": "uoıʇnןoS ǝuıɯoɹᗺ ɔıpıɔⱯ", "material.gtceu.acidic_enriched_naquadah_solution": "uoıʇnןoS ɥɐpɐnbɐN pǝɥɔıɹuƎ ɔıpıɔⱯ", "material.gtceu.acidic_naquadria_solution": "uoıʇnןoS ɐıɹpɐnbɐN ɔıpıɔⱯ", "material.gtceu.acidic_osmium_solution": "uoıʇnןoS ɯnıɯsO ɔıpıɔⱯ", @@ -4665,8 +4697,10 @@ "material.gtceu.alunite": "ǝʇıunןⱯ", "material.gtceu.americium": "ɯnıɔıɹǝɯⱯ", "material.gtceu.amethyst": "ʇsʎɥʇǝɯⱯ", + "material.gtceu.aminophenol": "ןouǝɥdouıɯⱯ", "material.gtceu.ammonia": "ɐıuoɯɯⱯ", "material.gtceu.ammonium_chloride": "ǝpıɹoןɥƆ ɯnıuoɯɯⱯ", + "material.gtceu.ammonium_formate": "ǝʇɐɯɹoℲ ɯnıuoɯɯⱯ", "material.gtceu.andesite": "ǝʇısǝpuⱯ", "material.gtceu.andradite": "ǝʇıpɐɹpuⱯ", "material.gtceu.annealed_copper": "ɹǝddoƆ pǝןɐǝuuⱯ", @@ -4718,6 +4752,7 @@ "material.gtceu.borosilicate_glass": "ssɐן⅁ ǝʇɐɔıןısoɹoᗺ", "material.gtceu.brass": "ssɐɹᗺ", "material.gtceu.brick": "ʞɔıɹᗺ", + "material.gtceu.brominated_chlorine_vapor": "ɹodɐΛ ǝuıɹoןɥƆ pǝʇɐuıɯoɹᗺ", "material.gtceu.bromine": "ǝuıɯoɹᗺ", "material.gtceu.bronze": "ǝzuoɹᗺ", "material.gtceu.brown_dye": "ǝʎᗡ uʍoɹᗺ", @@ -4729,7 +4764,10 @@ "material.gtceu.caesium": "ɯnısǝɐƆ", "material.gtceu.calcite": "ǝʇıɔןɐƆ", "material.gtceu.calcium": "ɯnıɔןɐƆ", + "material.gtceu.calcium_carbonate": "ǝʇɐuoqɹɐƆ ɯnıɔןɐƆ", "material.gtceu.calcium_chloride": "ǝpıɹoןɥƆ ɯnıɔןɐƆ", + "material.gtceu.calcium_ferrocyanide": "ǝpıuɐʎɔoɹɹǝℲ ɯnıɔןɐƆ", + "material.gtceu.calcium_hydroxide": "ǝpıxoɹpʎH ɯnıɔןɐƆ", "material.gtceu.calcium_phosphide": "ǝpıɥdsoɥԀ ɯnıɔןɐƆ", "material.gtceu.californium": "ɯnıuɹoɟıןɐƆ", "material.gtceu.caprolactam": "ɯɐʇɔɐןoɹdɐƆ", @@ -4764,6 +4802,7 @@ "material.gtceu.cocoa": "ɐoɔoƆ", "material.gtceu.coke": "ǝʞoƆ", "material.gtceu.collagen": "uǝbɐןןoƆ", + "material.gtceu.concentrated_bromine_solution": "uoıʇnןoS ǝuıɯoɹᗺ pǝʇɐɹʇuǝɔuoƆ", "material.gtceu.concrete": "ǝʇǝɹɔuoƆ", "material.gtceu.construction_foam": "ɯɐoℲ uoıʇɔnɹʇsuoƆ", "material.gtceu.cooperite": "ǝʇıuopןǝɥS", @@ -4780,6 +4819,7 @@ "material.gtceu.damascus_steel": "ןǝǝʇS snɔsɐɯɐᗡ", "material.gtceu.dark_ash": "ɥsⱯ ʞɹɐᗡ", "material.gtceu.darmstadtium": "ɯnıʇpɐʇsɯɹɐᗡ", + "material.gtceu.debrominated_brine": "ǝuıɹᗺ pǝʇɐuıɯoɹqǝᗡ", "material.gtceu.deepslate": "ǝʇɐןsdǝǝᗡ", "material.gtceu.depleted_uranium_hexafluoride": "ǝpıɹonןɟɐxǝH ɯnıuɐɹ∩ pǝʇǝןdǝᗡ", "material.gtceu.deuterium": "ɯnıɹǝʇnǝᗡ", @@ -4788,7 +4828,12 @@ "material.gtceu.diatomite": "ǝʇıɯoʇɐıᗡ", "material.gtceu.dichlorobenzene": "ǝuǝzuǝqoɹoןɥɔıᗡ", "material.gtceu.dichlorobenzidine": "ǝuıpızuǝqoɹoןɥɔıᗡ", + "material.gtceu.dichloroethane": "ǝuɐɥʇǝoɹoןɥɔıᗡ", "material.gtceu.diesel": "ןǝsǝıᗡ", + "material.gtceu.diethylenetriamine": "ǝuıɯɐıɹʇǝuǝןʎɥʇǝıᗡ", + "material.gtceu.diethylenetriamine_pentaacetonitrile": "ǝןıɹʇıuoʇǝɔɐɐʇuǝԀ ǝuıɯɐıɹʇǝuǝןʎɥʇǝıᗡ", + "material.gtceu.diethylenetriaminepentaacetic_acid": "pıɔⱯ ɔıʇǝɔɐɐʇuǝdǝuıɯɐıɹʇǝuǝןʎɥʇǝıᗡ", + "material.gtceu.dilute_iodine_solution": "uoıʇnןoS ǝuıpoI ǝʇnןıᗡ", "material.gtceu.diluted_hydrochloric_acid": "pıɔⱯ ɔıɹoןɥɔoɹpʎH pǝʇnןıᗡ", "material.gtceu.diluted_sulfuric_acid": "pıɔⱯ ɔıɹnɟןnS pǝʇnןıᗡ", "material.gtceu.dimethylamine": "ǝuıɯɐןʎɥʇǝɯıᗡ", @@ -4839,6 +4884,9 @@ "material.gtceu.flint": "ʇuıןℲ", "material.gtceu.fluorine": "ǝuıɹonןℲ", "material.gtceu.fluoroantimonic_acid": "pıɔⱯ ɔıuoɯıʇuɐoɹonןℲ", + "material.gtceu.formaldehyde": "ǝpʎɥǝpןɐɯɹoℲ", + "material.gtceu.formamide": "ǝpıɯɐɯɹoℲ", + "material.gtceu.formic_acid": "pıɔⱯ ɔıɯɹoℲ", "material.gtceu.francium": "ɯnıɔuɐɹℲ", "material.gtceu.fullers_earth": "ɥʇɹɐƎ s,ɹǝןןnℲ", "material.gtceu.gadolinium": "ɯnıuıןopɐ⅁", @@ -4858,6 +4906,7 @@ "material.gtceu.glue": "ǝnן⅁", "material.gtceu.glycerol": "ןoɹǝɔʎן⅁", "material.gtceu.glyceryl_trinitrate": "ǝʇɐɹʇıuıɹ⟘ ןʎɹǝɔʎן⅁", + "material.gtceu.glycolonitrile": "ǝןıɹʇıuoןoɔʎן⅁", "material.gtceu.goethite": "ǝʇıɥʇǝo⅁", "material.gtceu.gold": "pןo⅁", "material.gtceu.granite": "ǝʇıuɐɹ⅁", @@ -4882,6 +4931,10 @@ "material.gtceu.hematite": "ǝʇıʇɐɯǝH", "material.gtceu.high_octane_gasoline": "ǝuıןosɐ⅁ ǝuɐʇɔO ɥbıH", "material.gtceu.holmium": "ɯnıɯןoH", + "material.gtceu.hot_alkaline_debrominated_brine": "ǝuıɹᗺ pǝʇɐuıɯoɹqǝᗡ ǝuıןɐʞןⱯ ʇoH", + "material.gtceu.hot_brine": "ǝuıɹᗺ ʇoH", + "material.gtceu.hot_chlorinated_brominated_brine": "ǝuıɹᗺ pǝʇɐuıɯoɹᗺ pǝʇɐuıɹoןɥƆ ʇoH", + "material.gtceu.hot_debrominated_brine": "ǝuıɹᗺ pǝʇɐuıɯoɹqǝᗡ ʇoH", "material.gtceu.hsla_steel": "ןǝǝʇS ɐןsH", "material.gtceu.hsse": "Ǝ-SSH", "material.gtceu.hssg": "⅁-SSH", @@ -4896,6 +4949,7 @@ "material.gtceu.hydrochloric_acid": "pıɔⱯ ɔıɹoןɥɔoɹpʎH", "material.gtceu.hydrofluoric_acid": "pıɔⱯ ɔıɹonןɟoɹpʎH", "material.gtceu.hydrogen": "uǝboɹpʎH", + "material.gtceu.hydrogen_cyanide": "ǝpıuɐʎƆ uǝboɹpʎH", "material.gtceu.hydrogen_sulfide": "ǝpıɟןnS uǝboɹpʎH", "material.gtceu.hypochlorous_acid": "pıɔⱯ snoɹoןɥɔodʎH", "material.gtceu.ice": "ǝɔI", @@ -4910,11 +4964,14 @@ "material.gtceu.indium_tin_barium_titanium_cuprate": "ǝʇɐɹdnƆ ɯnıuɐʇı⟘ ɯnıɹɐᗺ uı⟘ ɯnıpuI", "material.gtceu.inert_metal_mixture": "ǝɹnʇxıW ןɐʇǝW ʇɹǝuI", "material.gtceu.invar": "ɹɐʌuI", + "material.gtceu.iodide": "ǝpıpoI", "material.gtceu.iodine": "ǝuıpoI", + "material.gtceu.iodine_solution": "uoıʇnןoS ǝuıpoI", "material.gtceu.iridium": "ɯnıpıɹI", "material.gtceu.iridium_chloride": "ǝpıɹoןɥƆ ɯnıpıɹI", "material.gtceu.iridium_metal_residue": "ǝnpısǝᴚ ןɐʇǝW ɯnıpıɹI", "material.gtceu.iron": "uoɹI", + "material.gtceu.iron_ii_chloride": "ǝpıɹoןɥƆ II uoɹI", "material.gtceu.iron_iii_chloride": "ǝpıɹoןɥƆ III uoɹI", "material.gtceu.isoprene": "ǝuǝɹdosI", "material.gtceu.kanthal": "ןɐɥʇuɐʞ", @@ -5040,6 +5097,7 @@ "material.gtceu.palladium": "ɯnıpɐןןɐԀ", "material.gtceu.palladium_raw": "ʍɐᴚ ɯnıpɐןןɐԀ", "material.gtceu.paper": "ɹǝdɐԀ", + "material.gtceu.paracetamol": "ןoɯɐʇǝɔɐɹɐԀ", "material.gtceu.pcb_coolant": "ʇuɐןooƆ ᗺƆԀ", "material.gtceu.pentlandite": "ǝʇıpuɐןʇuǝԀ", "material.gtceu.perlite": "ǝʇıןɹǝԀ", @@ -5071,8 +5129,14 @@ "material.gtceu.polyvinyl_chloride": "ǝpıɹoןɥƆ ןʎuıʌʎןoԀ", "material.gtceu.potash": "ɥsɐʇoԀ", "material.gtceu.potassium": "ɯnıssɐʇoԀ", + "material.gtceu.potassium_carbonate": "ǝʇɐuoqɹɐƆ ɯnıssɐʇoԀ", + "material.gtceu.potassium_cyanide": "ǝpıuɐʎƆ ɯnıssɐʇoԀ", "material.gtceu.potassium_dichromate": "ǝʇɐɯoɹɥɔıᗡ ɯnıssɐʇoԀ", "material.gtceu.potassium_feldspar": "ɹɐdspןǝℲ ɯnıssɐʇoԀ", + "material.gtceu.potassium_ferrocyanide": "ǝpıuɐʎɔoɹɹǝℲ ɯnıssɐʇoԀ", + "material.gtceu.potassium_hydroxide": "ǝpıxoɹpʎH ɯnıssɐʇoԀ", + "material.gtceu.potassium_iodide": "ǝpıpoI ɯnıssɐʇoԀ", + "material.gtceu.potassium_sulfate": "ǝʇɐɟןnS ɯnıssɐʇoԀ", "material.gtceu.potin": "uıʇoԀ", "material.gtceu.powellite": "ǝʇıןןǝʍoԀ", "material.gtceu.praseodymium": "ɯnıɯʎpoǝsɐɹԀ", @@ -5080,6 +5144,7 @@ "material.gtceu.propane": "ǝuɐdoɹԀ", "material.gtceu.propene": "ǝuǝdoɹԀ", "material.gtceu.protactinium": "ɯnıuıʇɔɐʇoɹԀ", + "material.gtceu.prussian_blue": "ǝnןᗺ uɐıssnɹԀ", "material.gtceu.purple_dye": "ǝʎᗡ ǝןdɹnԀ", "material.gtceu.pyrite": "ǝʇıɹʎԀ", "material.gtceu.pyrochlore": "ǝɹoןɥɔoɹʎԀ", @@ -5088,10 +5153,12 @@ "material.gtceu.quartz_sand": "puɐS zʇɹɐnὉ", "material.gtceu.quartzite": "ǝʇızʇɹɐnὉ", "material.gtceu.quicklime": "ǝɯıןʞɔınὉ", + "material.gtceu.rad_away": "ʎɐʍⱯ pɐᴚ", "material.gtceu.radium": "ɯnıpɐᴚ", "material.gtceu.radon": "uopɐᴚ", "material.gtceu.rare_earth": "ɥʇɹɐƎ ǝɹɐᴚ", "material.gtceu.rarest_metal_mixture": "ǝɹnʇxıW ןɐʇǝW ʇsǝɹɐᴚ", + "material.gtceu.raw_brine": "ǝuıɹᗺ ʍɐᴚ", "material.gtceu.raw_gasoline": "ǝuıןosɐ⅁ ʍɐᴚ", "material.gtceu.raw_growth_medium": "ɯnıpǝW ɥʇʍoɹ⅁ ʍɐᴚ", "material.gtceu.raw_rubber": "ɹǝqqnᴚ ʍɐᴚ", @@ -5155,6 +5222,7 @@ "material.gtceu.sodium_bicarbonate": "ǝʇɐuoqɹɐɔıᗺ ɯnıpoS", "material.gtceu.sodium_bisulfate": "ǝʇɐɟןnsıᗺ ɯnıpoS", "material.gtceu.sodium_hydroxide": "ǝpıxoɹpʎH ɯnıpoS", + "material.gtceu.sodium_nitrite": "ǝʇıɹʇıN ɯnıpoS", "material.gtceu.sodium_persulfate": "ǝʇɐɟןnsɹǝԀ ɯnıpoS", "material.gtceu.sodium_potassium": "ɯnıssɐʇoԀ ɯnıpoS", "material.gtceu.sodium_sulfide": "ǝpıɟןnS ɯnıpoS", @@ -5370,6 +5438,7 @@ "recipe.condition.thunder.tooltip": "%d :ןǝʌǝꞀ ɹǝpunɥ⟘", "tagprefix.andesite": "ǝɹO %s ǝʇısǝpuⱯ", "tagprefix.basalt": "ǝɹO %s ʇןɐsɐᗺ", + "tagprefix.blackstone": "ǝɹO %s ǝuoʇsʞɔɐןᗺ", "tagprefix.block": "%s ɟo ʞɔoןᗺ", "tagprefix.bolt": "ʇןoᗺ %s", "tagprefix.buzz_saw_blade": "ǝpɐןᗺ ʍɐszznᗺ %s", @@ -5476,4 +5545,4 @@ "tile.gtceu.reinforced_foam.name": "ɯɐoℲ pǝɔɹoɟuıǝᴚ", "tile.gtceu.reinforced_stone.name": "ǝuoʇS pǝɔɹoɟuıǝᴚ", "tile.gtceu.seal.name": "ʞɔoןᗺ pǝןɐǝS" -} \ No newline at end of file +} diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 2c852f3819..ed735703a1 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -239,6 +239,7 @@ "block.gtceu.ev_transformer_4a": "Extreme Voltage Hi-Amp (4x) Transformer", "block.gtceu.ev_wiremill": "§5Advanced Wiremill III§r", "block.gtceu.ev_world_accelerator": "§5Advanced World Accelerator III§r", + "block.gtceu.evaporation_plant": "Evaporation Tower", "block.gtceu.explosion_hazard_sign_block": "Explosion Hazard Sign Block", "block.gtceu.explosive.breaking_tooltip": "Primes explosion when mined, sneak mine to pick back up", "block.gtceu.explosive.lighting_tooltip": "Cannot be lit with Redstone", @@ -952,6 +953,7 @@ "block.gtceu.square_marble_bricks": "Square Marble Bricks", "block.gtceu.square_red_granite_bricks": "Square Red Granite Bricks", "block.gtceu.stable_machine_casing": "Stable Titanium Machine Casing", + "block.gtceu.stainless_evaporation_casing": "Stainless Evaporation Casing", "block.gtceu.stainless_steel_crate": "Stainless Steel Crate", "block.gtceu.stainless_steel_drum": "Stainless Steel Drum", "block.gtceu.stainless_steel_gearbox": "Stainless Steel Gearbox Casing", @@ -1645,6 +1647,7 @@ "compass.node.gtceu.ev/large_miner": "Large Miner", "compass.node.gtceu.generation/andesite": "Andesite", "compass.node.gtceu.generation/basalt": "Basalt", + "compass.node.gtceu.generation/blackstone": "Blackstone", "compass.node.gtceu.generation/deepslate": "Deepslate", "compass.node.gtceu.generation/diorite": "Diorite", "compass.node.gtceu.generation/endstone": "Endstone", @@ -2008,6 +2011,7 @@ "compass.section.gtceu.uv": "§3UV Voltage", "compass.section.gtceu.zpm": "§cZPM Voltage", "config.gtceu.option.addLoot": "addLoot", + "config.gtceu.option.ae2": "ae2", "config.gtceu.option.allUniqueStoneTypes": "allUniqueStoneTypes", "config.gtceu.option.animationTime": "animationTime", "config.gtceu.option.armorHud": "armorHud", @@ -2036,6 +2040,7 @@ "config.gtceu.option.enableTieredCasings": "enableTieredCasings", "config.gtceu.option.enableWorldAccelerators": "enableWorldAccelerators", "config.gtceu.option.energy": "energy", + "config.gtceu.option.energyConsumption": "energyConsumption", "config.gtceu.option.energyUsageMultiplier": "energyUsageMultiplier", "config.gtceu.option.euToPlatformRatio": "euToPlatformRatio", "config.gtceu.option.flintAndSteelRequireSteel": "flintAndSteelRequireSteel", @@ -2055,11 +2060,11 @@ "config.gtceu.option.harderCharcoalRecipe": "harderCharcoalRecipe", "config.gtceu.option.harderCircuitRecipes": "harderCircuitRecipes", "config.gtceu.option.harderRods": "harderRods", - "config.gtceu.option.hideOreProcessingDiagrams": "hideOreProcessingDiagrams", "config.gtceu.option.harmlessActiveTransformers": "harmlessActiveTransformers", "config.gtceu.option.hazardsEnabled": "hazardsEnabled", "config.gtceu.option.hideFacadesInJEI": "hideFacadesInJEI", "config.gtceu.option.hideFilledCellsInJEI": "hideFilledCellsInJEI", + "config.gtceu.option.hideOreProcessingDiagrams": "hideOreProcessingDiagrams", "config.gtceu.option.highTierContent": "highTierContent", "config.gtceu.option.hudLocation": "hudLocation", "config.gtceu.option.hudOffsetX": "hudOffsetX", @@ -2072,6 +2077,9 @@ "config.gtceu.option.machineSounds": "machineSounds", "config.gtceu.option.machines": "machines", "config.gtceu.option.machinesEmissiveTextures": "machinesEmissiveTextures", + "config.gtceu.option.nanoSaber": "nanoSaber", + "config.gtceu.option.nanoSaberBaseDamage": "nanoSaberBaseDamage", + "config.gtceu.option.nanoSaberDamageBoost": "nanoSaberDamageBoost", "config.gtceu.option.nativeEUToPlatformNative": "nativeEUToPlatformNative", "config.gtceu.option.nerfPaperCrafting": "nerfPaperCrafting", "config.gtceu.option.nerfWoodCrafting": "nerfWoodCrafting", @@ -2100,9 +2108,18 @@ "config.gtceu.option.toolCraftingSounds": "toolCraftingSounds", "config.gtceu.option.toolUseSounds": "toolUseSounds", "config.gtceu.option.tools": "tools", + "config.gtceu.option.universalHazards": "universalHazards", "config.gtceu.option.useVBO": "useVBO", + "config.gtceu.option.voltageTierAdvImpeller": "voltageTierAdvImpeller", + "config.gtceu.option.voltageTierAdvNanoSuit": "voltageTierAdvNanoSuit", + "config.gtceu.option.voltageTierAdvQuarkTech": "voltageTierAdvQuarkTech", + "config.gtceu.option.voltageTierImpeller": "voltageTierImpeller", + "config.gtceu.option.voltageTierNanoSuit": "voltageTierNanoSuit", + "config.gtceu.option.voltageTierNightVision": "voltageTierNightVision", + "config.gtceu.option.voltageTierQuarkTech": "voltageTierQuarkTech", "config.gtceu.option.worldAcceleratorBlacklist": "worldAcceleratorBlacklist", "config.gtceu.option.worldgen": "worldgen", + "config.gtceu.option.zombieSpawnWithSabers": "zombieSpawnWithSabers", "config.jade.plugin_gtceu.controllable_provider": "[GTCEu] Controllable", "config.jade.plugin_gtceu.electric_container_provider": "[GTCEu] Electric Container", "config.jade.plugin_gtceu.recipe_logic_provider": "[GTCEu] Recipe Logic", @@ -2308,6 +2325,7 @@ "death.attack.gtceu.wrench_hv": "%s's pipes were loosened by %s", "death.attack.gtceu.wrench_iv": "%s had a Monkey Wrench thrown into their plans by %s", "death.attack.gtceu.wrench_lv": "%s's pipes were loosened by %s", + "effect.gtceu.weak_poison": "Weak Poison", "enchantment.damage.disjunction": "Disjunction", "enchantment.disjunction": "Disjunction", "enchantment.gtceu.disjunction.desc": "Applies Weakness and Slowness to Ender-related mobs.", @@ -2407,6 +2425,7 @@ "gtceu.electric_furnace": "Electric Furnace", "gtceu.electrolyzer": "Electrolyzer", "gtceu.electromagnetic_separator": "Electromagnetic Separator", + "gtceu.evaporation": "Evaporation", "gtceu.extractor": "Extractor", "gtceu.extruder": "Extruder", "gtceu.fermenter": "Fermenter", @@ -2527,6 +2546,10 @@ "gtceu.gui.title_bar.page_switcher": "Pages", "gtceu.gui.toggle_view.disabled": "Toggle View (Fluids)", "gtceu.gui.toggle_view.enabled": "Toggle View (Items)", + "gtceu.hazard.antidote.description": "§aAntidote §7Hold Shift to show details", + "gtceu.hazard.antidote.description.time_removed": "Removes %ss of current ailments' time", + "gtceu.hazard.antidote.description.time_removed.all": "all", + "gtceu.hazard.antidote.description_shift": "§aCures types:", "gtceu.hazard.contact_poison": "§5Contact Poison", "gtceu.hazard.corrosive": "§6Corrosive", "gtceu.hazard.description": "§l§cHAZARDOUS §7Hold Shift to show details", @@ -3858,6 +3881,7 @@ "item.gtceu.exquisite_glass_gem": "Exquisite Glass Crystal", "item.gtceu.facade_cover": "%s Cover Facade", "item.gtceu.facade_cover.tooltip": "§7Decorative Outfit §fCover§7.", + "item.gtceu.face_mask": "Face Mask", "item.gtceu.fertilizer": "Fertilizer", "item.gtceu.fiber_reinforced_circuit_board": "Fiber-Reinforced Circuit Board", "item.gtceu.fiber_reinforced_circuit_board.tooltip": "§7An Extreme Board", @@ -4193,6 +4217,7 @@ "item.gtceu.osmium_credit.tooltip": "§74096 Credits", "item.gtceu.palladium_raw_dust": "Raw Palladium Powder", "item.gtceu.paper_dust": "Chad", + "item.gtceu.paracetamol_pill": "Paracetamol Pill", "item.gtceu.petri_dish": "Petri Dish", "item.gtceu.petri_dish.tooltip": "§7For cultivating Cells", "item.gtceu.phenolic_circuit_board": "Phenolic Circuit Board", @@ -4204,6 +4229,7 @@ "item.gtceu.phosphorus_wafer": "Phosphorus-doped Wafer", "item.gtceu.phosphorus_wafer.tooltip": "§7Raw Circuit", "item.gtceu.pickaxe_extruder_mold.tooltip": "§7Extruder Shape for making Pickaxes", + "item.gtceu.pill_casting_mold": "Casting Mold (Pill)", "item.gtceu.pink_dye_spray_can": "Spray Can (Pink)", "item.gtceu.pink_glass_lens": "Glass Lens (Pink)", "item.gtceu.pipe.huge_extruder_mold.tooltip": "§7Extruder Shape for making full Block Pipes", @@ -4272,6 +4298,7 @@ "item.gtceu.quarktech_helmet": "QuarkTech™ Suite Helmet", "item.gtceu.quarktech_leggings": "QuarkTech™ Suite Leggings", "item.gtceu.quartz_sand_dust": "Quartz Sand", + "item.gtceu.rad_away_pill": "RadAway™ Pill", "item.gtceu.ram_chip": "RAM Chip", "item.gtceu.ram_chip.tooltip": "§7Random Access Memory", "item.gtceu.ram_wafer": "RAM Wafer", @@ -4305,6 +4332,7 @@ "item.gtceu.rotor_casting_mold.tooltip": "§7Mold for making Rotors", "item.gtceu.rotor_extruder_mold": "Extruder Mold (Rotor)", "item.gtceu.rotor_extruder_mold.tooltip": "§7Extruder Shape for making Rotors", + "item.gtceu.rubber_gloves": "Rubber Gloves", "item.gtceu.salt_dust": "Salt", "item.gtceu.saw_extruder_mold.tooltip": "§7Extruder Shape for making Saws", "item.gtceu.shovel_extruder_mold.tooltip": "§7Extruder Shape for making Shovels", @@ -4651,7 +4679,10 @@ "ldlib.gui.editor.register.editor.gtceu.template_tab": "templates", "mataarmor.hud.supply_mode": "Supply Mode: %s", "material.gtceu.acetic_acid": "Acetic Acid", + "material.gtceu.acetic_anhydride": "Acetic Anhydride", "material.gtceu.acetone": "Acetone", + "material.gtceu.acidic_bromine_exhaust": "Acidic Bromine Exhaust", + "material.gtceu.acidic_bromine_solution": "Acidic Bromine Solution", "material.gtceu.acidic_enriched_naquadah_solution": "Acidic Enriched Naquadah Solution", "material.gtceu.acidic_naquadria_solution": "Acidic Naquadria Solution", "material.gtceu.acidic_osmium_solution": "Acidic Osmium Solution", @@ -4666,8 +4697,10 @@ "material.gtceu.alunite": "Alunite", "material.gtceu.americium": "Americium", "material.gtceu.amethyst": "Amethyst", + "material.gtceu.aminophenol": "Aminophenol", "material.gtceu.ammonia": "Ammonia", "material.gtceu.ammonium_chloride": "Ammonium Chloride", + "material.gtceu.ammonium_formate": "Ammonium Formate", "material.gtceu.andesite": "Andesite", "material.gtceu.andradite": "Andradite", "material.gtceu.annealed_copper": "Annealed Copper", @@ -4719,6 +4752,7 @@ "material.gtceu.borosilicate_glass": "Borosilicate Glass", "material.gtceu.brass": "Brass", "material.gtceu.brick": "Brick", + "material.gtceu.brominated_chlorine_vapor": "Brominated Chlorine Vapor", "material.gtceu.bromine": "Bromine", "material.gtceu.bronze": "Bronze", "material.gtceu.brown_dye": "Brown Dye", @@ -4730,7 +4764,10 @@ "material.gtceu.caesium": "Caesium", "material.gtceu.calcite": "Calcite", "material.gtceu.calcium": "Calcium", + "material.gtceu.calcium_carbonate": "Calcium Carbonate", "material.gtceu.calcium_chloride": "Calcium Chloride", + "material.gtceu.calcium_ferrocyanide": "Calcium Ferrocyanide", + "material.gtceu.calcium_hydroxide": "Calcium Hydroxide", "material.gtceu.calcium_phosphide": "Calcium Phosphide", "material.gtceu.californium": "Californium", "material.gtceu.caprolactam": "Caprolactam", @@ -4765,6 +4802,7 @@ "material.gtceu.cocoa": "Cocoa", "material.gtceu.coke": "Coke", "material.gtceu.collagen": "Collagen", + "material.gtceu.concentrated_bromine_solution": "Concentrated Bromine Solution", "material.gtceu.concrete": "Concrete", "material.gtceu.construction_foam": "Construction Foam", "material.gtceu.cooperite": "Sheldonite", @@ -4781,6 +4819,7 @@ "material.gtceu.damascus_steel": "Damascus Steel", "material.gtceu.dark_ash": "Dark Ash", "material.gtceu.darmstadtium": "Darmstadtium", + "material.gtceu.debrominated_brine": "Debrominated Brine", "material.gtceu.deepslate": "Deepslate", "material.gtceu.depleted_uranium_hexafluoride": "Depleted Uranium Hexafluoride", "material.gtceu.deuterium": "Deuterium", @@ -4789,7 +4828,12 @@ "material.gtceu.diatomite": "Diatomite", "material.gtceu.dichlorobenzene": "Dichlorobenzene", "material.gtceu.dichlorobenzidine": "Dichlorobenzidine", + "material.gtceu.dichloroethane": "Dichloroethane", "material.gtceu.diesel": "Diesel", + "material.gtceu.diethylenetriamine": "Diethylenetriamine", + "material.gtceu.diethylenetriamine_pentaacetonitrile": "Diethylenetriamine Pentaacetonitrile", + "material.gtceu.diethylenetriaminepentaacetic_acid": "Diethylenetriaminepentaacetic Acid", + "material.gtceu.dilute_iodine_solution": "Dilute Iodine Solution", "material.gtceu.diluted_hydrochloric_acid": "Diluted Hydrochloric Acid", "material.gtceu.diluted_sulfuric_acid": "Diluted Sulfuric Acid", "material.gtceu.dimethylamine": "Dimethylamine", @@ -4840,6 +4884,9 @@ "material.gtceu.flint": "Flint", "material.gtceu.fluorine": "Fluorine", "material.gtceu.fluoroantimonic_acid": "Fluoroantimonic Acid", + "material.gtceu.formaldehyde": "Formaldehyde", + "material.gtceu.formamide": "Formamide", + "material.gtceu.formic_acid": "Formic Acid", "material.gtceu.francium": "Francium", "material.gtceu.fullers_earth": "Fuller's Earth", "material.gtceu.gadolinium": "Gadolinium", @@ -4859,6 +4906,7 @@ "material.gtceu.glue": "Glue", "material.gtceu.glycerol": "Glycerol", "material.gtceu.glyceryl_trinitrate": "Glyceryl Trinitrate", + "material.gtceu.glycolonitrile": "Glycolonitrile", "material.gtceu.goethite": "Goethite", "material.gtceu.gold": "Gold", "material.gtceu.granite": "Granite", @@ -4883,6 +4931,10 @@ "material.gtceu.hematite": "Hematite", "material.gtceu.high_octane_gasoline": "High Octane Gasoline", "material.gtceu.holmium": "Holmium", + "material.gtceu.hot_alkaline_debrominated_brine": "Hot Alkaline Debrominated Brine", + "material.gtceu.hot_brine": "Hot Brine", + "material.gtceu.hot_chlorinated_brominated_brine": "Hot Chlorinated Brominated Brine", + "material.gtceu.hot_debrominated_brine": "Hot Debrominated Brine", "material.gtceu.hsla_steel": "Hsla Steel", "material.gtceu.hsse": "HSS-E", "material.gtceu.hssg": "HSS-G", @@ -4897,6 +4949,7 @@ "material.gtceu.hydrochloric_acid": "Hydrochloric Acid", "material.gtceu.hydrofluoric_acid": "Hydrofluoric Acid", "material.gtceu.hydrogen": "Hydrogen", + "material.gtceu.hydrogen_cyanide": "Hydrogen Cyanide", "material.gtceu.hydrogen_sulfide": "Hydrogen Sulfide", "material.gtceu.hypochlorous_acid": "Hypochlorous Acid", "material.gtceu.ice": "Ice", @@ -4911,11 +4964,14 @@ "material.gtceu.indium_tin_barium_titanium_cuprate": "Indium Tin Barium Titanium Cuprate", "material.gtceu.inert_metal_mixture": "Inert Metal Mixture", "material.gtceu.invar": "Invar", + "material.gtceu.iodide": "Iodide", "material.gtceu.iodine": "Iodine", + "material.gtceu.iodine_solution": "Iodine Solution", "material.gtceu.iridium": "Iridium", "material.gtceu.iridium_chloride": "Iridium Chloride", "material.gtceu.iridium_metal_residue": "Iridium Metal Residue", "material.gtceu.iron": "Iron", + "material.gtceu.iron_ii_chloride": "Iron II Chloride", "material.gtceu.iron_iii_chloride": "Iron III Chloride", "material.gtceu.isoprene": "Isoprene", "material.gtceu.kanthal": "Kanthal", @@ -5041,6 +5097,7 @@ "material.gtceu.palladium": "Palladium", "material.gtceu.palladium_raw": "Palladium Raw", "material.gtceu.paper": "Paper", + "material.gtceu.paracetamol": "Paracetamol", "material.gtceu.pcb_coolant": "PCB Coolant", "material.gtceu.pentlandite": "Pentlandite", "material.gtceu.perlite": "Perlite", @@ -5072,8 +5129,14 @@ "material.gtceu.polyvinyl_chloride": "Polyvinyl Chloride", "material.gtceu.potash": "Potash", "material.gtceu.potassium": "Potassium", + "material.gtceu.potassium_carbonate": "Potassium Carbonate", + "material.gtceu.potassium_cyanide": "Potassium Cyanide", "material.gtceu.potassium_dichromate": "Potassium Dichromate", "material.gtceu.potassium_feldspar": "Potassium Feldspar", + "material.gtceu.potassium_ferrocyanide": "Potassium Ferrocyanide", + "material.gtceu.potassium_hydroxide": "Potassium Hydroxide", + "material.gtceu.potassium_iodide": "Potassium Iodide", + "material.gtceu.potassium_sulfate": "Potassium Sulfate", "material.gtceu.potin": "Potin", "material.gtceu.powellite": "Powellite", "material.gtceu.praseodymium": "Praseodymium", @@ -5081,6 +5144,7 @@ "material.gtceu.propane": "Propane", "material.gtceu.propene": "Propene", "material.gtceu.protactinium": "Protactinium", + "material.gtceu.prussian_blue": "Prussian Blue", "material.gtceu.purple_dye": "Purple Dye", "material.gtceu.pyrite": "Pyrite", "material.gtceu.pyrochlore": "Pyrochlore", @@ -5089,10 +5153,12 @@ "material.gtceu.quartz_sand": "Quartz Sand", "material.gtceu.quartzite": "Quartzite", "material.gtceu.quicklime": "Quicklime", + "material.gtceu.rad_away": "Rad Away", "material.gtceu.radium": "Radium", "material.gtceu.radon": "Radon", "material.gtceu.rare_earth": "Rare Earth", "material.gtceu.rarest_metal_mixture": "Rarest Metal Mixture", + "material.gtceu.raw_brine": "Raw Brine", "material.gtceu.raw_gasoline": "Raw Gasoline", "material.gtceu.raw_growth_medium": "Raw Growth Medium", "material.gtceu.raw_rubber": "Raw Rubber", @@ -5156,6 +5222,7 @@ "material.gtceu.sodium_bicarbonate": "Sodium Bicarbonate", "material.gtceu.sodium_bisulfate": "Sodium Bisulfate", "material.gtceu.sodium_hydroxide": "Sodium Hydroxide", + "material.gtceu.sodium_nitrite": "Sodium Nitrite", "material.gtceu.sodium_persulfate": "Sodium Persulfate", "material.gtceu.sodium_potassium": "Sodium Potassium", "material.gtceu.sodium_sulfide": "Sodium Sulfide", @@ -5371,6 +5438,7 @@ "recipe.condition.thunder.tooltip": "Thunder Level: %d", "tagprefix.andesite": "Andesite %s Ore", "tagprefix.basalt": "Basalt %s Ore", + "tagprefix.blackstone": "Blackstone %s Ore", "tagprefix.block": "Block of %s", "tagprefix.bolt": "%s Bolt", "tagprefix.buzz_saw_blade": "%s Buzzsaw Blade", @@ -5477,4 +5545,4 @@ "tile.gtceu.reinforced_foam.name": "Reinforced Foam", "tile.gtceu.reinforced_stone.name": "Reinforced Stone", "tile.gtceu.seal.name": "Sealed Block" -} \ No newline at end of file +} diff --git a/src/generated/resources/assets/gtceu/models/item/face_mask.json b/src/generated/resources/assets/gtceu/models/item/face_mask.json new file mode 100644 index 0000000000..f3ce0ba31c --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/face_mask.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/face_mask" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/paracetamol_pill.json b/src/generated/resources/assets/gtceu/models/item/paracetamol_pill.json new file mode 100644 index 0000000000..845b7dea0e --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/paracetamol_pill.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/paracetamol_pill" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/pill_casting_mold.json b/src/generated/resources/assets/gtceu/models/item/pill_casting_mold.json new file mode 100644 index 0000000000..540c29d271 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/pill_casting_mold.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/pill_casting_mold" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/rad_away_pill.json b/src/generated/resources/assets/gtceu/models/item/rad_away_pill.json new file mode 100644 index 0000000000..aaec1fa825 --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/rad_away_pill.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/rad_away_pill" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/gtceu/models/item/rubber_gloves.json b/src/generated/resources/assets/gtceu/models/item/rubber_gloves.json new file mode 100644 index 0000000000..a34980063b --- /dev/null +++ b/src/generated/resources/assets/gtceu/models/item/rubber_gloves.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "gtceu:item/rubber_gloves" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/forge/tags/blocks/mineable/wrench.json b/src/generated/resources/data/forge/tags/blocks/mineable/wrench.json index bfbd1cd616..c397898a5b 100644 --- a/src/generated/resources/data/forge/tags/blocks/mineable/wrench.json +++ b/src/generated/resources/data/forge/tags/blocks/mineable/wrench.json @@ -16,6 +16,7 @@ "gtceu:sturdy_machine_casing", "gtceu:palladium_substation", "gtceu:tempered_glass", + "gtceu:stainless_evaporation_casing", "gtceu:nonconducting_casing", "gtceu:vibration_safe_casing", "gtceu:watertight_casing", diff --git a/src/generated/resources/data/gtceu/loot_tables/blocks/stainless_evaporation_casing.json b/src/generated/resources/data/gtceu/loot_tables/blocks/stainless_evaporation_casing.json new file mode 100644 index 0000000000..e627c10875 --- /dev/null +++ b/src/generated/resources/data/gtceu/loot_tables/blocks/stainless_evaporation_casing.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "gtceu:stainless_evaporation_casing" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "gtceu:blocks/stainless_evaporation_casing" +} \ No newline at end of file diff --git a/src/generated/resources/data/gtceu/tags/items/ppe_armor.json b/src/generated/resources/data/gtceu/tags/items/ppe_armor.json new file mode 100644 index 0000000000..ec5f73fa99 --- /dev/null +++ b/src/generated/resources/data/gtceu/tags/items/ppe_armor.json @@ -0,0 +1,16 @@ +{ + "values": [ + "gtceu:face_mask", + "gtceu:rubber_gloves", + "gtceu:hazmat_chestpiece", + "gtceu:hazmat_leggings", + "gtceu:hazmat_boots", + "gtceu:hazmat_headpiece", + "gtceu:quarktech_chestplate", + "gtceu:quarktech_leggings", + "gtceu:quarktech_boots", + "gtceu:quarktech_helmet", + "gtceu:avanced_nanomuscle_chestplate", + "gtceu:advanced_quarktech_chestplate" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index 04a9b24af7..639bb25724 100644 --- a/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -16,6 +16,7 @@ "gtceu:sturdy_machine_casing", "gtceu:palladium_substation", "gtceu:tempered_glass", + "gtceu:stainless_evaporation_casing", "gtceu:nonconducting_casing", "gtceu:vibration_safe_casing", "gtceu:watertight_casing", diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java index 361c793ba6..d8cb3b798a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java @@ -7,12 +7,14 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.energy.IEnergyStorage; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -117,4 +119,9 @@ private static T getBlockEntityCapability(Capability capability, Level le } return null; } + + @Nullable + public static IHazardEffectTracker getHazardEffectTracker(@NotNull Entity entity) { + return entity.getCapability(GTCapability.CAPABILITY_HAZARD_EFFECT_TRACKER, null).resolve().orElse(null); + } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/IHazardEffectTracker.java b/src/main/java/com/gregtechceu/gtceu/api/capability/IHazardEffectTracker.java new file mode 100644 index 0000000000..ac3a7e7ba0 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/IHazardEffectTracker.java @@ -0,0 +1,34 @@ +package com.gregtechceu.gtceu.api.capability; + +import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; + +import java.util.Map; +import java.util.Set; + +public interface IHazardEffectTracker { + + /** + * @return a map of the hazard types to their effects. + */ + Map> getTypesToEffects(); + + /** + * @return a map of hazard effect to how long it's been applied for. + */ + Object2IntMap getCurrentHazardEffects(); + + /** + * @return the maximum air supply for the entity this is attached to. -1 for default (300). + */ + // default maxAirSupply for players is 300. + int getMaxAirSupply(); + + void removeHazardItem(UnificationEntry entry); + + void addHazardItem(UnificationEntry entry); + + void tick(); +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/forge/GTCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/forge/GTCapability.java index 45f736139d..3330870b89 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/capability/forge/GTCapability.java +++ b/src/main/java/com/gregtechceu/gtceu/api/capability/forge/GTCapability.java @@ -40,6 +40,9 @@ public class GTCapability { public static final Capability CAPABILITY_DATA_ACCESS = CapabilityManager .get(new CapabilityToken<>() {}); + public static final Capability CAPABILITY_HAZARD_EFFECT_TRACKER = CapabilityManager + .get(new CapabilityToken<>() {}); + public static void register(RegisterCapabilitiesEvent event) { event.register(IEnergyContainer.class); event.register(IEnergyInfoProvider.class); @@ -54,5 +57,7 @@ public static void register(RegisterCapabilitiesEvent event) { event.register(ILaserContainer.class); event.register(IOpticalComputationProvider.class); event.register(IDataAccessHatch.class); + + event.register(IHazardEffectTracker.class); } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java index 24352bcf8e..b9cca23106 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/ChemicalHelper.java @@ -15,12 +15,9 @@ import com.gregtechceu.gtceu.data.tags.TagsHandler; import com.gregtechceu.gtceu.utils.SupplierMemoizer; -import com.lowdragmc.lowdraglib.Platform; - import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -28,9 +25,9 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.material.Fluids; import net.minecraftforge.registries.RegistryObject; +import com.mojang.datafixers.util.Pair; import com.tterrag.registrate.util.entry.BlockEntry; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -152,27 +149,24 @@ public static MaterialStack getMaterial(ItemLike itemLike) { @Nullable public static Material getMaterial(Fluid fluid) { - return FLUID_MATERIAL.computeIfAbsent(fluid, f -> { - for (Material material : GTCEuAPI.materialManager.getRegisteredMaterials()) { + if (FLUID_MATERIAL.isEmpty()) { + Set> allFluidTags = BuiltInRegistries.FLUID.getTagNames().collect(Collectors.toSet()); + for (final Material material : GTCEuAPI.materialManager.getRegisteredMaterials()) { if (material.hasProperty(PropertyKey.FLUID)) { FluidProperty property = material.getProperty(PropertyKey.FLUID); - for (FluidStorageKey key : FluidStorageKey.allKeys()) { - Fluid stored = property.getStorage().get(key); - TagKey tag = TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(stored).getPath()); - if (!Platform.isForge() && tag.location().equals(new ResourceLocation("water")) && - !stored.isSame(Fluids.WATER)) - continue; - if (!Platform.isForge() && tag.location().equals(new ResourceLocation("lava")) && - !stored.isSame(Fluids.LAVA)) - continue; - if (f == stored || f.is(tag)) { - return material; - } - } + FluidStorageKey.allKeys().stream() + .map(key -> property.getStorage().get(key)) + .filter(Objects::nonNull) + .map(f -> Pair.of(f, TagUtil.createFluidTag(BuiltInRegistries.FLUID.getKey(f).getPath()))) + .filter(pair -> allFluidTags.contains(pair.getSecond())) + .forEach(pair -> { + allFluidTags.remove(pair.getSecond()); + FLUID_MATERIAL.put(pair.getFirst(), material); + }); } } - return null; - }); + } + return FLUID_MATERIAL.get(fluid); } @Nullable diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java index eb5e58f327..0430d7c61a 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/Material.java @@ -24,13 +24,15 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.Item; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.material.Fluid; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import dev.latvian.mods.rhino.util.HideFromJS; import dev.latvian.mods.rhino.util.RemapPrefixForJS; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; @@ -199,7 +201,7 @@ protected void calculateDecompositionType() { * Retrieves a fluid from the material. * Attempts to retrieve with {@link FluidProperty#getPrimaryKey()}, {@link FluidStorageKeys#LIQUID} and * {@link FluidStorageKeys#GAS}. - * + * * @return the fluid * @see #getFluid(FluidStorageKey) */ @@ -268,7 +270,7 @@ public TagKey getFluidTag() { *
* Attempts to retrieve with {@link FluidProperty#getPrimaryKey()}, {@link FluidStorageKeys#LIQUID} and * {@link FluidStorageKeys#GAS}. - * + * * @return the fluid builder */ public FluidBuilder getFluidBuilder() { @@ -291,7 +293,7 @@ public FluidBuilder getFluidBuilder() { /** * NOTE: only available before the fluids are registered. - * + * * @param key the key for the fluid * @return the fluid corresponding with the key */ @@ -370,7 +372,7 @@ public int getMaterialSecondaryARGB() { /** * Gets a specific color layer in ARGB. - * + * * @param index the index of the layer [0,10). will crash if you pass values > 10. * @return Gets a specific color layer. */ @@ -384,7 +386,7 @@ public int getMaterialRGB() { /** * Gets a specific color layer. - * + * * @param index the index of the layer [0,10). will crash if you pass values > 10. * @return Gets a specific color layer. */ @@ -627,7 +629,7 @@ public Builder liquid(int temp) { /** * Add a plasma for this material. - * + * * @see #fluid(FluidStorageKey, FluidState) */ public Builder plasma() { @@ -649,7 +651,7 @@ public Builder plasma(int temp) { /** * Add a gas for this material. - * + * * @see #fluid(FluidStorageKey, FluidState) */ public Builder gas() { @@ -1050,51 +1052,123 @@ public Builder blastTemp(int temp, BlastProperty.GasTier gasTier, int eutOverrid return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardEffect effect, + // Tons of shortcut functions for adding various hazard effects. + + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardEffect effect, HazardProperty.HazardDamage damage, boolean applyToDerivatives) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, effect, damage, applyToDerivatives)); + properties.setProperty(HAZARD, new HazardProperty(hazardType, effect, damage, applyToDerivatives)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardEffect effect, + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardEffect effect, HazardProperty.HazardDamage damage) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, effect, damage, true)); + properties.setProperty(HAZARD, new HazardProperty(hazardType, effect, damage, true)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardEffect effect, + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardEffect effect, boolean applyToDerivatives) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, effect, null, applyToDerivatives)); + properties.setProperty(HAZARD, new HazardProperty(hazardType, effect, null, applyToDerivatives)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardDamage damage, + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardDamage damage, boolean applyToDerivatives) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, null, damage, applyToDerivatives)); + properties.setProperty(HAZARD, new HazardProperty(hazardType, List.of(), damage, applyToDerivatives)); + return this; + } + + @HideFromJS + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardEffect effect) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, effect, null, true)); + return this; + } + + public Builder hazard(HazardProperty.HazardType hazardType, HazardProperty.HazardDamage damage) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, List.of(), damage, true)); + return this; + } + + public Builder hazard(HazardProperty.HazardType hazardType, List effects) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, effects, null, true)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardEffect effect) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, effect, null, true)); + public Builder hazard(HazardProperty.HazardType hazardType, List effects, + boolean applyToDerivatives) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, effects, null, applyToDerivatives)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, HazardProperty.HazardDamage damage) { - properties.setProperty(HAZARD, new HazardProperty(poisonType, null, damage, true)); + public Builder hazard(HazardProperty.HazardType hazardType, int secondsToMax, Attribute attribute, + AttributeModifier maxModifier) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, + new HazardProperty.HazardEffect(secondsToMax, Map.of(attribute, maxModifier)), null, true)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType, boolean applyToDerivatives) { + public Builder hazard(HazardProperty.HazardType hazardType, int secondsToMax, Attribute attribute, + AttributeModifier maxModifier, boolean applyToDerivatives) { properties.setProperty(HAZARD, - new HazardProperty(poisonType, new HazardProperty.HazardEffect(200, MobEffects.POISON), - new HazardProperty.HazardDamage(2, 1), applyToDerivatives)); + new HazardProperty(hazardType, + new HazardProperty.HazardEffect(secondsToMax, Map.of(attribute, maxModifier)), null, + applyToDerivatives)); return this; } - public Builder hazard(HazardProperty.HazardType poisonType) { + public Builder hazard(HazardProperty.HazardType hazardType, int secondsToMax, Attribute attribute, + AttributeModifier maxModifier, int maxAirModifier) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, + new HazardProperty.HazardEffect(secondsToMax, Map.of(attribute, maxModifier), maxAirModifier), null, + true)); + return this; + } + + public Builder hazard(HazardProperty.HazardType hazardType, int secondsToMax, Attribute attribute, + AttributeModifier maxModifier, int maxAirModifier, boolean applyToDerivatives) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, + new HazardProperty.HazardEffect(secondsToMax, Map.of(attribute, maxModifier), maxAirModifier), null, + applyToDerivatives)); + return this; + } + + public Builder hazard(HazardProperty.HazardType hazardType, boolean applyToDerivatives) { + properties.setProperty(HAZARD, new HazardProperty(hazardType, HazardProperty.poisonEffect(1000, 2000, 3), + null, applyToDerivatives)); + return this; + } + + public Builder hazard(HazardProperty.HazardType hazardType) { properties.setProperty(HAZARD, - new HazardProperty(poisonType, new HazardProperty.HazardEffect(200, MobEffects.POISON), - new HazardProperty.HazardDamage(2, 1), true)); + new HazardProperty(hazardType, HazardProperty.poisonEffect(1000, 2000, 3), null, true)); + return this; + } + + public Builder radioactiveHazard(float multiplier) { + int effectAmplifier = (int) (multiplier - 1); + properties.setProperty(HAZARD, new HazardProperty( + HazardProperty.HazardType.RADIOACTIVE, + List.of( + HazardProperty.slownessEffect(-1, (int) (2000 / multiplier), effectAmplifier), + HazardProperty.weaknessEffect(-1, (int) (2000 / multiplier), effectAmplifier), + HazardProperty.miningFautigueEffect(-1, (int) (3000 / multiplier), effectAmplifier), + HazardProperty.maxAirLoweringEffect(1000, (int) (4000 / multiplier), + (int) (100 / multiplier)), + HazardProperty.maxHealthLoweringEffect(4000, (int) (6000 / multiplier), 10), + HazardProperty.witherEffect(10000, (int) (24000 / multiplier), effectAmplifier)), + null, + true)); + return this; + } + + public Builder irritantHazard(boolean applyToDerivatives) { + properties.setProperty(HAZARD, new HazardProperty( + HazardProperty.HazardType.CONTACT_POISON, + List.of( + HazardProperty.slownessEffect(200, 200, 0), + HazardProperty.miningFautigueEffect(200, 300, 0)), + null, + applyToDerivatives)); return this; } @@ -1215,20 +1289,26 @@ public Builder addDefaultEnchant(Enchantment enchant, int level) { return this; } + @HideFromJS public Material buildAndRegister() { materialInfo.componentList = composition.isEmpty() && this.compositionSupplier != null ? ImmutableList.copyOf(compositionSupplier.stream().map(MaterialStackWrapper::toMatStack) .toArray(MaterialStack[]::new)) : ImmutableList.copyOf(composition); - for (MaterialStack materialStack : materialInfo.componentList) - if (materialStack.material().getProperties().hasProperty(HAZARD) && - materialStack.material().getProperties().getProperty(HAZARD).isApplyToDerivatives() && - !properties.hasProperty(HAZARD)) - properties.setProperty(HAZARD, materialStack.material().getProperties().getProperty(HAZARD)); - + if (!properties.hasProperty(HAZARD)) { + for (MaterialStack materialStack : materialInfo.componentList) { + Material material = materialStack.material(); + if (material.hasProperty(HAZARD) && material.getProperty(HAZARD).isApplyToDerivatives()) { + properties.setProperty(HAZARD, material.getProperty(HAZARD)); + break; + } + } + } if (properties.hasProperty(HAZARD) && - properties.getProperty(HAZARD).getHazardType() == HazardProperty.HazardType.NONE) + properties.getProperty(HAZARD).getHazardType() == HazardProperty.HazardType.NONE) { properties.removeProperty(HAZARD); + } + var mat = new Material(materialInfo, properties, flags); materialInfo.verifyInfo(properties, averageRGB); mat.registerMaterial(); @@ -1236,6 +1316,7 @@ public Material buildAndRegister() { } @Override + @HideFromJS public Material register() { return value = buildAndRegister(); } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java index 7d28032f71..5ca467d6b0 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/properties/HazardProperty.java @@ -2,21 +2,29 @@ import com.gregtechceu.gtceu.api.data.tag.TagPrefix; import com.gregtechceu.gtceu.api.item.armor.ArmorComponentItem; +import com.gregtechceu.gtceu.common.data.GTMobEffects; import com.gregtechceu.gtceu.data.recipe.CustomTags; -import net.minecraft.world.effect.MobEffect; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ItemStack; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import lombok.Getter; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; +import java.util.*; +import java.util.function.Supplier; /** * @author h3tR @@ -25,33 +33,33 @@ */ public class HazardProperty implements IMaterialProperty { + public static final UUID HAZARD_MAX_HEALTH_UUID = UUID.fromString("607aa6d9-a7e4-4919-9962-f007104c4be8"); + public static final String HAZARD_MAX_HEALTH_KEY = "gtceu.hazard.max_health"; + @Getter @Nullable private final HazardProperty.HazardDamage damage; - @Getter - @Nullable - private final HazardProperty.HazardEffect effect; - + private final List effects = new ArrayList<>(); @Getter private final HazardType hazardType; - @Getter private final boolean applyToDerivatives; public HazardProperty(HazardType hazardType, @Nullable HazardProperty.HazardEffect effect, @Nullable HazardProperty.HazardDamage damage, boolean applyToDerivatives) { - this.damage = damage; this.hazardType = hazardType; + this.effects.add(effect); + this.damage = damage; this.applyToDerivatives = applyToDerivatives; - this.effect = effect; } - /** - * Default property constructor. - */ - public HazardProperty() { - this(HazardType.CONTACT_POISON, null, null, false); + public HazardProperty(HazardType hazardType, List effects, + @Nullable HazardProperty.HazardDamage damage, boolean applyToDerivatives) { + this.hazardType = hazardType; + this.effects.addAll(effects); + this.damage = damage; + this.applyToDerivatives = applyToDerivatives; } @Override @@ -59,22 +67,25 @@ public void verifyProperty(MaterialProperties properties) {} public enum HazardType { - INHALATION_POISON(ProtectionType.MASK, TagPrefix.dust, TagPrefix.dustImpure, TagPrefix.dustSmall, - TagPrefix.dustPure, TagPrefix.dustTiny, TagPrefix.rawOre, TagPrefix.rawOreBlock, TagPrefix.crushed, - TagPrefix.crushedRefined, TagPrefix.crushedPurified), + INHALATION_POISON(ProtectionType.MASK, TagPrefix.dust, TagPrefix.dustSmall, TagPrefix.dustTiny, + TagPrefix.dustPure, TagPrefix.dustImpure), CONTACT_POISON(ProtectionType.FULL), RADIOACTIVE(ProtectionType.FULL), CORROSIVE(ProtectionType.HANDS, TagPrefix.dust, TagPrefix.dustSmall, TagPrefix.dustTiny), NONE(ProtectionType.FULL); - private final List affectedTagPrefixes = new ArrayList<>(); + public static final HazardType[] ALL = { INHALATION_POISON, CONTACT_POISON, RADIOACTIVE, CORROSIVE }; + private final Set affectedTagPrefixes = new HashSet<>(); @Getter private final ProtectionType protectionType; HazardType(ProtectionType protectionType, TagPrefix... tagPrefixes) { this.protectionType = protectionType; affectedTagPrefixes.addAll(Arrays.asList(tagPrefixes)); + if (tagPrefixes.length > 0) + affectedTagPrefixes.add(null); // add a null for fluid, because they don't have a prefix but still need + // to always be harmful. } public boolean isAffected(TagPrefix prefix) { @@ -87,17 +98,17 @@ public enum ProtectionType { MASK(ArmorItem.Type.HELMET), HANDS(ArmorItem.Type.CHESTPLATE), - FULL(ArmorItem.Type.BOOTS, ArmorItem.Type.HELMET, ArmorItem.Type.CHESTPLATE, ArmorItem.Type.LEGGINGS); - private final List equipmentTypes; + @Getter + private final Set equipmentTypes; ProtectionType(ArmorItem.Type... equipmentTypes) { - this.equipmentTypes = List.of(equipmentTypes); + this.equipmentTypes = Set.of(equipmentTypes); } public boolean isProtected(LivingEntity livingEntity) { - List correctArmorItems = new ArrayList<>(); + Set correctArmorItems = new HashSet<>(); for (ArmorItem.Type equipmentType : equipmentTypes) { ItemStack armor = livingEntity.getItemBySlot(equipmentType.getSlot()); if (!armor.isEmpty() && ((armor.getItem() instanceof ArmorComponentItem armorItem && @@ -106,20 +117,176 @@ public boolean isProtected(LivingEntity livingEntity) { correctArmorItems.add(equipmentType); } } - return new HashSet<>(correctArmorItems).containsAll(equipmentTypes); + return correctArmorItems.containsAll(equipmentTypes); } } + public static HazardProperty.HazardEffect maxHealthLoweringEffect(int secondsToMax, int startTime, int modifier) { + return new HazardProperty.HazardEffect(secondsToMax, startTime, + Map.of(Attributes.MAX_HEALTH, new AttributeModifier(HazardProperty.HAZARD_MAX_HEALTH_UUID, + HazardProperty.HAZARD_MAX_HEALTH_KEY, -modifier, AttributeModifier.Operation.ADDITION))); + } + + public static HazardProperty.HazardEffect maxAirLoweringEffect(int secondsToMax, int startTime, + int newMaxAirSupply) { + return new HazardProperty.HazardEffect(secondsToMax, startTime, newMaxAirSupply); + } + + public static HazardProperty.HazardEffect witherEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(MobEffects.WITHER, 1, amplifier)); + } + + public static HazardProperty.HazardEffect slownessEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 1, amplifier)); + } + + public static HazardProperty.HazardEffect miningFautigueEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 1, amplifier)); + } + + public static HazardProperty.HazardEffect poisonEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(GTMobEffects.WEAK_POISON.get(), 1, amplifier)); + } + + public static HazardProperty.HazardEffect weaknessEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(MobEffects.WEAKNESS, 1, amplifier)); + } + + public static HazardProperty.HazardEffect blindnessEffect(int duration, int startTime, int amplifier) { + return new HazardProperty.HazardEffect(duration, startTime, + () -> new MobEffectInstance(MobEffects.BLINDNESS, 1, amplifier)); + } + /** - * @param delay damage is applied every X seconds + * @param damage amount of damage applied every {@code delay} seconds. + * @param delay damage is applied every {@code delay} seconds */ public record HazardDamage(int damage, int delay) {} - public record HazardEffect(int duration, MobEffect... effects) { + /** + * A group of effects applied by a hazard. + * + * @param duration if this is a potion effect, the time (in ticks) the effect has. else it's the ramp-up + * time (in ticks) for the attribute modifiers. + * @param modifierStartTime the time (in seconds) before the modifier is applied at all. + * @param effects the mob effects, if any. + * @param modifiers the attribute modifiers, if any. + */ + public record HazardEffect(int duration, int modifierStartTime, List> effects, + Map modifiers, int newMaxAirSupply) { + + @SafeVarargs + public HazardEffect(int duration, Supplier... effects) { + this(duration, 0, Arrays.stream(effects).toList(), Object2ObjectMaps.emptyMap(), -1); + } + + @SafeVarargs + public HazardEffect(int duration, int modifierStartTime, Supplier... effects) { + this(duration, modifierStartTime, Arrays.stream(effects).toList(), Object2ObjectMaps.emptyMap(), -1); + } + + public HazardEffect(int secondsToMax, Map modifiers) { + this(secondsToMax, 0, List.of(), modifiers, -1); + } + + public HazardEffect(int secondsToMax, int modifierStartTime, Map modifiers) { + this(secondsToMax, modifierStartTime, List.of(), modifiers, -1); + } + + public HazardEffect(int secondsToMax, Map modifiers, int maxAirModifier) { + this(secondsToMax, 0, List.of(), modifiers, maxAirModifier); + } + + public HazardEffect(int secondsToMax, int maxAirModifier) { + this(secondsToMax, 0, List.of(), Object2ObjectMaps.emptyMap(), maxAirModifier); + } + + public HazardEffect(int secondsToMax, int modifierStartTime, int maxAirModifier) { + this(secondsToMax, modifierStartTime, List.of(), Object2ObjectMaps.emptyMap(), maxAirModifier); + } + + public List getEffectInstancesAtTime(int timeFromStart) { + if (this.effects.isEmpty()) { + return List.of(); + } + List effectInstances = new ArrayList<>(); + for (Supplier effectSupplier : effects) { + MobEffectInstance effect = effectSupplier.get(); + // the effects get stronger the longer you hold the item. + int effectDuration = duration == -1 ? -1 : effect.getDuration() * duration * timeFromStart / 500; + int effectAmplifier = effect.getAmplifier() * timeFromStart / 1000; + effectInstances.add(new MobEffectInstance(effect.getEffect(), effectDuration, effectAmplifier)); + } + return effectInstances; + } + + public Map getModifiersAtTime(int timeFromStart) { + if (this.modifiers.isEmpty()) { + return Object2ObjectMaps.emptyMap(); + } + Map modifierMap = new HashMap<>(); + for (var entry : this.modifiers.entrySet()) { + AttributeModifier modifier = entry.getValue(); + double amount = modifier.getAmount() * (double) timeFromStart / Math.max(duration, 1); + modifierMap.put(entry.getKey(), + new AttributeModifier(modifier.getId(), modifier.getName(), amount, modifier.getOperation())); + } + return modifierMap; + } + + public int getNewMaxAirSupplyAtTime(int timeFromStart) { + if (newMaxAirSupply == -1) { + return -1; + } + return newMaxAirSupply / Math.max(Math.round((float) timeFromStart / Math.max(duration, 1)), 1); + } + + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putInt("duration", duration); + tag.putInt("modifier_start_time", modifierStartTime); + + ListTag effectsTag = new ListTag(); + for (Supplier effect : effects) { + effectsTag.add(effect.get().save(new CompoundTag())); + } + tag.put("effects", effectsTag); + CompoundTag attributesTag = new CompoundTag(); + for (Map.Entry modifier : modifiers.entrySet()) { + attributesTag.put(BuiltInRegistries.ATTRIBUTE.getKey(modifier.getKey()).toString(), + modifier.getValue().save()); + } + tag.put("modifiers", attributesTag); + tag.putInt("max_air_supply", newMaxAirSupply); + + return tag; + } + + public static HazardEffect deserializeNBT(CompoundTag tag) { + int duration = tag.getInt("duration"); + int modifierStartTime = tag.getInt("modifier_start_time"); + + List> effects = new ArrayList<>(); + for (Tag effect : tag.getList("effects", Tag.TAG_COMPOUND)) { + if (!(effect instanceof CompoundTag compoundTag)) { + continue; + } + effects.add(() -> MobEffectInstance.load(compoundTag)); + } + Map modifiers = new HashMap<>(); + CompoundTag attributesTag = tag.getCompound("modifiers"); + for (String key : attributesTag.getAllKeys()) { + modifiers.put(BuiltInRegistries.ATTRIBUTE.get(new ResourceLocation(key)), + AttributeModifier.load(attributesTag.getCompound(key))); + } + int maxAirModifier = tag.getInt("max_air_supply"); - public void apply(LivingEntity entity) { - for (MobEffect effect : effects) - entity.addEffect(new MobEffectInstance(effect, duration)); + return new HazardEffect(duration, modifierStartTime, effects, modifiers, maxAirModifier); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/stack/UnificationEntry.java b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/stack/UnificationEntry.java index 3bf6eb3a83..4aadc9675b 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/stack/UnificationEntry.java +++ b/src/main/java/com/gregtechceu/gtceu/api/data/chemical/material/stack/UnificationEntry.java @@ -36,14 +36,14 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = tagPrefix.hashCode(); + int result = (tagPrefix != null ? tagPrefix.hashCode() : 0); result = 31 * result + (material != null ? material.hashCode() : 0); return result; } @Override public String toString() { - return tagPrefix.name + (material != null ? material.toCamelCaseString() : ""); + return (tagPrefix != null ? tagPrefix.name : "") + (material != null ? material.toCamelCaseString() : ""); } public static final UnificationEntry EmptyMapMarkerEntry = new UnificationEntry(null) { diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/TagPrefixItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/TagPrefixItem.java index 97227462de..509c25185c 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/TagPrefixItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/TagPrefixItem.java @@ -32,8 +32,6 @@ import javax.annotation.ParametersAreNonnullByDefault; -import static com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey.HAZARD; - /** * @author KilaBash * @date 2023/2/14 @@ -107,13 +105,8 @@ public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotI super.inventoryTick(stack, level, entity, slotId, isSelected); if (entity instanceof LivingEntity livingEntity) { if (livingEntity.tickCount % 20 == 0) { - - if (tagPrefix != TagPrefix.ingotHot || !material.hasProperty(PropertyKey.BLAST)) { // ignore hazards for - // hot ingots - GTUtil.applyHazardEffects(material, livingEntity, - () -> material.getProperty(HAZARD).getHazardType().isAffected(tagPrefix)); + if (tagPrefix != TagPrefix.ingotHot || !material.hasProperty(PropertyKey.BLAST)) return; - } float heatDamage = ((material.getBlastTemperature() - 1750) / 1000.0F) + 2; ItemStack armor = livingEntity.getItemBySlot(EquipmentSlot.CHEST); diff --git a/src/main/java/com/gregtechceu/gtceu/api/item/forge/GTBucketItem.java b/src/main/java/com/gregtechceu/gtceu/api/item/forge/GTBucketItem.java index 43185bcf8f..4e0641aab9 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/item/forge/GTBucketItem.java +++ b/src/main/java/com/gregtechceu/gtceu/api/item/forge/GTBucketItem.java @@ -15,8 +15,6 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.FluidTags; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; @@ -30,11 +28,13 @@ import net.minecraft.world.level.material.Fluid; import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -105,16 +105,9 @@ public int getBurnTime(ItemStack itemStack, @Nullable RecipeType recipeType) } @Override - public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) { - super.inventoryTick(stack, level, entity, slotId, isSelected); - if (entity instanceof LivingEntity livingEntity && livingEntity.tickCount % 20 == 0) - GTUtil.applyHazardEffects(material, livingEntity, () -> true); - } - - @Override - public boolean emptyContents(@org.jetbrains.annotations.Nullable Player pPlayer, Level pLevel, BlockPos pPos, - @org.jetbrains.annotations.Nullable BlockHitResult pResult, - @org.jetbrains.annotations.Nullable ItemStack container) { + public boolean emptyContents(@Nullable Player pPlayer, Level pLevel, BlockPos pPos, + @Nullable BlockHitResult pResult, + @Nullable ItemStack container) { if (!(this.getFluid() instanceof FlowingFluid)) return false; BlockState blockstate = pLevel.getBlockState(pPos); @@ -122,8 +115,8 @@ public boolean emptyContents(@org.jetbrains.annotations.Nullable Player pPlayer, boolean flag = blockstate.canBeReplaced(this.getFluid()); boolean flag1 = blockstate.isAir() || flag || block instanceof LiquidBlockContainer && ((LiquidBlockContainer) block).canPlaceLiquid(pLevel, pPos, blockstate, this.getFluid()); - java.util.Optional containedFluidStack = java.util.Optional - .ofNullable(container).flatMap(net.minecraftforge.fluids.FluidUtil::getFluidContained); + Optional containedFluidStack = Optional + .ofNullable(container).flatMap(FluidUtil::getFluidContained); if (!flag1) { return pResult != null && this.emptyContents(pPlayer, pLevel, pResult.getBlockPos().relative(pResult.getDirection()), null, container); diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java index dc11c98a1a..f0764ee8b9 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java +++ b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java @@ -87,6 +87,8 @@ public CommonProxy() { GTRegistries.init(eventBus); GTFeatures.init(eventBus); + GTCommandArguments.init(eventBus); + GTMobEffects.init(eventBus); // init common features GTRegistries.GLOBAL_LOOT_MODIFIES.register("tool", () -> ToolLootModifier.CODEC); } diff --git a/src/main/java/com/gregtechceu/gtceu/common/ServerCommands.java b/src/main/java/com/gregtechceu/gtceu/common/ServerCommands.java deleted file mode 100644 index dd5eaed311..0000000000 --- a/src/main/java/com/gregtechceu/gtceu/common/ServerCommands.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gregtechceu.gtceu.common; - -import com.gregtechceu.gtceu.api.gui.factory.GTUIEditorFactory; -import com.gregtechceu.gtceu.api.recipe.GTRecipe; - -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.Commands; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.crafting.Recipe; - -import com.mojang.brigadier.builder.LiteralArgumentBuilder; - -import java.util.List; - -/** - * @author KilaBash - * @date 2023/2/9 - * @implNote ServerCommands - */ -public class ServerCommands { - - public static List> createServerCommands() { - return List.of( - Commands.literal("gtceu") - .then(Commands.literal("ui_editor") - .executes(context -> { - GTUIEditorFactory.INSTANCE.openUI(GTUIEditorFactory.INSTANCE, - context.getSource().getPlayerOrException()); - return 1; - })) - .then(Commands.literal("check_recipes_valid") - .requires(cs -> cs.hasPermission(0)) - .executes(context -> { - for (Recipe recipe : context.getSource().getServer().getRecipeManager() - .getRecipes()) { - if (recipe instanceof GTRecipe gtRecipe && !gtRecipe.checkRecipeValid()) { - context.getSource().sendSuccess( - () -> Component - .literal("recipe %s is invalid".formatted(gtRecipe.id)), - false); - } - } - return 1; - }))); - } -} diff --git a/src/main/java/com/gregtechceu/gtceu/common/capability/HazardEffectTracker.java b/src/main/java/com/gregtechceu/gtceu/common/capability/HazardEffectTracker.java new file mode 100644 index 0000000000..c1de1975e8 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/capability/HazardEffectTracker.java @@ -0,0 +1,224 @@ +package com.gregtechceu.gtceu.common.capability; + +import com.gregtechceu.gtceu.api.GTCEuAPI; +import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.AttributeModifier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ArmorItem; +import net.minecraftforge.common.util.INBTSerializable; + +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class HazardEffectTracker implements IHazardEffectTracker, INBTSerializable { + + @Getter + @Setter + private int maxAirSupply = -1; + + @Getter + private final Object2IntMap entryToAmount = new Object2IntOpenHashMap<>(); + @Getter + private final Map> typesToEffects = new EnumMap<>( + HazardProperty.HazardType.class); + @Getter + private final Object2IntMap currentHazardEffects = new Object2IntOpenHashMap<>(); + + private final Player player; + + public HazardEffectTracker(Player player) { + this.player = player; + } + + @Override + public void tick() { + Set protectedFrom = new HashSet<>(); + Object2BooleanMap isAffected = new Object2BooleanOpenHashMap<>(); + for (UnificationEntry entry : entryToAmount.keySet()) { + HazardProperty property = entry.material.getProperty(PropertyKey.HAZARD); + if (property.getHazardType().getProtectionType().isProtected(player)) { + // entity has proper safety equipment, so damage it per material every 5 seconds. + if (player.level().getGameTime() % 100 == 0) { + for (ArmorItem.Type type : property.getHazardType().getProtectionType().getEquipmentTypes()) { + player.getItemBySlot(type.getSlot()).hurtAndBreak(1, player, + p -> p.broadcastBreakEvent(type.getSlot())); + } + } + protectedFrom.addAll(property.getEffects()); + } + for (var effect : property.getEffects()) { + isAffected.put(effect, property.getHazardType().isAffected(entry.tagPrefix)); + } + } + if (protectedFrom.containsAll(currentHazardEffects.keySet())) { + return; + } + + int totalMaxAirSupply = 0; + int maxAirSupplySetterAmount = 0; + + for (var entry : currentHazardEffects.object2IntEntrySet()) { + HazardProperty.HazardEffect effect = entry.getKey(); + int time = entry.getIntValue(); + + if (protectedFrom.contains(effect) || !isAffected.getBoolean(effect)) { + continue; + } + + if (time < effect.modifierStartTime()) { + // if the current applied time is less than the minimum for effects to be applied, return early. + entry.setValue(time + 1); + continue; + } + + for (MobEffectInstance mobEffect : effect.getEffectInstancesAtTime(time)) { + player.addEffect(mobEffect); + } + var attributeModifiers = effect.getModifiersAtTime(time); + for (var modifierEntry : attributeModifiers.entrySet()) { + AttributeModifier modifier = modifierEntry.getValue(); + AttributeInstance attributeInstance = player.getAttribute(modifierEntry.getKey()); + if (attributeInstance == null) { + continue; + } + + if (attributeInstance.hasModifier(modifier)) { + attributeInstance.removeModifier(modifier); + } + attributeInstance.addPermanentModifier(modifier); + } + int maxAirSupply = effect.getNewMaxAirSupplyAtTime(time); + if (maxAirSupply >= 0) { + totalMaxAirSupply += maxAirSupply; + maxAirSupplySetterAmount++; + } + + entry.setValue(time + 1); + } + + if (maxAirSupplySetterAmount > 0) { + this.setMaxAirSupply(totalMaxAirSupply / maxAirSupplySetterAmount); + } + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + ListTag amountsTag = new ListTag(); + for (var amount : entryToAmount.object2IntEntrySet()) { + CompoundTag amountTag = new CompoundTag(); + if (amount.getKey().tagPrefix != null) { + amountTag.putString("prefix", amount.getKey().tagPrefix.name); + } + amountTag.putString("material", amount.getKey().material.toString()); + amountTag.putInt("amount", amount.getIntValue()); + amountsTag.add(amountTag); + } + tag.put("amounts", amountsTag); + + ListTag effectsTag = new ListTag(); + for (var effect : currentHazardEffects.object2IntEntrySet()) { + CompoundTag effectTag = new CompoundTag(); + effectTag.put("effect", effect.getKey().serializeNBT()); + HazardProperty.HazardType type = getType(effect.getKey()); + if (type != null) { + effectTag.putByte("type", (byte) type.ordinal()); + } + effectTag.putInt("time", effect.getIntValue()); + effectsTag.add(effectTag); + } + tag.put("effects", effectsTag); + return tag; + } + + @Override + public void deserializeNBT(CompoundTag arg) { + ListTag amounts = arg.getList("amounts", Tag.TAG_COMPOUND); + for (Tag tag : amounts) { + if (!(tag instanceof CompoundTag compoundTag)) { + continue; + } + TagPrefix prefix = null; + if (compoundTag.contains("prefix", Tag.TAG_STRING)) { + prefix = TagPrefix.get(compoundTag.getString("prefix")); + } + Material material = GTCEuAPI.materialManager.getMaterial(compoundTag.getString("material")); + int amount = compoundTag.getInt("amount"); + entryToAmount.put(new UnificationEntry(prefix, material), amount); + } + + ListTag effects = arg.getList("effects", Tag.TAG_COMPOUND); + for (Tag tag : effects) { + if (!(tag instanceof CompoundTag compoundTag)) { + continue; + } + HazardProperty.HazardEffect effect = HazardProperty.HazardEffect + .deserializeNBT(compoundTag.getCompound("effect")); + int time = compoundTag.getInt("time"); + currentHazardEffects.put(effect, time); + if (compoundTag.contains("type", Tag.TAG_BYTE)) { + HazardProperty.HazardType type = HazardProperty.HazardType.values()[compoundTag.getByte("type")]; + if (!typesToEffects.containsKey(type)) { + typesToEffects.put(type, new HashSet<>()); + } + typesToEffects.get(type).add(effect); + } + } + } + + @Override + public void removeHazardItem(UnificationEntry entry) { + if (!entryToAmount.containsKey(entry)) { + return; + } + entryToAmount.put(entry, entryToAmount.getOrDefault(entry, 0) - 1); + if (entryToAmount.getInt(entry) <= 0) { + entryToAmount.removeInt(entry); + } + } + + @Override + public void addHazardItem(UnificationEntry entry) { + if (player.isCreative()) { + return; + } + entryToAmount.put(entry, entryToAmount.getOrDefault(entry, 0) + 1); + // noinspection DataFlowIssue property existence is checked before this method is called. + for (HazardProperty.HazardEffect effect : entry.material.getProperty(PropertyKey.HAZARD).getEffects()) { + if (!this.currentHazardEffects.containsKey(effect)) { + this.currentHazardEffects.put(effect, 0); + } + } + } + + @Nullable + public HazardProperty.HazardType getType(HazardProperty.HazardEffect value) { + for (var entry : typesToEffects.entrySet()) { + if (entry.getValue().contains(value)) { + return entry.getKey(); + } + } + return null; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/ServerCommands.java b/src/main/java/com/gregtechceu/gtceu/common/commands/ServerCommands.java new file mode 100644 index 0000000000..41d1668efb --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/commands/ServerCommands.java @@ -0,0 +1,127 @@ +package com.gregtechceu.gtceu.common.commands; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; +import com.gregtechceu.gtceu.api.data.tag.TagPrefix; +import com.gregtechceu.gtceu.api.gui.factory.GTUIEditorFactory; +import com.gregtechceu.gtceu.api.recipe.GTRecipe; +import com.gregtechceu.gtceu.common.commands.arguments.MaterialArgument; + +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.crafting.Recipe; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; + +import java.util.Collection; +import java.util.List; + +/** + * @author KilaBash + * @date 2023/2/9 + * @implNote ServerCommands + */ +public class ServerCommands { + + private static final SimpleCommandExceptionType ERROR_CLEAR_EVERYTHING_FAILED = new SimpleCommandExceptionType( + Component.translatable("commands.effect.clear.everything.failed")); + private static final SimpleCommandExceptionType ERROR_INVALID_MATERIAL = new SimpleCommandExceptionType( + Component.translatable("commands.gtceu.hazard.invalid.material")); + private static final SimpleCommandExceptionType ERROR_GIVE_FAILED = new SimpleCommandExceptionType( + Component.translatable("commands.effect.give.failed")); + + public static List> createServerCommands() { + return List.of( + Commands.literal("gtceu") + .then(Commands.literal("ui_editor") + .executes(context -> { + GTUIEditorFactory.INSTANCE.openUI(GTUIEditorFactory.INSTANCE, + context.getSource().getPlayerOrException()); + return 1; + })) + .then(Commands.literal("check_recipes_valid") + .requires(cs -> cs.hasPermission(0)) + .executes(context -> { + for (Recipe recipe : context.getSource().getServer().getRecipeManager() + .getRecipes()) { + if (recipe instanceof GTRecipe gtRecipe && !gtRecipe.checkRecipeValid()) { + context.getSource().sendSuccess( + () -> Component + .literal("recipe %s is invalid".formatted(gtRecipe.id)), + false); + } + } + return 1; + })) + .then(Commands.literal("hazard") + .requires(source -> source.hasPermission(2)) + .then(Commands.literal("clear") + .executes(context -> { + ServerPlayer target = context.getSource().getPlayerOrException(); + IHazardEffectTracker tracker = GTCapabilityHelper + .getHazardEffectTracker(target); + if (tracker == null) { + throw EntityArgument.NO_PLAYERS_FOUND.create(); + } + int count = tracker.getCurrentHazardEffects().keySet().size(); + tracker.getCurrentHazardEffects().clear(); + return count; + }) + .then(Commands.argument("targets", EntityArgument.players()) + .executes(context -> { + Collection targets = EntityArgument + .getPlayers(context, "targets"); + int count = 0; + for (ServerPlayer target : targets) { + IHazardEffectTracker tracker = GTCapabilityHelper + .getHazardEffectTracker(target); + if (tracker == null) { + continue; + } + count += tracker.getCurrentHazardEffects().keySet().size(); + tracker.getCurrentHazardEffects().clear(); + } + if (count == 0) { + throw ERROR_CLEAR_EVERYTHING_FAILED.create(); + } + return count; + }))) + .then(Commands.literal("apply") + .then(Commands.argument("targets", EntityArgument.players()) + .then(Commands.argument("material", MaterialArgument.material()) + .executes(context -> { + Material material = MaterialArgument.getMaterial(context, + "material"); + Collection players = EntityArgument + .getPlayers(context, "targets"); + int success = 0; + HazardProperty property = material + .getProperty(PropertyKey.HAZARD); + if (property == null) { + throw ERROR_INVALID_MATERIAL.create(); + } + for (ServerPlayer player : players) { + IHazardEffectTracker tracker = GTCapabilityHelper + .getHazardEffectTracker(player); + if (tracker == null) { + continue; + } + tracker.addHazardItem( + new UnificationEntry(TagPrefix.dust, material)); + success++; + } + if (success == 0) { + throw ERROR_GIVE_FAILED.create(); + } + return success; + })))))); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialArgument.java b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialArgument.java new file mode 100644 index 0000000000..b752292f67 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialArgument.java @@ -0,0 +1,45 @@ +package com.gregtechceu.gtceu.common.commands.arguments; + +import com.gregtechceu.gtceu.api.GTCEuAPI; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class MaterialArgument implements ArgumentType { + + private static final Collection EXAMPLES = Arrays.asList("aluminium", "gtceu:steel"); + + public MaterialArgument() {} + + public static MaterialArgument material() { + return new MaterialArgument(); + } + + @Override + public Material parse(StringReader reader) throws CommandSyntaxException { + return MaterialParser.parseForMaterial(GTCEuAPI.materialManager, reader); + } + + public static Material getMaterial(CommandContext context, String name) { + return context.getArgument(name, Material.class); + } + + @Override + public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return MaterialParser.fillSuggestions(GTCEuAPI.materialManager, builder); + } + + @Override + public Collection getExamples() { + return EXAMPLES; + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java new file mode 100644 index 0000000000..cd2b4b55e9 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java @@ -0,0 +1,100 @@ +package com.gregtechceu.gtceu.common.commands.arguments; + +import com.gregtechceu.gtceu.api.data.chemical.material.IMaterialRegistryManager; +import com.gregtechceu.gtceu.api.data.chemical.material.Material; + +import net.minecraft.commands.SharedSuggestionProvider; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +public class MaterialParser { + + private static final SimpleCommandExceptionType ERROR_NO_TAGS_ALLOWED = new SimpleCommandExceptionType( + Component.translatable("argument.item.tag.disallowed")); + private static final DynamicCommandExceptionType ERROR_UNKNOWN_ITEM = new DynamicCommandExceptionType( + id -> Component.translatable("argument.item.id.invalid", id)); + private static final DynamicCommandExceptionType ERROR_UNKNOWN_TAG = new DynamicCommandExceptionType( + tag -> Component.translatable("arguments.item.tag.unknown", tag)); + private static final char SYNTAX_START_NBT = '{'; + private static final char SYNTAX_TAG = '#'; + private static final Function> SUGGEST_NOTHING = SuggestionsBuilder::buildFuture; + private final IMaterialRegistryManager materials; + private final StringReader reader; + private Material result; + /** + * Builder to be used when creating a list of suggestions + */ + private Function> suggestions = SUGGEST_NOTHING; + + private MaterialParser(IMaterialRegistryManager materials, StringReader reader) { + this.materials = materials; + this.reader = reader; + } + + public static Material parseForMaterial(IMaterialRegistryManager registry, + StringReader reader) throws CommandSyntaxException { + int i = reader.getCursor(); + + try { + MaterialParser materialParser = new MaterialParser(registry, reader); + materialParser.parse(); + return materialParser.result; + } catch (CommandSyntaxException var5) { + reader.setCursor(i); + throw var5; + } + } + + public static CompletableFuture fillSuggestions(IMaterialRegistryManager lookup, + SuggestionsBuilder builder) { + StringReader stringReader = new StringReader(builder.getInput()); + stringReader.setCursor(builder.getStart()); + MaterialParser materialParser = new MaterialParser(lookup, stringReader); + + try { + materialParser.parse(); + } catch (CommandSyntaxException var6) {} + + return (CompletableFuture) materialParser.suggestions + .apply(builder.createOffset(stringReader.getCursor())); + } + + private void readMaterial() throws CommandSyntaxException { + int i = this.reader.getCursor(); + ResourceLocation resourceLocation = ResourceLocation.read(this.reader); + Material material = this.materials.getRegistry(resourceLocation.getNamespace()).get(resourceLocation.getPath()); + this.result = Optional.ofNullable(material).orElseThrow(() -> { + this.reader.setCursor(i); + return ERROR_UNKNOWN_ITEM.createWithContext(this.reader, resourceLocation); + }); + } + + private void parse() throws CommandSyntaxException { + this.suggestions = this::suggestMaterial; + this.readMaterial(); + } + + private CompletableFuture suggestOpenNbt(SuggestionsBuilder builder) { + if (builder.getRemaining().isEmpty()) { + builder.suggest(String.valueOf('{')); + } + + return builder.buildFuture(); + } + + private CompletableFuture suggestMaterial(SuggestionsBuilder builder) { + return SharedSuggestionProvider.suggestResource( + this.materials.getRegisteredMaterials().stream().map(Material::getResourceLocation), builder); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java index 4990889b2c..115f9d5a58 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTBlocks.java @@ -515,6 +515,9 @@ private static void registerOpticalPipeBlock(int index) { GTCEu.id("block/casings/solid/machine_casing_palladium_substation")); public static final BlockEntry CASING_TEMPERED_GLASS = createGlassCasingBlock("tempered_glass", GTCEu.id("block/casings/transparent/tempered_glass"), () -> RenderType::translucent); + public static final BlockEntry CASING_STAINLESS_EVAPORATION = createCasingBlock( + "stainless_evaporation_casing", + GTCEu.id("block/casings/solid/machine_casing_stainless_evaporation")); public static final ImmutableMap> MATERIALS_TO_CASINGS; diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTCommandArguments.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTCommandArguments.java new file mode 100644 index 0000000000..f330235d72 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTCommandArguments.java @@ -0,0 +1,27 @@ +package com.gregtechceu.gtceu.common.data; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.common.commands.arguments.MaterialArgument; + +import net.minecraft.commands.synchronization.ArgumentTypeInfo; +import net.minecraft.commands.synchronization.ArgumentTypeInfos; +import net.minecraft.commands.synchronization.SingletonArgumentInfo; +import net.minecraft.core.registries.Registries; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +public class GTCommandArguments { + + private static final DeferredRegister> COMMAND_ARGUMENT_TYPES = DeferredRegister + .create(Registries.COMMAND_ARGUMENT_TYPE, GTCEu.MOD_ID); + + private static final RegistryObject> MATERIAL_ARGUMENT_TYPE = COMMAND_ARGUMENT_TYPES + .register( + "material", () -> ArgumentTypeInfos.registerByClass(MaterialArgument.class, + SingletonArgumentInfo.contextFree(MaterialArgument::material))); + + public static void init(IEventBus modBus) { + COMMAND_ARGUMENT_TYPES.register(modBus); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java index 03e1b4d1e5..63d144c447 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java @@ -11,6 +11,7 @@ import com.gregtechceu.gtceu.api.data.chemical.material.MarkerMaterial; import com.gregtechceu.gtceu.api.data.chemical.material.MarkerMaterials; import com.gregtechceu.gtceu.api.data.chemical.material.Material; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty; import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; import com.gregtechceu.gtceu.api.data.chemical.material.registry.MaterialRegistry; import com.gregtechceu.gtceu.api.data.chemical.material.stack.ItemMaterialInfo; @@ -275,7 +276,7 @@ public static void generateTools() { .onRegister(materialInfo(new ItemMaterialInfo(new MaterialStack(GTMaterials.Steel, GTValues.M * 4)))) .register(); - public static final ItemEntry[] SHAPE_MOLDS = new ItemEntry[13]; + public static final ItemEntry[] SHAPE_MOLDS = new ItemEntry[14]; public static final ItemEntry SHAPE_MOLD_PLATE; public static final ItemEntry SHAPE_MOLD_GEAR; public static final ItemEntry SHAPE_MOLD_CREDIT; @@ -289,6 +290,7 @@ public static void generateTools() { public static final ItemEntry SHAPE_MOLD_NAME; public static final ItemEntry SHAPE_MOLD_GEAR_SMALL; public static final ItemEntry SHAPE_MOLD_ROTOR; + public static final ItemEntry SHAPE_MOLD_PILL; static { SHAPE_MOLDS[0] = SHAPE_MOLD_PLATE = REGISTRATE.item("plate_casting_mold", Item::new) @@ -343,6 +345,10 @@ public static void generateTools() { .lang("Casting Mold (Rotor)").onRegister(compassNodeExist(GTCompassSections.MISC, "mold")) .onRegister(materialInfo(new ItemMaterialInfo(new MaterialStack(GTMaterials.Steel, GTValues.M * 4)))) .register(); + SHAPE_MOLDS[13] = SHAPE_MOLD_PILL = REGISTRATE.item("pill_casting_mold", Item::new) + .lang("Casting Mold (Pill)").onRegister(compassNodeExist(GTCompassSections.MISC, "mold")) + .onRegister(materialInfo(new ItemMaterialInfo(new MaterialStack(GTMaterials.Steel, GTValues.M * 4)))) + .register(); } public static final ItemEntry[] SHAPE_EXTRUDERS = new ItemEntry[27]; @@ -2228,10 +2234,20 @@ public Component getItemName(ItemStack stack) { .onRegister(attach(ElectricStats.createElectricItem(25600000L, GTValues.IV))) .register(); - public static ItemEntry MASK_FILTER = REGISTRATE.item("mask_filter", ComponentItem::create) + public static ItemEntry MASK_FILTER = REGISTRATE.item("mask_filter", Item::new) .lang("Gas Mask Filter") .properties(p -> p.stacksTo(1)) .register(); + public static ItemEntry PARACETAMOL_PILL = REGISTRATE.item("paracetamol_pill", ComponentItem::create) + .lang("Paracetamol Pill") + .properties(p -> p.food(GTFoods.ANTIDOTE)) + .onRegister(attach(new AntidoteBehavior(100, HazardProperty.HazardType.ALL))) + .register(); + public static ItemEntry RAD_AWAY_PILL = REGISTRATE.item("rad_away_pill", ComponentItem::create) + .lang("RadAway™ Pill") + .properties(p -> p.food(GTFoods.ANTIDOTE)) + .onRegister(attach(new AntidoteBehavior(-1, HazardProperty.HazardType.RADIOACTIVE))) + .register(); public static ItemEntry NANO_SABER; public static ItemEntry PROSPECTOR_LV = REGISTRATE.item("prospector.lv", ComponentItem::create) @@ -2420,30 +2436,51 @@ public Component getItemName(ItemStack stack) { .properties(p -> p.rarity(Rarity.UNCOMMON)) .register(); + public static ItemEntry FACE_MASK = REGISTRATE + .item("face_mask", + (p) -> new ArmorComponentItem(GTArmorMaterials.BAD_PPE_EQUIPMENT, ArmorItem.Type.HELMET, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.HELMET, "bad_hazmat"))) + .lang("Face Mask") + .tag(CustomTags.PPE_ARMOR) + .register(); + public static ItemEntry RUBBER_GLOVES = REGISTRATE + .item("rubber_gloves", + (p) -> new ArmorComponentItem(GTArmorMaterials.BAD_PPE_EQUIPMENT, ArmorItem.Type.HELMET, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.CHESTPLATE, "bad_hazmat"))) + .lang("Rubber Gloves") + .tag(CustomTags.PPE_ARMOR) + .register(); public static ItemEntry HAZMAT_CHESTPLATE = REGISTRATE .item("hazmat_chestpiece", - (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.CHESTPLATE, p) - .setArmorLogic(new HazmatSuit(ArmorItem.Type.CHESTPLATE))) + (p) -> new ArmorComponentItem(GTArmorMaterials.GOOD_PPE_EQUIPMENT, ArmorItem.Type.CHESTPLATE, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.CHESTPLATE, "hazmat"))) .lang("Hazardous Materials Suit Chestpiece") .properties(p -> p.rarity(Rarity.UNCOMMON)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry HAZMAT_LEGGINGS = REGISTRATE - .item("hazmat_leggings", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.LEGGINGS, p) - .setArmorLogic(new HazmatSuit(ArmorItem.Type.LEGGINGS))) + .item("hazmat_leggings", + (p) -> new ArmorComponentItem(GTArmorMaterials.GOOD_PPE_EQUIPMENT, ArmorItem.Type.LEGGINGS, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.LEGGINGS, "hazmat"))) .lang("Hazardous Materials Suit Leggings") .properties(p -> p.rarity(Rarity.UNCOMMON)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry HAZMAT_BOOTS = REGISTRATE - .item("hazmat_boots", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.BOOTS, p) - .setArmorLogic(new HazmatSuit(ArmorItem.Type.BOOTS))) + .item("hazmat_boots", + (p) -> new ArmorComponentItem(GTArmorMaterials.GOOD_PPE_EQUIPMENT, ArmorItem.Type.BOOTS, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.BOOTS, "hazmat"))) .lang("Hazardous Materials Suit Boots") .properties(p -> p.rarity(Rarity.UNCOMMON)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry HAZMAT_HELMET = REGISTRATE - .item("hazmat_headpiece", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.HELMET, p) - .setArmorLogic(new HazmatSuit(ArmorItem.Type.HELMET))) + .item("hazmat_headpiece", + (p) -> new ArmorComponentItem(GTArmorMaterials.GOOD_PPE_EQUIPMENT, ArmorItem.Type.HELMET, p) + .setArmorLogic(new HazmatSuit(ArmorItem.Type.HELMET, "hazmat"))) .lang("Hazardous Materials Suit Headpiece") .properties(p -> p.rarity(Rarity.UNCOMMON)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry QUANTUM_CHESTPLATE = REGISTRATE @@ -2456,6 +2493,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierQuarkTech))) .lang("QuarkTech™ Suite Chestplate") .properties(p -> p.rarity(Rarity.RARE)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry QUANTUM_LEGGINGS = REGISTRATE .item("quarktech_leggings", @@ -2467,6 +2505,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierQuarkTech))) .lang("QuarkTech™ Suite Leggings") .properties(p -> p.rarity(Rarity.RARE)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry QUANTUM_BOOTS = REGISTRATE .item("quarktech_boots", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.BOOTS, p) @@ -2477,6 +2516,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierQuarkTech))) .lang("QuarkTech™ Suite Leggings") .properties(p -> p.rarity(Rarity.RARE)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry QUANTUM_HELMET = REGISTRATE .item("quarktech_helmet", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, ArmorItem.Type.HELMET, p) @@ -2487,6 +2527,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierQuarkTech))) .lang("QuarkTech™ Suite Helmet") .properties(p -> p.rarity(Rarity.RARE)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry LIQUID_FUEL_JETPACK = REGISTRATE @@ -2528,6 +2569,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierAdvNanoSuit))) .lang("Advanced NanoMuscle™ Suite Chestplate") .properties(p -> p.rarity(Rarity.RARE)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry QUANTUM_CHESTPLATE_ADVANCED = REGISTRATE .item("advanced_quarktech_chestplate", (p) -> new ArmorComponentItem(GTArmorMaterials.ARMOR, @@ -2539,6 +2581,7 @@ public Component getItemName(ItemStack stack) { ConfigHolder.INSTANCE.tools.voltageTierAdvQuarkTech))) .lang("Advanced QuarkTech™ Suite Chestplate") .properties(p -> p.rarity(Rarity.EPIC)) + .tag(CustomTags.PPE_ARMOR) .register(); public static ItemEntry POWER_THRUSTER = REGISTRATE.item("power_thruster", Item::new) diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java index 2d9bb41dbd..e4af3417c5 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java @@ -1447,6 +1447,33 @@ public static BiConsumer> createTankTooltips(String n .compassNodeSelf() .register(); + public static final MachineDefinition EVAPORATION_PLANT = REGISTRATE + .multiblock("evaporation_plant", WorkableElectricMultiblockMachine::new) + .langValue("Evaporation Tower") + .rotationState(RotationState.NON_Y_AXIS) + .recipeType(GTRecipeTypes.EVAPORATION_RECIPES) + .recipeModifier(GTRecipeModifiers.ELECTRIC_OVERCLOCK.apply(OverclockingLogic.NON_PERFECT_OVERCLOCK)) + .appearanceBlock(CASING_STAINLESS_EVAPORATION) + .pattern(definition -> FactoryBlockPattern.start(RIGHT, BACK, UP) + .aisle("YSYY", "YYYY", "YYYY", "YYYY") + .aisle("XXXX", "X##X", "X##X", "XXXX").setRepeatable(3, 5) + .aisle(" XX ", "X##X", "X##X", " XX ") + .where('S', Predicates.controller(blocks(definition.getBlock()))) + .where('Y', blocks(CASING_STAINLESS_EVAPORATION.get()) + .or(Predicates.abilities(PartAbility.INPUT_ENERGY).setMinGlobalLimited(1) + .setMaxGlobalLimited(2)) + .or(Predicates.abilities(PartAbility.IMPORT_FLUIDS).setExactLimit(1)) + .or(Predicates.abilities(PartAbility.EXPORT_ITEMS).setMaxGlobalLimited(1))) + .where('X', blocks(CASING_STAINLESS_EVAPORATION.get()) + .or(Predicates.abilities(PartAbility.EXPORT_FLUIDS_1X).setMaxLayerLimited(1))) + .where('#', Predicates.air()) + .where(' ', Predicates.any()) + .build()) + .partSorter(Comparator.comparingInt(a -> a.self().getPos().getY())) + .workableCasingRenderer(GTCEu.id("block/casings/solid/machine_casing_stainless_evaporation"), + GTCEu.id("block/multiblock/distillation_tower"), false) + .register(); + public static final MultiblockMachineDefinition VACUUM_FREEZER = REGISTRATE .multiblock("vacuum_freezer", WorkableElectricMultiblockMachine::new) .rotationState(RotationState.NON_Y_AXIS) diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterials.java index faff657f71..aa04916dfe 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMaterials.java @@ -591,6 +591,7 @@ private static void excludeAllGemsButNormal(Material material) { public static Material HydrofluoricAcid; public static Material NitricOxide; public static Material Iron3Chloride; + public static Material Iron2Chloride; public static Material UraniumHexafluoride; public static Material EnrichedUraniumHexafluoride; public static Material DepletedUraniumHexafluoride; @@ -630,6 +631,29 @@ private static void excludeAllGemsButNormal(Material material) { public static Material EnrichedNaquadahSulfate; public static Material NaquadriaSulfate; public static Material Pyrochlore; + public static Material PotassiumHydroxide; + public static Material PotassiumIodide; + public static Material PotassiumFerrocyanide; + public static Material CalciumFerrocyanide; + public static Material CalciumHydroxide; + public static Material CalciumCarbonate; + public static Material PotassiumCyanide; + public static Material PotassiumCarbonate; + public static Material HydrogenCyanide; + public static Material FormicAcid; + public static Material PotassiumSulfate; + public static Material PrussianBlue; + public static Material Formaldehyde; + public static Material Glycolonitrile; + public static Material DiethylenetriaminePentaacetonitrile; + public static Material DiethylenetriaminepentaaceticAcid; + public static Material SodiumNitrite; + + public static Material AcidicBromineSolution; + public static Material ConcentratedBromineSolution; + public static Material Iodide; + public static Material IodineSolution; + public static Material DiluteIodineSolution; /** * Organic chemistry @@ -713,6 +737,11 @@ private static void excludeAllGemsButNormal(Material material) { public static Material PolyvinylButyral; public static Material Biphenyl; public static Material PolychlorinatedBiphenyl; + public static Material AceticAnhydride; + public static Material AminoPhenol; + public static Material Paracetamol; + public static Material AmmoniumFormate; + public static Material Formamide; /** * Not possible to determine exact Components @@ -903,6 +932,13 @@ private static void excludeAllGemsButNormal(Material material) { public static Material SaltWater; public static Material Clay; public static Material Redstone; + public static Material Dichloroethane; + public static Material Diethylenetriamine; + + public static Material RawBrine; + public static Material DebrominatedBrine; + public static Material BrominatedChlorineVapor; + public static Material AcidicBromineExhaust; /** * Third Degree Materials @@ -923,6 +959,11 @@ private static void excludeAllGemsButNormal(Material material) { public static Material Fireclay; public static Material Diorite; + public static Material HotBrine; + public static Material HotChlorinatedBrominatedBrine; + public static Material HotDebrominatedBrine; + public static Material HotAlkalineDebrominatedBrine; + /** * Fourth Degree Materials */ @@ -931,6 +972,7 @@ private static void excludeAllGemsButNormal(Material material) { public static Material BasalticMineralSand; public static Material HSSE; public static Material HSSS; + public static Material RadAway; /** * GCyM Materials diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java new file mode 100644 index 0000000000..ea0041cdc4 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java @@ -0,0 +1,24 @@ +package com.gregtechceu.gtceu.common.data; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.common.effect.GTPoisonEffect; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class GTMobEffects { + + public static final DeferredRegister MOB_EFFECTS = DeferredRegister.create(ForgeRegistries.MOB_EFFECTS, + GTCEu.MOD_ID); + + public static final RegistryObject WEAK_POISON = MOB_EFFECTS.register("weak_poison", + () -> new GTPoisonEffect(MobEffectCategory.HARMFUL, 0x6D7917)); + + public static void init(IEventBus modBus) { + MOB_EFFECTS.register(modBus); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java index 7812294f69..a9b453bfff 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTRecipeTypes.java @@ -592,6 +592,11 @@ public class GTRecipeTypes { } }); + public static final GTRecipeType EVAPORATION_RECIPES = register("evaporation", ELECTRIC).setMaxIOSize(0, 1, 1, 6) + .setEUIO(IO.IN) + .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW_MULTIPLE, LEFT_TO_RIGHT) + .setSound(GTSoundEntries.MOTOR); + public final static GTRecipeType PYROLYSE_RECIPES = register("pyrolyse_oven", MULTIBLOCK).setMaxIOSize(2, 1, 1, 1) .setEUIO(IO.IN) .setSound(GTSoundEntries.FIRE); 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 a1b23dae19..c3277e6243 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 @@ -9,11 +9,12 @@ import com.gregtechceu.gtceu.api.data.chemical.material.properties.ToolProperty; import com.gregtechceu.gtceu.api.fluids.FluidBuilder; import com.gregtechceu.gtceu.api.fluids.FluidState; +import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttributes; import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys; import com.gregtechceu.gtceu.api.item.tool.GTToolType; import com.gregtechceu.gtceu.common.data.GTElements; -import net.minecraft.world.effect.MobEffects; +import java.util.List; import static com.gregtechceu.gtceu.api.GTValues.LV; import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.*; @@ -122,6 +123,7 @@ public static void register() { .buildAndRegister(); Bromine = new Material.Builder(GTCEu.id("bromine")) + .liquid(new FluidBuilder().attribute(FluidAttributes.ACID)) .color(0x912200).secondaryColor(0x080101).iconSet(SHINY) .element(GTElements.Br) .buildAndRegister(); @@ -168,8 +170,9 @@ public static void register() { .gas(new FluidBuilder().state(FluidState.GAS).customStill()) .element(GTElements.Cl) .hazard(HazardProperty.HazardType.INHALATION_POISON, - new HazardProperty.HazardEffect(500, MobEffects.BLINDNESS), - new HazardProperty.HazardDamage(2, 1), false) + List.of(HazardProperty.blindnessEffect(2000, 1000, 3), + HazardProperty.poisonEffect(2000, 1000, 3)), + false) .buildAndRegister(); Chromium = new Material.Builder(GTCEu.id("chromium")) @@ -181,7 +184,7 @@ public static void register() { .rotorStats(130, 155, 3.0f, 512) .fluidPipeProperties(2180, 35, true, true, false, false) .blastTemp(1700, GasTier.LOW) - .hazard(HazardProperty.HazardType.INHALATION_POISON, false) + .irritantHazard(false) .buildAndRegister(); Cobalt = new Material.Builder(GTCEu.id("cobalt")) @@ -198,7 +201,7 @@ public static void register() { Copernicium = new Material.Builder(GTCEu.id("copernicium")) .color(0x565c5d).secondaryColor(0xffd34b).iconSet(RADIOACTIVE) .element(GTElements.Cn) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Copper = new Material.Builder(GTCEu.id("copper")) @@ -215,7 +218,7 @@ public static void register() { Curium = new Material.Builder(GTCEu.id("curium")) .color(0x7B544E).iconSet(RADIOACTIVE) .element(GTElements.Cm) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Darmstadtium = new Material.Builder(GTCEu.id("darmstadtium")) @@ -267,7 +270,7 @@ public static void register() { Fermium = new Material.Builder(GTCEu.id("fermium")) .color(0xc99fe7).secondaryColor(0x3e0022).iconSet(METALLIC) .element(GTElements.Fm) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Flerovium = new Material.Builder(GTCEu.id("flerovium")) @@ -367,6 +370,7 @@ public static void register() { .buildAndRegister(); Iodine = new Material.Builder(GTCEu.id("iodine")) + .dust() .color(0x67686d).secondaryColor(0x773000).iconSet(SHINY) .element(GTElements.I) .buildAndRegister(); @@ -518,7 +522,7 @@ public static void register() { Neptunium = new Material.Builder(GTCEu.id("neptunium")) .color(0x284D7B).iconSet(RADIOACTIVE) .element(GTElements.Np) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Nickel = new Material.Builder(GTCEu.id("nickel")) @@ -605,7 +609,7 @@ public static void register() { .color(0x163b27).secondaryColor(0x00ff78) .iconSet(RADIOACTIVE) .element(GTElements.Po) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Platinum = new Material.Builder(GTCEu.id("platinum")) @@ -625,7 +629,7 @@ public static void register() { .ore(true) .color(0xba2727).secondaryColor(0x222730).iconSet(RADIOACTIVE) .element(GTElements.Pu239) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1.5f) .buildAndRegister(); Plutonium241 = new Material.Builder(GTCEu.id("plutonium_241")) @@ -634,7 +638,7 @@ public static void register() { .color(0xfa7272).secondaryColor(0x222730).iconSet(RADIOACTIVE) .appendFlags(EXT_METAL) .element(GTElements.Pu241) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1.5f) .buildAndRegister(); Potassium = new Material.Builder(GTCEu.id("potassium")) @@ -653,26 +657,26 @@ public static void register() { .color(0x786160).secondaryColor(0xe7ffb8) .iconSet(RADIOACTIVE) .element(GTElements.Pm) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Protactinium = new Material.Builder(GTCEu.id("protactinium")) .color(0xA78B6D).iconSet(RADIOACTIVE) .element(GTElements.Pa) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Radon = new Material.Builder(GTCEu.id("radon")) .gas() .color(0xFF39FF) .element(GTElements.Rn) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1) .buildAndRegister(); Radium = new Material.Builder(GTCEu.id("radium")) .color(0x838361).secondaryColor(0x90ff2d).iconSet(RADIOACTIVE) .element(GTElements.Ra) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Rhenium = new Material.Builder(GTCEu.id("rhenium")) @@ -783,7 +787,7 @@ public static void register() { Technetium = new Material.Builder(GTCEu.id("technetium")) .color(0xb1d0d8).secondaryColor(0xd7fce2).iconSet(RADIOACTIVE) .element(GTElements.Tc) - // .hazard(HazardProperty.HazardType.RADIOACTIVE) + // .radioactiveHazard(1) .buildAndRegister(); Tellurium = new Material.Builder(GTCEu.id("tellurium")) @@ -853,7 +857,7 @@ public static void register() { .color(0xff316b).secondaryColor(0xd00000) .iconSet(METALLIC) .element(GTElements.T) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1) .buildAndRegister(); Tungsten = new Material.Builder(GTCEu.id("tungsten")) @@ -875,7 +879,7 @@ public static void register() { .color(0x1d891d).secondaryColor(0x33342c).iconSet(RADIOACTIVE) .appendFlags(EXT_METAL) .element(GTElements.U238) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1) .buildAndRegister(); Uranium235 = new Material.Builder(GTCEu.id("uranium_235")) @@ -884,7 +888,7 @@ public static void register() { .color(0x46FA46).secondaryColor(0x33342c).iconSet(RADIOACTIVE) .appendFlags(EXT_METAL) .element(GTElements.U235) - .hazard(HazardProperty.HazardType.RADIOACTIVE) + .radioactiveHazard(1) .buildAndRegister(); Vanadium = new Material.Builder(GTCEu.id("vanadium")) @@ -936,6 +940,7 @@ public static void register() { .cableProperties(GTValues.V[7], 2, 2) .fluidPipeProperties(3776, 200, true, false, true, true) .blastTemp(5000, GasTier.HIGH, GTValues.VA[GTValues.IV], 600) + .radioactiveHazard(2) .buildAndRegister(); NaquadahEnriched = new Material.Builder(GTCEu.id("enriched_naquadah")) @@ -945,6 +950,7 @@ public static void register() { .appendFlags(EXT_METAL, GENERATE_FOIL) .element(GTElements.Nq1) .blastTemp(7000, GasTier.HIGH, GTValues.VA[GTValues.IV], 1000) + .radioactiveHazard(2.5f) .buildAndRegister(); Naquadria = new Material.Builder(GTCEu.id("naquadria")) @@ -954,6 +960,7 @@ public static void register() { .appendFlags(EXT_METAL, GENERATE_FOIL, GENERATE_GEAR, GENERATE_FINE_WIRE, GENERATE_BOLT_SCREW) .element(GTElements.Nq2) .blastTemp(9000, GasTier.HIGH, GTValues.VA[GTValues.ZPM], 1200) + .radioactiveHazard(3) .buildAndRegister(); Neutronium = new Material.Builder(GTCEu.id("neutronium")) @@ -966,6 +973,7 @@ public static void register() { .attackSpeed(0.5F).enchantability(33).magnetic().unbreakable().build()) .rotorStats(400, 250, 12.0f, 655360) .fluidPipeProperties(100_000, 5000, true, true, true, true) + .radioactiveHazard(10) .buildAndRegister(); Tritanium = new Material.Builder(GTCEu.id("tritanium")) diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/FirstDegreeMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/FirstDegreeMaterials.java index 51caaf7b6f..d913471388 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/FirstDegreeMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/FirstDegreeMaterials.java @@ -12,6 +12,7 @@ import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttributes; import com.gregtechceu.gtceu.api.item.tool.GTToolType; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.item.enchantment.Enchantments; @@ -879,8 +880,8 @@ public static void register() { .color(0xecfff3).secondaryColor(0x7d8e83) .components(Calcium, 1, Oxygen, 1) .hazard(HazardProperty.HazardType.CORROSIVE, - new HazardProperty.HazardEffect(5000, MobEffects.WEAKNESS, MobEffects.DIG_SLOWDOWN), - new HazardProperty.HazardDamage(2, 1)) + new HazardProperty.HazardEffect(5000, () -> new MobEffectInstance(MobEffects.WEAKNESS, 1), + () -> new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 1))) .buildAndRegister(); SodiumBisulfate = new Material.Builder(GTCEu.id("sodium_bisulfate")) @@ -933,7 +934,7 @@ public static void register() { .dust(1) .color(0xFFE4E1) .components(Chromium, 1, Oxygen, 3) - .hazard(HazardProperty.HazardType.CONTACT_POISON) + .irritantHazard(true) .buildAndRegister(); AntimonyTrioxide = new Material.Builder(GTCEu.id("antimony_trioxide")) @@ -990,8 +991,8 @@ public static void register() { .flags(DISABLE_DECOMPOSITION) .components(Sodium, 1, Oxygen, 1, Hydrogen, 1) .hazard(HazardProperty.HazardType.CORROSIVE, - new HazardProperty.HazardEffect(5000, MobEffects.WEAKNESS, MobEffects.DIG_SLOWDOWN), - new HazardProperty.HazardDamage(2, 1)) + new HazardProperty.HazardEffect(5000, () -> new MobEffectInstance(MobEffects.WEAKNESS, 1), + () -> new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 1))) .buildAndRegister(); SodiumPersulfate = new Material.Builder(GTCEu.id("sodium_persulfate")) @@ -1195,6 +1196,13 @@ public static void register() { .components(Iron, 1, Chlorine, 3) .buildAndRegister(); + Iron2Chloride = new Material.Builder(GTCEu.id("iron_ii_chloride")) + .fluid() + .color(0xe8e0be) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Iron, 1, Chlorine, 2) + .buildAndRegister(); + UraniumHexafluoride = new Material.Builder(GTCEu.id("uranium_hexafluoride")) .gas() .color(0x42D126) @@ -1492,8 +1500,161 @@ public static void register() { Pyrochlore = new Material.Builder(GTCEu.id("pyrochlore")) .dust().ore() .color(0x5b4838).secondaryColor(0x331400).iconSet(METALLIC) - .flags() .components(Calcium, 2, Niobium, 2, Oxygen, 7) .buildAndRegister(); + + PotassiumHydroxide = new Material.Builder(GTCEu.id("potassium_hydroxide")) + .dust(1) + .color(0xd1c299).secondaryColor(0x85623a).iconSet(METALLIC) + .hazard(HazardProperty.HazardType.CORROSIVE, + new HazardProperty.HazardEffect(5000, () -> new MobEffectInstance(MobEffects.WEAKNESS, 1), + () -> new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 1))) + .components(Potassium, 1, Oxygen, 1, Hydrogen, 1) + .buildAndRegister(); + + PotassiumIodide = new Material.Builder(GTCEu.id("potassium_iodide")) + .dust() + .color(0xa66c71).secondaryColor(0x802d67).iconSet(METALLIC) + .components(Potassium, 1, Iodine, 1) + .buildAndRegister(); + + PotassiumCarbonate = new Material.Builder(GTCEu.id("potassium_carbonate")) + .dust() + .color(0xa66c71).secondaryColor(0x802d67).iconSet(METALLIC) + .components(Potassium, 2, Carbon, 1, Oxygen, 3) + .buildAndRegister(); + + PotassiumFerrocyanide = new Material.Builder(GTCEu.id("potassium_ferrocyanide")) + .dust() + .color(0xc9a842).secondaryColor(0x947110).iconSet(DULL) + .components(Potassium, 4, Iron, 1, Carbon, 6, Nitrogen, 6) + .buildAndRegister() + .setFormula("K4[Fe(CN)6]", true); + + CalciumFerrocyanide = new Material.Builder(GTCEu.id("calcium_ferrocyanide")) + .dust() + .color(0xc9a842).secondaryColor(0x947110).iconSet(DULL) + .components(Calcium, 2, Iron, 1, Carbon, 6, Nitrogen, 6) + .buildAndRegister() + .setFormula("Ca2[Fe(CN)6]", true); + + CalciumHydroxide = new Material.Builder(GTCEu.id("calcium_hydroxide")) + .dust() + .color(0x72dbd4).secondaryColor(0x138a80).iconSet(ROUGH) + .components(Calcium, 1, Oxygen, 2, Hydrogen, 2) + .buildAndRegister() + .setFormula("Ca(OH)2", true); + + CalciumCarbonate = new Material.Builder(GTCEu.id("calcium_carbonate")) + .dust() + .color(0xd9ca9c).secondaryColor(0xad913b) + .components(Calcium, 2, Carbon, 1, Oxygen, 3) + .buildAndRegister(); + + PotassiumCyanide = new Material.Builder(GTCEu.id("potassium_cyanide")) + .dust() + .color(0x93badb).secondaryColor(0x0c5696).iconSet(ROUGH) + .components(Potassium, 1, Carbon, 1, Nitrogen, 1) + .hazard(HazardProperty.HazardType.INHALATION_POISON, HazardProperty.poisonEffect(100, 0, 4), true) + .buildAndRegister(); + + HydrogenCyanide = new Material.Builder(GTCEu.id("hydrogen_cyanide")) + .gas() + .color(0x72dbd4) + .components(Hydrogen, 1, Carbon, 1, Nitrogen, 1) + .hazard(HazardProperty.HazardType.INHALATION_POISON, HazardProperty.poisonEffect(100, 0, 4), true) + .buildAndRegister(); + + FormicAcid = new Material.Builder(GTCEu.id("formic_acid")) + .gas() + .color(0xa6a6a6) + .components(Carbon, 1, Hydrogen, 2, Oxygen, 2) + .hazard(HazardProperty.HazardType.INHALATION_POISON) + .buildAndRegister(); + + PotassiumSulfate = new Material.Builder(GTCEu.id("potassium_sulfate")) + .dust() + .color(0xebab34).secondaryColor(0xb5570e) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Potassium, 1, Sulfur, 1, Oxygen, 4) + .buildAndRegister(); + + PrussianBlue = new Material.Builder(GTCEu.id("prussian_blue")) + .dust() + .color(0x102e5e).secondaryColor(0x010c42) + .flags(DISABLE_DECOMPOSITION) + .components(Iron, 7, Carbon, 18, Nitrogen, 18) + .buildAndRegister() + .setFormula("Fe4[Fe(CN)6]3", true); + + Formaldehyde = new Material.Builder(GTCEu.id("formaldehyde")) + .liquid() + .color(0xddeced) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Carbon, 1, Hydrogen, 2, Oxygen, 1) + .buildAndRegister(); + + Glycolonitrile = new Material.Builder(GTCEu.id("glycolonitrile")) + .liquid() + .color(0x5b8c8f) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 2, Hydrogen, 3, Nitrogen, 1, Oxygen, 1) + .buildAndRegister(); + + AcidicBromineSolution = new Material.Builder(GTCEu.id("acidic_bromine_solution")) + .liquid() + .color(0xc49b52) + .components(Chlorine, 1, Bromine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + ConcentratedBromineSolution = new Material.Builder(GTCEu.id("concentrated_bromine_solution")) + .liquid() + .color(0x91481e) + .components(Bromine, 2, Chlorine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + Iodide = new Material.Builder(GTCEu.id("iodide")) + .liquid() + .color(0x5f6173) + .components(Iodine, 2) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + IodineSolution = new Material.Builder(GTCEu.id("iodine_solution")) + .liquid() + .color(0x9194a3) + .components(Hydrogen, 1, Iodine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + DiluteIodineSolution = new Material.Builder(GTCEu.id("dilute_iodine_solution")) + .liquid() + .color(0x8187a6) + .components(Hydrogen, 1, Iodine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + DiethylenetriaminePentaacetonitrile = new Material.Builder(GTCEu.id("diethylenetriamine_pentaacetonitrile")) + .liquid() + .color(0xcbbfd6) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 14, Hydrogen, 18, Nitrogen, 8) + .buildAndRegister(); + + DiethylenetriaminepentaaceticAcid = new Material.Builder(GTCEu.id("diethylenetriaminepentaacetic_acid")) + .dust() + .color(0xe8c93c).secondaryColor(0xc99118) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 14, Hydrogen, 23, Nitrogen, 3, Oxygen, 10) + .buildAndRegister(); + + SodiumNitrite = new Material.Builder(GTCEu.id("sodium_nitrite")) + .dust() + .color(0xcfbf65).secondaryColor(0x85600b) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Sodium, 1, Nitrogen, 1, Oxygen, 2) + .buildAndRegister(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/GTFoods.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/GTFoods.java index dcf125c2ed..b75bbadea5 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/GTFoods.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/GTFoods.java @@ -19,5 +19,8 @@ public class GTFoods { .effect(() -> new MobEffectInstance(MobEffects.HEAL, 200, 1), 0.1f) .alwaysEat().nutrition(4).saturationMod(0.3F).build(); + public static final FoodProperties ANTIDOTE = new FoodProperties.Builder() + .alwaysEat().fast().build(); + public static void init() {} } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/HigherDegreeMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/HigherDegreeMaterials.java index e0f141935f..aa1874e643 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/HigherDegreeMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/HigherDegreeMaterials.java @@ -165,6 +165,34 @@ public static void register() { .components(Mirabilite, 2, Clay, 7) .buildAndRegister(); + HotBrine = new Material.Builder(GTCEu.id("hot_brine")) + .liquid(320) + .color(0xbe6026) + .components(RawBrine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + HotChlorinatedBrominatedBrine = new Material.Builder(GTCEu.id("hot_chlorinated_brominated_brine")) + .liquid(320) + .color(0xab765d) + .components(HotBrine, 1, Chlorine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + HotDebrominatedBrine = new Material.Builder(GTCEu.id("hot_debrominated_brine")) + .liquid(320) + .color(0xab896d) + .components(DebrominatedBrine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + HotAlkalineDebrominatedBrine = new Material.Builder(GTCEu.id("hot_alkaline_debrominated_brine")) + .liquid(320) + .color(0xbe8938) + .components(HotDebrominatedBrine, 2, Chlorine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + BlueAlloy = new Material.Builder(GTCEu.id("blue_alloy")) .ingot() .liquid(new FluidBuilder().temperature(1400)) @@ -173,5 +201,12 @@ public static void register() { .components(Electrotine, 4, Silver, 1) .cableProperties(GTValues.V[GTValues.HV], 2, 1) .buildAndRegister(); + + RadAway = new Material.Builder(GTCEu.id("rad_away")) + .dust() + .color(0xe3a1d7).secondaryColor(0x9845a3).iconSet(ROUGH) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .components(PotassiumIodide, 5, PrussianBlue, 3, DiethylenetriaminepentaaceticAcid, 5) + .buildAndRegister(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java index 9a66f39649..0d1b1dcd9c 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/OrganicChemistryMaterials.java @@ -8,6 +8,7 @@ import com.gregtechceu.gtceu.api.fluids.attribute.FluidAttributes; import com.gregtechceu.gtceu.api.item.tool.GTToolType; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import static com.gregtechceu.gtceu.api.data.chemical.material.info.MaterialFlags.*; @@ -401,15 +402,14 @@ public static void register() { .fluid() .color(0xAA8800) .components(Carbon, 1, Hydrogen, 4, Oxygen, 1) - .hazard(HazardProperty.HazardType.INHALATION_POISON, - new HazardProperty.HazardEffect(200, MobEffects.BLINDNESS)) + .hazard(HazardProperty.HazardType.INHALATION_POISON, HazardProperty.blindnessEffect(200, 200, 3)) .buildAndRegister(); Ethanol = new Material.Builder(GTCEu.id("ethanol")) .liquid(new FluidBuilder().customStill()) .flags(DISABLE_DECOMPOSITION) .hazard(HazardProperty.HazardType.INHALATION_POISON, - new HazardProperty.HazardEffect(200, MobEffects.CONFUSION)) + new HazardProperty.HazardEffect(200, () -> new MobEffectInstance(MobEffects.CONFUSION, 1))) .components(Carbon, 2, Hydrogen, 6, Oxygen, 1) .buildAndRegister(); @@ -571,5 +571,42 @@ public static void register() { .hazard(HazardProperty.HazardType.INHALATION_POISON) .buildAndRegister() .setFormula("(C6H4Cl)2", true); + + AceticAnhydride = new Material.Builder(GTCEu.id("acetic_anhydride")) + .fluid() + .color(0xE0D182) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 4, Hydrogen, 6, Oxygen, 3) + .buildAndRegister() + .setFormula("(CH3CO)2O", true); + + AminoPhenol = new Material.Builder(GTCEu.id("aminophenol")) + .fluid() + .color(0x784421) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 6, Hydrogen, 7, Nitrogen, 1, Oxygen, 1) + .buildAndRegister() + .setFormula("H2NC6H4OH", true); + + Paracetamol = new Material.Builder(GTCEu.id("paracetamol")) + .dust() + .color(0xF2EDCB) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 8, Hydrogen, 9, Nitrogen, 1, Oxygen, 2) + .buildAndRegister(); + + AmmoniumFormate = new Material.Builder(GTCEu.id("ammonium_formate")) + .gas() + .color(0x93badb) + .components(Carbon, 1, Hydrogen, 5, Nitrogen, 1, Oxygen, 2) + .hazard(HazardProperty.HazardType.INHALATION_POISON) + .buildAndRegister(); + + Formamide = new Material.Builder(GTCEu.id("formamide")) + .liquid() + .color(0x5cccb6) + .components(Carbon, 1, Hydrogen, 3, Nitrogen, 1, Oxygen, 1) + .hazard(HazardProperty.HazardType.INHALATION_POISON) + .buildAndRegister(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java index 804ce12ac8..e60d37b4a4 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/SecondDegreeMaterials.java @@ -322,6 +322,7 @@ public static void register() { .color(0xa8aa9a).iconSet(ROUGH) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Asbestos, 4, Saltpeter, 1) + .hazard(HazardProperty.HazardType.NONE) .buildAndRegister(); NaquadahAlloy = new Material.Builder(GTCEu.id("naquadah_alloy")) @@ -500,5 +501,47 @@ public static void register() { .components(Silicon, 1, Pyrite, 5, Ruby, 1, Mercury, 3) .hazard(HazardProperty.HazardType.NONE) .buildAndRegister(); + + Dichloroethane = new Material.Builder(GTCEu.id("dichloroethane")) + .liquid() + .color(0xafc979) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Carbon, 2, Hydrogen, 4, Chlorine, 2) + .buildAndRegister(); + + Diethylenetriamine = new Material.Builder(GTCEu.id("diethylenetriamine")) + .liquid() + .color(0xa9d9a7) + .flags(DISABLE_DECOMPOSITION) + .components(Carbon, 4, Hydrogen, 13, Nitrogen, 3) + .hazard(HazardProperty.HazardType.CONTACT_POISON) + .buildAndRegister(); + + RawBrine = new Material.Builder(GTCEu.id("raw_brine")) + .liquid() + .color(0x9f6b26) + .components(Water, 4, Salt, 20, Magnesium, 3, Lithium, 2, Bromine, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + DebrominatedBrine = new Material.Builder(GTCEu.id("debrominated_brine")) + .liquid() + .color(0xab8c6d) + .components(Water, 4, Salt, 20, Magnesium, 3, Lithium, 2) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .buildAndRegister(); + + BrominatedChlorineVapor = new Material.Builder(GTCEu.id("brominated_chlorine_vapor")) + .gas() + .color(0xbb9b72) + .components(Chlorine, 1, Bromine, 1, Steam, 1) + .flags(DISABLE_DECOMPOSITION) + .buildAndRegister(); + + AcidicBromineExhaust = new Material.Builder(GTCEu.id("acidic_bromine_exhaust")) + .gas() + .color(0x8f681e) + .components(Steam, 3, Chlorine, 1) + .buildAndRegister(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/materials/UnknownCompositionMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/data/materials/UnknownCompositionMaterials.java index 605cda3ed7..3daa931ec7 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/data/materials/UnknownCompositionMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/data/materials/UnknownCompositionMaterials.java @@ -557,6 +557,7 @@ public static void register() { PCBCoolant = new Material.Builder(GTCEu.id("pcb_coolant")) .fluid().color(0xD5D69C) - .hazard(HazardProperty.HazardType.INHALATION_POISON).buildAndRegister(); + .hazard(HazardProperty.HazardType.INHALATION_POISON) + .buildAndRegister(); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/effect/GTPoisonEffect.java b/src/main/java/com/gregtechceu/gtceu/common/effect/GTPoisonEffect.java new file mode 100644 index 0000000000..ed0185175f --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/effect/GTPoisonEffect.java @@ -0,0 +1,29 @@ +package com.gregtechceu.gtceu.common.effect; + +import net.minecraft.world.effect.MobEffect; +import net.minecraft.world.effect.MobEffectCategory; +import net.minecraft.world.entity.LivingEntity; + +public class GTPoisonEffect extends MobEffect { + + public GTPoisonEffect(MobEffectCategory category, int color) { + super(category, color); + } + + @Override + public void applyEffectTick(LivingEntity livingEntity, int amplifier) { + if (livingEntity.getHealth() > 1.0F) { + livingEntity.hurt(livingEntity.damageSources().magic(), amplifier / 10.0F); + } + } + + @Override + public boolean isDurationEffectTick(int duration, int amplifier) { + int j = 25 >> amplifier; + if (j > 0) { + return duration % j == 0; + } else { + return true; + } + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/AntidoteBehavior.java b/src/main/java/com/gregtechceu/gtceu/common/item/AntidoteBehavior.java new file mode 100644 index 0000000000..3ba88186ed --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/common/item/AntidoteBehavior.java @@ -0,0 +1,84 @@ +package com.gregtechceu.gtceu.common.item; + +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty; +import com.gregtechceu.gtceu.api.item.component.IAddInformation; +import com.gregtechceu.gtceu.api.item.component.IInteractionItem; +import com.gregtechceu.gtceu.config.ConfigHolder; +import com.gregtechceu.gtceu.utils.GTUtil; + +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; + +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Defines an antidote for a hazard (e.g. poisoning) + * + * @param types the type of the hazard to remove + * @param timeToRemove the time to remove from the chosen hazard. -1 for all. + */ +public record AntidoteBehavior(Set types, int timeToRemove) + implements IInteractionItem, IAddInformation { + + public AntidoteBehavior(int timeToRemove, HazardProperty.HazardType... types) { + this(Arrays.stream(types).collect(Collectors.toSet()), timeToRemove); + } + + @Override + public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livingEntity) { + ItemStack itemstack = IInteractionItem.super.finishUsingItem(stack, level, livingEntity); + IHazardEffectTracker tracker = GTCapabilityHelper.getHazardEffectTracker(livingEntity); + if (tracker != null) { + var effectTimes = tracker.getCurrentHazardEffects(); + var typesToEffects = tracker.getTypesToEffects(); + for (var type : this.types) { + var effects = typesToEffects.getOrDefault(type, Set.of()); + for (HazardProperty.HazardEffect effect : effects) { + if (!effectTimes.containsKey(effect)) { + continue; + } + if (timeToRemove == -1) { + effectTimes.removeInt(effect); + } else { + int effectTime = effectTimes.getInt(effect); + effectTimes.put(effect, Math.max(0, effectTime - this.timeToRemove)); + if (effectTimes.getInt(effect) == 0) { + effectTimes.removeInt(effect); + } + } + } + } + } + return itemstack; + } + + @Override + public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltipComponents, + TooltipFlag isAdvanced) { + if (!ConfigHolder.INSTANCE.gameplay.hazardsEnabled) return; + + if (GTUtil.isShiftDown()) { + tooltipComponents.add(Component.translatable("gtceu.hazard.antidote.description_shift")); + for (var type : types) { + tooltipComponents.add(Component + .translatable("gtceu.hazard." + type.name().toLowerCase())); + } + Component time = this.timeToRemove == -1 ? + Component.translatable("gtceu.hazard.antidote.description.time_removed.all") : + Component.literal(Integer.toString(this.timeToRemove / 20)); + tooltipComponents.add(Component.translatable("gtceu.hazard.antidote.description.time_removed", time)); + return; + } + tooltipComponents.add(Component.translatable("gtceu.hazard.antidote.description")); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/armor/GTArmorMaterials.java b/src/main/java/com/gregtechceu/gtceu/common/item/armor/GTArmorMaterials.java index 9603f095cb..f8717cd8d2 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/armor/GTArmorMaterials.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/armor/GTArmorMaterials.java @@ -36,6 +36,18 @@ public enum GTArmorMaterials implements ArmorMaterial, StringRepresentable { map.put(ArmorItem.Type.CHESTPLATE, 0); map.put(ArmorItem.Type.HELMET, 0); }), 50, SoundEvents.ARMOR_EQUIP_GENERIC, 5.0F, 0.0F, () -> Ingredient.EMPTY), + BAD_PPE_EQUIPMENT("bad_ppe_equipment", 10, Util.make(new EnumMap<>(ArmorItem.Type.class), map -> { + map.put(ArmorItem.Type.BOOTS, 1); + map.put(ArmorItem.Type.LEGGINGS, 2); + map.put(ArmorItem.Type.CHESTPLATE, 3); + map.put(ArmorItem.Type.HELMET, 1); + }), 10, SoundEvents.ARMOR_EQUIP_GENERIC, 0.0F, 0.0F, () -> Ingredient.EMPTY), + GOOD_PPE_EQUIPMENT("good_ppe_equipment", 20, Util.make(new EnumMap<>(ArmorItem.Type.class), map -> { + map.put(ArmorItem.Type.BOOTS, 2); + map.put(ArmorItem.Type.LEGGINGS, 5); + map.put(ArmorItem.Type.CHESTPLATE, 6); + map.put(ArmorItem.Type.HELMET, 2); + }), 10, SoundEvents.ARMOR_EQUIP_GENERIC, 0.0F, 0.0F, () -> Ingredient.EMPTY), ; public static final Codec CODEC = StringRepresentable.fromEnum(GTArmorMaterials::values); diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/armor/HazmatSuit.java b/src/main/java/com/gregtechceu/gtceu/common/item/armor/HazmatSuit.java index 49ea1d47ed..e6c015ff69 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/armor/HazmatSuit.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/armor/HazmatSuit.java @@ -16,9 +16,11 @@ public class HazmatSuit implements IArmorLogic { private final ArmorItem.Type type; + private final String armorTexture; - public HazmatSuit(ArmorItem.Type type) { + public HazmatSuit(ArmorItem.Type type, String armorTexture) { this.type = type; + this.armorTexture = armorTexture; } @Override @@ -33,7 +35,6 @@ public int getArmorDisplay(Player player, @NotNull ItemStack armor, EquipmentSlo @Override public @Nullable ResourceLocation getArmorTexture(ItemStack stack, Entity entity, EquipmentSlot slot, String type) { - String armorTexture = "hazmat"; return slot != EquipmentSlot.LEGS ? GTCEu.id(String.format("textures/armor/%s_1.png", armorTexture)) : GTCEu.id(String.format("textures/armor/%s_2.png", armorTexture)); diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/armor/QuarkTechSuite.java b/src/main/java/com/gregtechceu/gtceu/common/item/armor/QuarkTechSuite.java index fc48f34e5d..5b37d0bf3d 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/item/armor/QuarkTechSuite.java +++ b/src/main/java/com/gregtechceu/gtceu/common/item/armor/QuarkTechSuite.java @@ -32,6 +32,9 @@ import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; import org.jetbrains.annotations.NotNull; @@ -84,25 +87,29 @@ public void onArmorTick(Level world, Player player, ItemStack itemStack) { if (item.canUse(energyPerUse / 10) && player.getFoodData().needsFood()) { int slotId = -1; - for (int i = 0; i < player.getInventory().items.size(); i++) { - ItemStack current = player.getInventory().items.get(i); - if (current.getFoodProperties(player) != null) { - slotId = i; - break; + IItemHandler playerInv = player.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve().orElse(null); + if (playerInv instanceof IItemHandlerModifiable items) { + for (int i = 0; i < items.getSlots(); i++) { + ItemStack current = items.getStackInSlot(i); + if (current.getFoodProperties(player) != null) { + slotId = i; + break; + } } - } - if (slotId > -1) { - ItemStack stack = player.getInventory().items.get(slotId); - InteractionResultHolder result = ArmorUtils.eat(player, stack); - stack = result.getObject(); - if (stack.isEmpty()) - player.getInventory().items.set(slotId, ItemStack.EMPTY); + if (slotId > -1) { + ItemStack stack = items.getStackInSlot(slotId); + InteractionResultHolder result = ArmorUtils.eat(player, stack); + stack = result.getObject(); + if (stack.isEmpty()) + items.setStackInSlot(slotId, ItemStack.EMPTY); - if (result.getResult() == InteractionResult.SUCCESS) - item.discharge(energyPerUse / 10, item.getTier(), true, false, false); + if (result.getResult() == InteractionResult.SUCCESS) + item.discharge(energyPerUse / 10, item.getTier(), true, false, false); + + ret = true; + } - ret = true; } } @@ -248,19 +255,19 @@ public static void disableNightVision(@NotNull Level world, Player player, boole * if (energyPerUse > 0) { * damageLimit = (int) Math.min(damageLimit, 25.0D * item.getCharge() / (energyPerUse * 100.0D)); * } - * + * * if (source == DamageSource.FALL) { * if (SLOT == EntityEquipmentSlot.FEET) { * return new ArmorProperties(10, 1.0D, damageLimit); * } - * + * * if (SLOT == EntityEquipmentSlot.LEGS) { * return new ArmorProperties(9, 0.8D, damageLimit); * } * } * return new ArmorProperties(8, getDamageAbsorption() * getAbsorption(armor), damageLimit); * } - * + * * @Override * public boolean handleUnblockableDamage(EntityLivingBase entity, @NotNull ItemStack armor, DamageSource source, * double damage, EntityEquipmentSlot equipmentSlot) { diff --git a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java index 88af8eb0a7..7a80a8cf70 100644 --- a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java +++ b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java @@ -455,6 +455,10 @@ public static class GameplayConfigs { @Configurable @Configurable.Comment({ "Enable hazardous materials", "Default: true" }) public boolean hazardsEnabled = true; + @Configurable + @Configurable.Comment({ "Whether hazards are applied to all valid items, or just GT's.", + "true = all, false = GT only.", "Default: true" }) + public boolean universalHazards = true; } public static class ClientConfigs { diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java index 008ed915c0..d068c1e940 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java @@ -1,15 +1,20 @@ package com.gregtechceu.gtceu.core.mixins; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker; import com.gregtechceu.gtceu.core.IFireImmuneEntity; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) @@ -20,13 +25,33 @@ public abstract class EntityMixin implements IFireImmuneEntity { @Unique private boolean gtceu$fireImmune = false; + @Unique + private boolean gtceu$isEntityInit = false; @Inject(method = "fireImmune", at = @At("RETURN"), cancellable = true) private void gtceu$changeFireImmune(CallbackInfoReturnable cir) { cir.setReturnValue(gtceu$fireImmune || cir.getReturnValueZ()); } + @Inject(method = "", at = @At("TAIL")) + private void gtceu$onEntityInit(EntityType entityType, Level level, CallbackInfo ci) { + gtceu$isEntityInit = true; + } + public void gtceu$setFireImmune(boolean isImmune) { this.gtceu$fireImmune = isImmune; } + + @SuppressWarnings("UnreachableCode") // it doesn't like the cast because mixin. + @ModifyReturnValue(method = "getMaxAirSupply", at = @At("RETURN")) + private int gtceu$hazardModifyMaxAir(int original) { + if (!gtceu$isEntityInit) { + return original; + } + IHazardEffectTracker tracker = GTCapabilityHelper.getHazardEffectTracker((Entity) (Object) this); + if (tracker != null && tracker.getMaxAirSupply() != -1) { + return tracker.getMaxAirSupply(); + } + return original; + } } diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/GuiHeartTypeMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/GuiHeartTypeMixin.java new file mode 100644 index 0000000000..d50077288c --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/GuiHeartTypeMixin.java @@ -0,0 +1,21 @@ +package com.gregtechceu.gtceu.core.mixins; + +import com.gregtechceu.gtceu.common.data.GTMobEffects; + +import net.minecraft.world.entity.player.Player; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(targets = "net.minecraft.client.gui.Gui$HeartType") +public class GuiHeartTypeMixin { + + @ModifyExpressionValue(method = "forPlayer", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/world/entity/player/Player;hasEffect(Lnet/minecraft/world/effect/MobEffect;)Z", + ordinal = 0)) + private static boolean gtceu$isPoisoned(boolean original, Player player) { + return original || player.hasEffect(GTMobEffects.WEAK_POISON.get()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/InventoryMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/InventoryMixin.java index d531381f6f..e2968405c0 100644 --- a/src/main/java/com/gregtechceu/gtceu/core/mixins/InventoryMixin.java +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/InventoryMixin.java @@ -1,17 +1,39 @@ package com.gregtechceu.gtceu.core.mixins; +import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper; +import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker; +import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper; +import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey; +import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry; import com.gregtechceu.gtceu.api.item.IGTTool; +import com.gregtechceu.gtceu.api.item.TagPrefixItem; +import com.gregtechceu.gtceu.api.item.forge.GTBucketItem; +import com.gregtechceu.gtceu.config.ConfigHolder; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Inventory.class) -public class InventoryMixin { +public abstract class InventoryMixin { + + @Shadow + public abstract ItemStack getItem(int slot); + + @Shadow + @Final + public Player player; @WrapOperation(method = "findSlotMatchingUnusedItem", at = @At(value = "INVOKE", @@ -44,4 +66,79 @@ public class InventoryMixin { } return original.call(instance); } + + // Capture any and all player inventory changes. why doesn't forge have an event for this??? + @Inject(method = "setItem", at = @At("HEAD")) + private void gtceu$setItemInSlot(int slot, ItemStack stack, CallbackInfo ci) { + if (this.player.level().isClientSide) { + return; + } + ItemStack current = !stack.isEmpty() ? stack : this.getItem(slot); + // force the stack to have a count of 1 in case it's empty. + if (current != ItemStack.EMPTY) { + ItemStack old = current; + int oldCount = old.getCount(); + current.setCount(1); + current = current.copy(); + old.setCount(oldCount); + } + + UnificationEntry entry = null; + if (current.getItem() instanceof BucketItem bucket) { + if (ConfigHolder.INSTANCE.gameplay.universalHazards || bucket instanceof GTBucketItem) { + // fake the entry being a prefix at all. + entry = new UnificationEntry(null, ChemicalHelper.getMaterial(bucket.getFluid())); + } + } else if (current.getItem() instanceof TagPrefixItem prefixItem) { + entry = new UnificationEntry(prefixItem.tagPrefix, prefixItem.material); + } else if (ConfigHolder.INSTANCE.gameplay.universalHazards) { + entry = ChemicalHelper.getUnificationEntry(current.getItem()); + } + if (entry == null || entry.material == null) { + return; + } + if (!entry.material.hasProperty(PropertyKey.HAZARD)) { + return; + } + IHazardEffectTracker tracker = GTCapabilityHelper.getHazardEffectTracker(player); + if (tracker == null) { + return; + } + if (current.isEmpty()) { + tracker.removeHazardItem(entry); + } else { + tracker.addHazardItem(entry); + } + } + + @Inject(method = "removeItem(II)Lnet/minecraft/world/item/ItemStack;", at = @At("HEAD")) + private void gtceu$dropitem(int slot, int amount, CallbackInfoReturnable cir) { + if (this.player.level().isClientSide) { + return; + } + ItemStack current = this.getItem(slot); + + UnificationEntry entry = null; + if (current.getItem() instanceof BucketItem bucket) { + if (ConfigHolder.INSTANCE.gameplay.universalHazards || bucket instanceof GTBucketItem) { + // fake the fluid being an UnificationEntry at all. + entry = new UnificationEntry(null, ChemicalHelper.getMaterial(bucket.getFluid())); + } + } else if (current.getItem() instanceof TagPrefixItem prefixItem) { + entry = new UnificationEntry(prefixItem.tagPrefix, prefixItem.material); + } else if (ConfigHolder.INSTANCE.gameplay.universalHazards) { + entry = ChemicalHelper.getUnificationEntry(current.getItem()); + } + if (entry == null || entry.material == null) { + return; + } + if (!entry.material.hasProperty(PropertyKey.HAZARD)) { + return; + } + IHazardEffectTracker tracker = GTCapabilityHelper.getHazardEffectTracker(player); + if (tracker == null) { + return; + } + tracker.removeHazardItem(entry); + } } 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 1359406dab..eed431b09a 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -123,6 +123,10 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.hazard.inhalation_poison", "§2Poisonous when inhaled"); provider.add("gtceu.hazard.corrosive", "§6Corrosive"); provider.add("gtceu.hazard.radioactive", "§eRadioactive"); + provider.add("gtceu.hazard.antidote.description", "§aAntidote §7Hold Shift to show details"); + provider.add("gtceu.hazard.antidote.description_shift", "§aCures types:"); + provider.add("gtceu.hazard.antidote.description.time_removed", "Removes %ss of current ailments' time"); + provider.add("gtceu.hazard.antidote.description.time_removed.all", "all"); provider.add("item.gtceu.tool.replace_tool_head", "Craft with a new Tool Head to replace it"); provider.add("item.gtceu.tool.usable_as", "§8Usable as: §f%s"); @@ -434,6 +438,7 @@ public static void init(RegistrateLangProvider provider) { replace(provider, GTMaterials.PCBCoolant.getUnlocalizedName(), "PCB Coolant"); replace(provider, GTMaterials.TungstenSteel.getUnlocalizedName(), "Tungstensteel"); replace(provider, GTMaterials.Iron3Chloride.getUnlocalizedName(), "Iron III Chloride"); + replace(provider, GTMaterials.Iron2Chloride.getUnlocalizedName(), "Iron II Chloride"); replace(provider, GTMaterials.OilHeavy.getUnlocalizedName(), "Heavy Oil"); replace(provider, "block.gtceu.oil_heavy", "Heavy Oil"); replace(provider, GTMaterials.OilLight.getUnlocalizedName(), "Light Oil"); @@ -1165,18 +1170,20 @@ public static void init(RegistrateLangProvider provider) { replace(provider, "block.gtceu.yellow_stripes_block.b", "Yellow Stripes Block"); replace(provider, "block.gtceu.yellow_stripes_block.c", "Yellow Stripes Block"); replace(provider, "block.gtceu.yellow_stripes_block.d", "Yellow Stripes Block"); + + provider.add("effect.gtceu.weak_poison", "Weak Poison"); } /** * Returns the sub-key consisting of the given key plus the given index.
* E.g.,
- * + * *
      * getSubKey("terminal.fluid_prospector.tier", 0)
      * 
- * + * * returns the String: - * + * *
      * 
      * "terminal.fluid_prospector.tier.0"
@@ -1194,22 +1201,22 @@ protected static String getSubKey(String key, int index) {
      * Registers multiple values under the same key with a given provider.
*
* For example, a cumbersome way to add translations would be the following:
- * + * *
      * provider.add("terminal.fluid_prospector.tier.0", "radius size 1");
      * provider.add("terminal.fluid_prospector.tier.1", "radius size 2");
      * provider.add("terminal.fluid_prospector.tier.2", "radius size 3");
      * 
- * + * * Instead, multiLang can be used for the same result: - * + * *
      * multiLang(provider, "terminal.fluid_prospector.tier", "radius size 1", "radius size 2", "radius size 3");
      * 
- * + * * In situations requiring a large number of generated translations, the following could be used instead, which * generates translations for 100 tiers: - * + * *
      * multiLang(provider, "terminal.fluid_prospector.tier", IntStream.of(100)
      *                 .map(i -> i + 1)
@@ -1232,21 +1239,21 @@ protected static void multiLang(RegistrateLangProvider provider, String key, Str
     /**
      * Gets all translation components from a multi lang's sub-keys.
* E.g., given a multi lang: - * + * *
      * multiLang(provider, "terminal.fluid_prospector.tier", "radius size 1", "radius size 2", "radius size 3");
      * 
- * + * * The following code can be used to print out the translations: - * + * *
      * for (var component : getMultiLang("terminal.fluid_prospector.tier")) {
      *     System.out.println(component.getString());
      * }
      * 
- * + * * Result: - * + * *
      * radius size 1
      * radius size 2
@@ -1271,21 +1278,21 @@ public static List getMultiLang(String key) {
      * Gets all translation components from a multi lang's sub-keys. Supports additional arguments for the translation
      * components.
* E.g., given a multi lang: - * + * *
      * multiLang(provider, "terminal.fluid_prospector.tier", "radius size 1", "radius size 2", "radius size 3");
      * 
- * + * * The following code can be used to print out the translations: - * + * *
      * for (var component : getMultiLang("terminal.fluid_prospector.tier")) {
      *     System.out.println(component.getString());
      * }
      * 
- * + * * Result: - * + * *
      * radius size 1
      * radius size 2
@@ -1348,13 +1355,13 @@ public static MutableComponent getFromMultiLang(String key, int index, Object...
      * Adds one key-value-pair to the given lang provider per line in the given multiline (a multiline is a String
      * containing newline characters).
* Example: - * + * *
      * multilineLang(provider, "gtceu.gui.overclock.enabled", "Overclocking Enabled.\nClick to Disable");
      * 
- * + * * This results in the following translations:
- * + * *
      * "gtceu.gui.overclock.enabled.0": "Overclocking Enabled.",
      * "gtceu.gui.overclock.enabled.1": "Click to Disable",
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java
index ee461c4b2b..3490a81838 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/CraftingRecipeLoader.java
@@ -202,6 +202,8 @@ public static void init(Consumer provider) {
         VanillaRecipeHelper.addStrictShapedRecipe(provider, "shape_extruder_rotor", SHAPE_EXTRUDER_ROTOR.asStack(),
                 "   ", " S ", "x  ", 'S', SHAPE_EMPTY.asStack());
 
+        VanillaRecipeHelper.addStrictShapedRecipe(provider, "shape_mold_pill", SHAPE_MOLD_PILL.asStack(), "  h",
+                "  S", "   ", 'S', SHAPE_EMPTY.asStack());
         VanillaRecipeHelper.addStrictShapedRecipe(provider, "shape_mold_rotor", SHAPE_MOLD_ROTOR.asStack(), "  h",
                 " S ", "   ", 'S', SHAPE_EMPTY.asStack());
         VanillaRecipeHelper.addStrictShapedRecipe(provider, "shape_mold_gear_small", SHAPE_MOLD_GEAR_SMALL.asStack(),
@@ -311,6 +313,11 @@ public static void init(Consumer provider) {
                 "POP", "ESE", 'E', GTItems.EMITTER_LuV.asStack(), 'S', new UnificationEntry(wireGtQuadruple, Osmium),
                 'P', new UnificationEntry(plateDouble, Iridium), 'O', GTItems.ENERGY_LAPOTRONIC_ORB.asStack());
 
+        VanillaRecipeHelper.addShapedRecipe(provider, "face_mask", FACE_MASK.asStack(), "S S", "PPP", 'S', Items.STRING,
+                'P', Items.PAPER);
+        VanillaRecipeHelper.addShapedRecipe(provider, "rubber_gloves", RUBBER_GLOVES.asStack(), "P P", 'P',
+                new UnificationEntry(plate, Rubber));
+
         VanillaRecipeHelper.addShapedRecipe(provider, "powderbarrel", new ItemStack(GTBlocks.POWDERBARREL), "PSP",
                 "GGG", "PGP",
                 'P', new UnificationEntry(plate, Wood),
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MachineRecipeLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MachineRecipeLoader.java
index 742e5d8eac..3b30070b56 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MachineRecipeLoader.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MachineRecipeLoader.java
@@ -11,6 +11,7 @@
 import com.gregtechceu.gtceu.api.machine.multiblock.CleanroomType;
 import com.gregtechceu.gtceu.common.block.StoneBlockType;
 import com.gregtechceu.gtceu.common.data.GTBlocks;
+import com.gregtechceu.gtceu.common.data.GTItems;
 import com.gregtechceu.gtceu.common.data.GTMachines;
 import com.gregtechceu.gtceu.config.ConfigHolder;
 import com.gregtechceu.gtceu.data.recipe.CustomTags;
@@ -452,6 +453,18 @@ private static void registerAssemblerRecipes(Consumer provider)
                 .outputItems(MASK_FILTER)
                 .duration(100).EUt(2).save(provider);
 
+        CANNER_RECIPES.recipeBuilder("pack_paracetamol")
+                .inputItems(dust, Paracetamol, 16)
+                .notConsumable(GTItems.SHAPE_MOLD_PILL)
+                .outputItems(GTItems.PARACETAMOL_PILL.asStack(16))
+                .duration(60).EUt(VA[LV]).save(provider);
+
+        CANNER_RECIPES.recipeBuilder("pack_rad_away")
+                .inputItems(dust, RadAway, 16)
+                .notConsumable(GTItems.SHAPE_MOLD_PILL)
+                .outputItems(GTItems.RAD_AWAY_PILL.asStack(16))
+                .duration(60).EUt(VA[LV]).save(provider);
+
         Material material = Iron;
 
         ASSEMBLER_RECIPES.recipeBuilder("cover_shutter")
@@ -677,6 +690,12 @@ private static void registerAssemblerRecipes(Consumer provider)
                 .outputItems(
                         GTBlocks.CASING_PALLADIUM_SUBSTATION.asStack(ConfigHolder.INSTANCE.recipes.casingsPerCraft))
                 .duration(50).save(provider);
+        ASSEMBLER_RECIPES.recipeBuilder("casing_stainless_evaporation")
+                .inputItems(GTBlocks.CASING_STAINLESS_CLEAN.asStack(1))
+                .inputItems(wireGtDouble, AnnealedCopper, 4)
+                .inputFluids(PolyvinylChloride.getFluid(L * 2))
+                .outputItems(GTBlocks.CASING_STAINLESS_EVAPORATION.asStack(1))
+                .duration(30).EUt(VA[HV]).save(provider);
 
         ASSEMBLER_RECIPES.recipeBuilder("casing_ptfe_inert").EUt(16).inputItems(GTBlocks.CASING_STEEL_SOLID.asStack())
                 .inputFluids(Polytetrafluoroethylene.getFluid(216)).circuitMeta(6)
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MetaTileEntityLoader.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MetaTileEntityLoader.java
index 42fac89706..feb25d0377 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MetaTileEntityLoader.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/misc/MetaTileEntityLoader.java
@@ -567,6 +567,10 @@ public static void init(Consumer provider) {
                 GTMachines.DISTILLATION_TOWER.asStack(), "CBC", "FMF", "CBC", 'M', GTMachines.HULL[HV].asStack(), 'B',
                 new UnificationEntry(TagPrefix.pipeLargeFluid, GTMaterials.StainlessSteel), 'C', CustomTags.EV_CIRCUITS,
                 'F', GTItems.ELECTRIC_PUMP_HV);
+        VanillaRecipeHelper.addShapedRecipe(provider, true, "evaporation_plant",
+                GTMachines.EVAPORATION_PLANT.asStack(), "CBC", "FMF", "CBC", 'M', GTMachines.HULL[HV].asStack(),
+                'B', new UnificationEntry(TagPrefix.wireGtDouble, GTMaterials.Kanthal), 'C', CustomTags.HV_CIRCUITS,
+                'F', GTItems.ELECTRIC_PUMP_HV);
         VanillaRecipeHelper.addShapedRecipe(provider, true, "cracking_unit", GTMachines.CRACKER.asStack(), "CEC", "PHP",
                 "CEC", 'C', GTBlocks.COIL_CUPRONICKEL.asStack(), 'E', GTItems.ELECTRIC_PUMP_HV.asStack(), 'P',
                 CustomTags.HV_CIRCUITS, 'H', GTMachines.HULL[HV].asStack());
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/AntidoteRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/AntidoteRecipes.java
new file mode 100644
index 0000000000..6ace866b71
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/AntidoteRecipes.java
@@ -0,0 +1,181 @@
+package com.gregtechceu.gtceu.data.recipe.serialized.chemistry;
+
+import net.minecraft.data.recipes.FinishedRecipe;
+
+import java.util.function.Consumer;
+
+import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.gregtechceu.gtceu.api.GTValues.LV;
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.dust;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.AceticAcid;
+import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*;
+
+public class AntidoteRecipes {
+
+    public static void init(Consumer provider) {
+        paracetamolProcess(provider);
+        potassiumHydroxideProcess(provider);
+        prussianBlueProcess(provider);
+        dtpaProcess(provider);
+    }
+
+    private static void paracetamolProcess(Consumer provider) {
+        CHEMICAL_RECIPES.recipeBuilder("acetic_anhydride")
+                .inputFluids(Ethenone.getFluid(1000))
+                .inputFluids(AceticAcid.getFluid(1000))
+                .outputFluids(AceticAnhydride.getFluid(1000))
+                .duration(200).EUt(VH[LV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("aminophenol")
+                .inputFluids(Phenol.getFluid(1000))
+                .inputFluids(NitrationMixture.getFluid(1000))
+                .notConsumable(dust, Iron)
+                .outputFluids(AminoPhenol.getFluid(1000))
+                .outputFluids(DilutedSulfuricAcid.getFluid(1000))
+                .duration(300).EUt(VA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("paracetamol")
+                .inputFluids(AceticAnhydride.getFluid(1000))
+                .inputFluids(AminoPhenol.getFluid(1000))
+                .outputItems(dust, Paracetamol, 1)
+                .outputFluids(AceticAcid.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+    }
+
+    private static void potassiumHydroxideProcess(Consumer provider) {
+        CHEMICAL_RECIPES.recipeBuilder("potassium_hydroxide")
+                .inputItems(dust, RockSalt, 2)
+                .inputFluids(Water.getFluid(1000))
+                .outputItems(dust, PotassiumHydroxide, 3)
+                .outputFluids(HydrochloricAcid.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("potassium_iodide")
+                .inputItems(dust, PotassiumHydroxide, 3)
+                .inputItems(dust, Iodine, 1)
+                .outputItems(dust, PotassiumIodide, 1)
+                .outputFluids(Oxygen.getFluid(1000))
+                .outputFluids(Hydrogen.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+    }
+
+    private static void prussianBlueProcess(Consumer provider) {
+        CHEMICAL_RECIPES.recipeBuilder("calcium_hydroxide")
+                .inputItems(dust, Quicklime, 2)
+                .inputFluids(Water.getFluid(1000))
+                .outputItems(dust, CalciumHydroxide, 3)
+                .duration(100).EUt(VHA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("formic_acid")
+                .inputFluids(CarbonDioxide.getFluid(1000))
+                .inputFluids(Water.getFluid(1000))
+                .outputFluids(FormicAcid.getFluid(1000))
+                .outputFluids(Oxygen.getFluid(1000))
+                .duration(100).EUt(VA[LV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("ammonium_formate")
+                .inputFluids(Ammonia.getFluid(1000))
+                .inputFluids(FormicAcid.getFluid(1000))
+                .outputFluids(AmmoniumFormate.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+
+        FLUID_HEATER_RECIPES.recipeBuilder("formamide")
+                .inputFluids(AmmoniumFormate.getFluid(100))
+                .outputFluids(Formamide.getFluid(100))
+                .duration(16).EUt(VA[LV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("potassium_cyanide")
+                .inputItems(dust, PotassiumHydroxide, 3)
+                .inputFluids(Formamide.getFluid(1000))
+                .outputItems(dust, PotassiumCyanide, 3)
+                .outputFluids(Water.getFluid(1000))
+                .duration(100).EUt(VHA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("hydrogen_cyanide")
+                .inputFluids(Methane.getFluid(1000))
+                .inputFluids(Ammonia.getFluid(1000))
+                .inputFluids(Oxygen.getFluid(3000))
+                .notConsumable(dust, Platinum)
+                .outputFluids(HydrogenCyanide.getFluid(1000))
+                .outputFluids(Water.getFluid(3000))
+                .duration(100).EUt(VA[HV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("potassium_carbonate")
+                .inputItems(dust, PotassiumHydroxide, 6)
+                .inputFluids(CarbonDioxide.getFluid(1000))
+                .outputItems(dust, PotassiumCarbonate, 6)
+                .outputFluids(Water.getFluid(1000))
+                .duration(100).EUt(VHA[MV]).save(provider);
+
+        LARGE_CHEMICAL_RECIPES.recipeBuilder("calcium_ferrocyanide")
+                .inputFluids(HydrogenCyanide.getFluid(6000))
+                .inputFluids(Iron2Chloride.getFluid(1000))
+                .inputFluids(Water.getFluid(7000))
+                .inputItems(dust, CalciumHydroxide, 10)
+                .outputItems(dust, CalciumFerrocyanide, 15)
+                .outputFluids(HydrochloricAcid.getFluid(2000))
+                .duration(300).EUt(VA[HV]).save(provider);
+
+        LARGE_CHEMICAL_RECIPES.recipeBuilder("potassium_ferrocyanide")
+                .inputItems(dust, CalciumFerrocyanide, 15)
+                .inputItems(dust, RockSalt, 8)
+                .outputItems(dust, PotassiumFerrocyanide, 17)
+                .outputItems(dust, CalciumHydroxide, 10)
+                .outputFluids(HydrochloricAcid.getFluid(4000))
+                .outputFluids(Water.getFluid(4000))
+                .duration(300).EUt(VA[HV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("prussian_blue")
+                .inputItems(dust, PotassiumFerrocyanide, 51)
+                .inputFluids(Iron3Chloride.getFluid(4000))
+                .outputItems(dust, PrussianBlue, 1)
+                .outputItems(dust, RockSalt, 6)
+                .duration(500).EUt(VA[HV]).save(provider);
+    }
+
+    public static void dtpaProcess(Consumer provider) {
+        CHEMICAL_RECIPES.recipeBuilder("dichloroethane")
+                .inputFluids(Ethylene.getFluid(1000))
+                .inputFluids(Chlorine.getFluid(2000))
+                .notConsumableFluid(Iron3Chloride.getFluid(100))
+                .outputFluids(Dichloroethane.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("diethylenetriamine")
+                .inputFluids(Dichloroethane.getFluid(2000))
+                .inputFluids(Ammonia.getFluid(3000))
+                .outputFluids(Diethylenetriamine.getFluid(1000))
+                .outputFluids(HydrochloricAcid.getFluid(4000))
+                .duration(100).EUt(VA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("formaldehyde")
+                .inputFluids(Methanol.getFluid(1000))
+                .inputFluids(Oxygen.getFluid(1000))
+                .notConsumable(dust, Silver)
+                .outputFluids(Formaldehyde.getFluid(1000))
+                .outputFluids(Water.getFluid(1000))
+                .duration(100).EUt(VA[HV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("glycolonitrile")
+                .inputFluids(Formaldehyde.getFluid(1000))
+                .inputFluids(HydrogenCyanide.getFluid(1000))
+                .outputFluids(Glycolonitrile.getFluid(1000))
+                .duration(100).EUt(VA[MV]).save(provider);
+
+        CHEMICAL_RECIPES.recipeBuilder("diethylenetriamine_pentaacetonitrile")
+                .inputFluids(Diethylenetriamine.getFluid(1000))
+                .inputFluids(Glycolonitrile.getFluid(5000))
+                .outputFluids(DiethylenetriaminePentaacetonitrile.getFluid(1000))
+                .outputFluids(Water.getFluid(5000))
+                .duration(100).EUt(VA[HV]).save(provider);
+
+        LARGE_CHEMICAL_RECIPES.recipeBuilder("diethylenetriaminepentaacetic_acid")
+                .inputItems(dust, SodiumHydroxide, 15)
+                .inputFluids(DiethylenetriaminePentaacetonitrile.getFluid(1000))
+                .inputFluids(Oxygen.getFluid(15000))
+                .outputItems(dust, DiethylenetriaminepentaaceticAcid, 1)
+                .outputItems(dust, SodiumNitrite, 20)
+                .duration(100).EUt(VA[EV]).save(provider);
+    }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/BrineRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/BrineRecipes.java
new file mode 100644
index 0000000000..135ff5772d
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/BrineRecipes.java
@@ -0,0 +1,108 @@
+package com.gregtechceu.gtceu.data.recipe.serialized.chemistry;
+
+import net.minecraft.data.recipes.FinishedRecipe;
+
+import java.util.function.Consumer;
+
+import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.dust;
+import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
+import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*;
+import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.CHEMICAL_RECIPES;
+
+public class BrineRecipes {
+
+    public static void init(Consumer provider) {
+        bromineProcess(provider);
+        iodineProcess(provider);
+    }
+
+    private static void bromineProcess(Consumer provider) {
+        EVAPORATION_RECIPES.recipeBuilder("brine_evaporation")
+                .inputFluids(SaltWater.getFluid(20000))
+                .outputFluids(RawBrine.getFluid(1000))
+                .duration(1000).EUt(VA[HV]).save(provider);
+        FLUID_HEATER_RECIPES.recipeBuilder("brine_heating")
+                .inputFluids(RawBrine.getFluid(1000))
+                .outputFluids(HotBrine.getFluid(1000))
+                .duration(12000).EUt(VA[HV]).save(provider);
+
+        // Main chain
+        CHEMICAL_RECIPES.recipeBuilder("brine_chlorination")
+                .inputFluids(HotBrine.getFluid(1000))
+                .inputFluids(Chlorine.getFluid(1000))
+                .outputFluids(HotChlorinatedBrominatedBrine.getFluid(2000))
+                .duration(100).EUt(VA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("brine_filtration")
+                .inputFluids(HotChlorinatedBrominatedBrine.getFluid(1000))
+                .inputFluids(Chlorine.getFluid(1000))
+                .inputFluids(Steam.getFluid(1000))
+                .outputFluids(HotAlkalineDebrominatedBrine.getFluid(1000))
+                .outputFluids(BrominatedChlorineVapor.getFluid(2000))
+                .duration(300).EUt(VA[HV]).save(provider);
+        FLUID_HEATER_RECIPES.recipeBuilder("brominated_chlorine_vapor_condensation")
+                .inputFluids(BrominatedChlorineVapor.getFluid(1000))
+                .inputFluids(Water.getFluid(1000))
+                .outputFluids(AcidicBromineSolution.getFluid(1000))
+                .outputFluids(Water.getFluid(1000))
+                .duration(200).EUt(VA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("bromine_vapor_concentration")
+                .inputFluids(AcidicBromineSolution.getFluid(1000))
+                .inputFluids(Steam.getFluid(1000))
+                .outputFluids(ConcentratedBromineSolution.getFluid(1000))
+                .outputFluids(AcidicBromineExhaust.getFluid(1000))
+                .duration(100).EUt(VA[HV]).save(provider);
+        DISTILLATION_RECIPES.recipeBuilder("bromine_distillation")
+                .inputFluids(ConcentratedBromineSolution.getFluid(1000))
+                .outputFluids(Chlorine.getFluid(500))
+                .outputFluids(Bromine.getFluid(1000))
+                .duration(500).EUt(VA[HV]).save(provider);
+
+        // byproduct loop
+        CHEMICAL_RECIPES.recipeBuilder("brine_neutralization")
+                .inputFluids(HotAlkalineDebrominatedBrine.getFluid(3000))
+                .outputFluids(Chlorine.getFluid(1000))
+                .outputFluids(HotDebrominatedBrine.getFluid(2000))
+                .duration(100).EUt(VA[HV]).save(provider);
+        FLUID_HEATER_RECIPES.recipeBuilder("debrominated_brine_raw_brine_mixing")
+                .inputFluids(RawBrine.getFluid(1000))
+                .inputFluids(HotDebrominatedBrine.getFluid(1000))
+                .outputFluids(HotBrine.getFluid(1000))
+                .outputFluids(DebrominatedBrine.getFluid(1000))
+                .duration(200).EUt(VA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("acidic_bromine_exhaust_heating")
+                .inputFluids(AcidicBromineExhaust.getFluid(1000))
+                .inputFluids(HotBrine.getFluid(1000))
+                .outputFluids(HotChlorinatedBrominatedBrine.getFluid(1000))
+                .outputFluids(Steam.getFluid(3000))
+                .duration(100).EUt(VA[HV]).save(provider);
+    }
+
+    public static void iodineProcess(Consumer provider) {
+        CHEMICAL_RECIPES.recipeBuilder("brine_acidification")
+                .inputFluids(HotBrine.getFluid(1000))
+                .inputFluids(HydrochloricAcid.getFluid(1000))
+                .outputFluids(HotDebrominatedBrine.getFluid(1000))
+                .outputFluids(DiluteIodineSolution.getFluid(1000))
+                .duration(100).EUt(VHA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("iodine_solution")
+                .inputFluids(DiluteIodineSolution.getFluid(1000))
+                .inputFluids(Chlorine.getFluid(2000))
+                .outputFluids(Iodide.getFluid(1000))
+                .outputFluids(HydrochloricAcid.getFluid(2000))
+                .duration(1000).EUt(VHA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("iodine_solution_reduction")
+                .inputFluids(Iodide.getFluid(1000))
+                .inputFluids(Water.getFluid(2000))
+                .inputFluids(SulfurDioxide.getFluid(1000))
+                .outputFluids(IodineSolution.getFluid(2000))
+                .outputFluids(SulfuricAcid.getFluid(1000))
+                .duration(1000).EUt(VHA[HV]).save(provider);
+        CHEMICAL_RECIPES.recipeBuilder("iodine_solution_reduction")
+                .inputFluids(IodineSolution.getFluid(2000))
+                .inputFluids(Chlorine.getFluid(1000))
+                .outputItems(dust, Iodine, 1)
+                .outputFluids(HydrochloricAcid.getFluid(2000))
+                .duration(1000).EUt(VHA[HV]).save(provider);
+    }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ChemistryRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ChemistryRecipes.java
index 2033f45be1..701b29ead6 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ChemistryRecipes.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ChemistryRecipes.java
@@ -33,6 +33,8 @@ public static void init(Consumer provider) {
         PolymerRecipes.init(provider);
         ReactorRecipes.init(provider);
         SeparationRecipes.init(provider);
+        BrineRecipes.init(provider);
+        AntidoteRecipes.init(provider);
 
         // A Few Random Recipes
         FLUID_HEATER_RECIPES.recipeBuilder("ethenone")
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/MixerRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/MixerRecipes.java
index 0ca77c6dd6..042ec9dbe9 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/MixerRecipes.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/MixerRecipes.java
@@ -578,5 +578,12 @@ public static void init(Consumer provider) {
                 .circuitMeta(4)
                 .outputItems(dust, RutheniumTriniumAmericiumNeutronate, 14)
                 .save(provider);
+
+        MIXER_RECIPES.recipeBuilder("rad_away")
+                .inputItems(dust, PotassiumIodide, 5)
+                .inputItems(dust, PrussianBlue, 3)
+                .inputItems(dust, DiethylenetriaminepentaaceticAcid, 10)
+                .outputItems(dust, RadAway, 48)
+                .duration(60).EUt(VA[HV]).save(provider);
     }
 }
diff --git a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ReactorRecipes.java b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ReactorRecipes.java
index 48f1735082..5b7f0565e0 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ReactorRecipes.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/recipe/serialized/chemistry/ReactorRecipes.java
@@ -16,8 +16,7 @@
 import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.*;
 import static com.gregtechceu.gtceu.common.data.GTItems.GELLED_TOLUENE;
 import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
-import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.CHEMICAL_RECIPES;
-import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.LARGE_CHEMICAL_RECIPES;
+import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.*;
 
 public class ReactorRecipes {
 
@@ -143,6 +142,15 @@ public static void init(Consumer provider) {
                 .duration(400).EUt(VA[LV])
                 .save(provider);
 
+        CHEMICAL_RECIPES.recipeBuilder("iron_2_chloride")
+                .inputFluids(Iron3Chloride.getFluid(2000))
+                .inputFluids(Chlorobenzene.getFluid(1000))
+                .outputFluids(Iron2Chloride.getFluid(2000))
+                .outputFluids(HydrochloricAcid.getFluid(1000))
+                .outputFluids(Dichlorobenzene.getFluid(1000))
+                .duration(400).EUt(VA[MV])
+                .save(provider);
+
         CHEMICAL_RECIPES.recipeBuilder("chloromethane_from_methane")
                 .circuitMeta(3)
                 .inputFluids(Chlorine.getFluid(2000))
diff --git a/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java b/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java
index 11715e1f63..5d04172493 100644
--- a/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java
+++ b/src/main/java/com/gregtechceu/gtceu/forge/ForgeCommonEventListener.java
@@ -4,6 +4,9 @@
 import com.gregtechceu.gtceu.api.GTCEuAPI;
 import com.gregtechceu.gtceu.api.block.MaterialBlock;
 import com.gregtechceu.gtceu.api.block.MetaMachineBlock;
+import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
+import com.gregtechceu.gtceu.api.capability.IHazardEffectTracker;
+import com.gregtechceu.gtceu.api.capability.forge.GTCapability;
 import com.gregtechceu.gtceu.api.capability.forge.compat.EUToFEProvider;
 import com.gregtechceu.gtceu.api.data.tag.TagPrefix;
 import com.gregtechceu.gtceu.api.item.DrumMachineItem;
@@ -11,7 +14,8 @@
 import com.gregtechceu.gtceu.api.item.TagPrefixItem;
 import com.gregtechceu.gtceu.api.item.armor.ArmorComponentItem;
 import com.gregtechceu.gtceu.api.machine.feature.IInteractedMachine;
-import com.gregtechceu.gtceu.common.ServerCommands;
+import com.gregtechceu.gtceu.common.capability.HazardEffectTracker;
+import com.gregtechceu.gtceu.common.commands.ServerCommands;
 import com.gregtechceu.gtceu.common.data.GTBlocks;
 import com.gregtechceu.gtceu.common.data.GTItems;
 import com.gregtechceu.gtceu.data.loader.BedrockOreLoader;
@@ -21,13 +25,17 @@
 
 import net.minecraft.core.Direction;
 import net.minecraft.core.registries.Registries;
+import net.minecraft.nbt.CompoundTag;
 import net.minecraft.server.level.ServerLevel;
 import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.level.block.entity.BlockEntity;
 import net.minecraftforge.common.capabilities.Capability;
 import net.minecraftforge.common.capabilities.ICapabilityProvider;
+import net.minecraftforge.common.capabilities.ICapabilitySerializable;
 import net.minecraftforge.common.util.LazyOptional;
 import net.minecraftforge.event.AddReloadListenerEvent;
 import net.minecraftforge.event.AttachCapabilitiesEvent;
@@ -38,6 +46,7 @@
 import net.minecraftforge.event.level.LevelEvent;
 import net.minecraftforge.eventbus.api.EventPriority;
 import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.LogicalSide;
 import net.minecraftforge.fml.common.Mod;
 import net.minecraftforge.registries.MissingMappingsEvent;
 
@@ -62,7 +71,6 @@ public class ForgeCommonEventListener {
     @SubscribeEvent
     public static void registerItemStackCapabilities(AttachCapabilitiesEvent event) {
         if (event.getObject().getItem() instanceof IComponentItem componentItem) {
-
             final ItemStack itemStack = event.getObject();
             event.addCapability(GTCEu.id("capability"), new ICapabilityProvider() {
 
@@ -86,6 +94,49 @@ public  LazyOptional getCapability(@NotNull Capability cap, @Nullable D
         }
     }
 
+    @SubscribeEvent
+    public static void registerEntityCapabilities(AttachCapabilitiesEvent event) {
+        if (event.getObject() instanceof Player entity) {
+            final HazardEffectTracker tracker = new HazardEffectTracker(entity);
+            event.addCapability(GTCEu.id("hazard_tracker"), new ICapabilitySerializable() {
+
+                @Override
+                public CompoundTag serializeNBT() {
+                    return tracker.serializeNBT();
+                }
+
+                @Override
+                public void deserializeNBT(CompoundTag arg) {
+                    tracker.deserializeNBT(arg);
+                }
+
+                @Override
+                public @NotNull  LazyOptional getCapability(@NotNull Capability capability,
+                                                                  @Nullable Direction arg) {
+                    return GTCapability.CAPABILITY_HAZARD_EFFECT_TRACKER.orEmpty(capability,
+                            LazyOptional.of(() -> tracker));
+                }
+            });
+        }
+    }
+
+    @SubscribeEvent
+    public static void attachCapabilities(AttachCapabilitiesEvent event) {
+        event.addCapability(GTCEu.id("fe_capability"), new EUToFEProvider(event.getObject()));
+    }
+
+    @SubscribeEvent
+    public static void tickPlayerInventoryHazards(TickEvent.PlayerTickEvent event) {
+        if (event.side == LogicalSide.CLIENT || event.phase != TickEvent.Phase.END) {
+            return;
+        }
+        Player player = event.player;
+        IHazardEffectTracker tracker = GTCapabilityHelper.getHazardEffectTracker(player);
+        if (tracker != null) {
+            tracker.tick();
+        }
+    }
+
     @SubscribeEvent
     public static void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) {
         var blockState = event.getLevel().getBlockState(event.getPos());
@@ -110,14 +161,9 @@ public static void registerReloadListeners(AddReloadListenerEvent event) {
         event.addListener(new BedrockOreLoader());
     }
 
-    @SubscribeEvent
-    public static void attachCapabilities(AttachCapabilitiesEvent event) {
-        event.addCapability(GTCEu.id("fe_capability"), new EUToFEProvider(event.getObject()));
-    }
-
     @SubscribeEvent
     public static void levelTick(TickEvent.LevelTickEvent event) {
-        if (event.level instanceof ServerLevel serverLevel && event.phase.equals(TickEvent.Phase.END)) {
+        if (event.phase == TickEvent.Phase.END && event.level instanceof ServerLevel serverLevel) {
             TaskHandler.onTickUpdate(serverLevel);
         }
     }
diff --git a/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java
index a81332dd86..74fa817d2f 100644
--- a/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java
+++ b/src/main/java/com/gregtechceu/gtceu/integration/emi/GTEMIPlugin.java
@@ -51,7 +51,7 @@ public void register(EmiRegistry registry) {
             }
         }
         registry.addRecipeHandler(ModularUIContainer.MENUTYPE, new GTEmiRecipeHandler());
-        if(GTCEu.isAE2Loaded()) {
+        if (GTCEu.isAE2Loaded()) {
             registry.addRecipeHandler(PatternEncodingTermMenu.TYPE, new Ae2PatternTerminalHandler<>());
         }
         if (LDLib.isModLoaded(GTValues.MODID_AE2WTLIB)) {
diff --git a/src/main/java/com/gregtechceu/gtceu/integration/emi/recipe/Ae2PatternTerminalHandler.java b/src/main/java/com/gregtechceu/gtceu/integration/emi/recipe/Ae2PatternTerminalHandler.java
index 3f39316cd9..0f6057453e 100644
--- a/src/main/java/com/gregtechceu/gtceu/integration/emi/recipe/Ae2PatternTerminalHandler.java
+++ b/src/main/java/com/gregtechceu/gtceu/integration/emi/recipe/Ae2PatternTerminalHandler.java
@@ -86,5 +86,4 @@ private static GenericStack fromEmiStack(EmiStack stack, long amount) {
         }
         return new GenericStack(AEItemKey.of(ItemStack.EMPTY), 0);
     }
-
 }
diff --git a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java
index bf313a29b4..d672103a44 100644
--- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java
+++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java
@@ -11,6 +11,7 @@
 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.HazardProperty;
 import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey;
 import com.gregtechceu.gtceu.api.data.chemical.material.properties.ToolProperty;
 import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack;
@@ -203,6 +204,7 @@ public void registerBindings(BindingsEvent event) {
         event.add("GTFluidState", FluidState.class);
         event.add("PropertyKey", PropertyKey.class);
         event.add("ToolProperty", ToolProperty.class);
+        event.add("HazardProperty", HazardProperty.class);
         event.add("CleanroomType", CleanroomType.class);
         event.add("ChemicalHelper", ChemicalHelper.class);
 
diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
index afcbafbf45..3efaf680bb 100644
--- a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
+++ b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
@@ -2,11 +2,9 @@
 
 import com.gregtechceu.gtceu.api.GTValues;
 import com.gregtechceu.gtceu.api.data.chemical.material.Material;
-import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty;
 import com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey;
 import com.gregtechceu.gtceu.api.data.tag.TagPrefix;
 import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys;
-import com.gregtechceu.gtceu.common.data.GTDamageTypes;
 import com.gregtechceu.gtceu.config.ConfigHolder;
 import com.gregtechceu.gtceu.data.recipe.CustomTags;
 
@@ -23,7 +21,6 @@
 import net.minecraft.network.chat.Component;
 import net.minecraft.tags.BiomeTags;
 import net.minecraft.util.RandomSource;
-import net.minecraft.world.entity.LivingEntity;
 import net.minecraft.world.item.DyeColor;
 import net.minecraft.world.item.Item;
 import net.minecraft.world.item.ItemStack;
@@ -46,7 +43,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.function.Supplier;
 
 import static com.gregtechceu.gtceu.api.data.chemical.material.properties.PropertyKey.HAZARD;
 
@@ -434,19 +430,4 @@ public static void appendHazardTooltips(Material material, List toolt
         }
         tooltipComponents.add(Component.translatable("gtceu.hazard.description"));
     }
-
-    public static void applyHazardEffects(Material material, LivingEntity livingEntity, Supplier condition) {
-        if (!ConfigHolder.INSTANCE.gameplay.hazardsEnabled || !material.hasProperty(HAZARD) || !condition.get()) return;
-
-        HazardProperty poisonProperty = material.getProperty(HAZARD);
-
-        if (poisonProperty.getHazardType().getProtectionType().isProtected(livingEntity)) return; // entity has proper
-                                                                                                  // safety equipment
-        if (poisonProperty.getDamage() != null &&
-                livingEntity.tickCount % (20 * poisonProperty.getDamage().delay()) == 0)
-            livingEntity.hurt(GTDamageTypes.CHEMICAL.source(livingEntity.level()), poisonProperty.getDamage().damage());
-
-        if (poisonProperty.getEffect() != null)
-            poisonProperty.getEffect().apply(livingEntity);
-    }
 }
diff --git a/src/main/resources/assets/gtceu/textures/armor/bad_hazmat_1.png b/src/main/resources/assets/gtceu/textures/armor/bad_hazmat_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b1c6395c541c2241d47a7308fe4b9e793c5f2a9
GIT binary patch
literal 8399
zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQfx`y?k)_GAh>tdt5rY|&H|6f
zVg?31We{epSZZGe6l5>)^mS!_!79zC!J(j>ZVVKXEOCt}an8@pP0cG|a4t$sEJ;mK
zD9+_^)NpRlF?ut`IN
zU}9ooU}k0pyY}zjza+bwiDVtaOv8{*0igK!^XCsZ3;g@{Zdu}10$1Wr
z5clFra3L!G0a3wGncJE6woQ{X@pKedrnG5Kzweyyd?yc2o;ci&Rz(P*cJIjKDcDDv
zTLkcY^!V~_*yN2P=WZdib$xT=yHEGsh9K|vj!*Gf+K$#QnSJ(TIfPdBr_S~dUB7yD
z=2{;ex;b;9KXYl~&XxY%6|V)4CWYcR&7srCQmJ;J#8
zRXgOpr+_|vbcMC`_ryugmX3Cf$_WV|l2>(0Qp$wYMVhOjGH>5y6moz0S-$^}Zdn^U
zT-jfRwjS~^f+@j?M*+?Tx&8Dl-?hC9V7gd~?3ifj4bwx?{hF0yBV8#(;cBgo5K%sy
zFO%;Z?aSIxkk=4EN#%@}%N$=iIujgjD^1j
z2?t0gPz
z&Cr0P#!l!G`fHECFujy9B}i8~FLQ)kKuD3pr2>qcYs_c}fDS3P#ny<-
zXoQd`ju@i=4uYnKhR}_g_NCxuk*D)>gSo_78<0jifNWjE+`whQ$X`h^?nnmGl`3+m
zUKAyeqc{$EsFXquan5BJjCEkji%n~lmByv%Kr_|?k12}dsIHwc3Vf+`g{gxgW^tg6
zOO>{ns_Wq#kBATwGc-)*ZKc6RYn%`v)hQgL*+l&v+`>?O{F-kvFFKNdXpq-2j)HpU
zp|Y)g6b5fUXFIob8%aRr%x~S?9_>gljZr+vj2Fle3}o*7cuZ#pB^;!dzyJn+{Hr$$
qaH_mdA;F&orD6U1gm;L5vjD!hZO`lduXgNh0KKUblg|&HfAAZHhh7^1

literal 0
HcmV?d00001

diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta
new file mode 100644
index 0000000000..53b118fbef
--- /dev/null
+++ b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation.png.mcmeta
@@ -0,0 +1,5 @@
+{
+    "ldlib": {
+        "connection": "gtceu:block/casings/solid/machine_casing_stainless_evaporation_ctm"
+    }
+}
diff --git a/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation_ctm.png b/src/main/resources/assets/gtceu/textures/block/casings/solid/machine_casing_stainless_evaporation_ctm.png
new file mode 100644
index 0000000000000000000000000000000000000000..96ea407376cbef6f38378adfa90e9337821cbea9
GIT binary patch
literal 3249
zcmbVOTWB4}8Qz_lz0F?EIXaS#Y(`w$2u$OH@~PbCkD38baP351YRr?wT}bBuVzlkwZVi??UnE1g)6qyoDd**GGQ*TS0iD0;;GZC($l{=^|RGeKVSI6FIRuD
zu)Ol@iRb_1)FjDzVCB%k=Z@I&f^~Huzp=K)7*kaht7Tb6o98(?XtOL+7^9RHQ-q90
zqd1Pgc>8xxEIEwG!S_xFN;Q|s7Cff7=o%lrCer-xS3DSJ-?{&O-}l?So?#dZb91ii
zDvBb6@H}s3X2vwlZnq0Se=tbXloEOI;4}RT=Tlu*?ehG-`K@?vc#SK`r$k@cPuD*o
z*!$J%*Uy|eQ*j(q*MSyE5(WVr!}|C@y*5Fhacz4?{Gi`^|Du~`
z2_+IiG~y&VdGaJYAsVetM>h!gRtrmPYH#ZTw!EhJ^0b+%bVhyh*Sx4tw
z=FZ-G=C15}#k#KFx^)Y2_iWp;EL>^5ULOPjPNr!Z0N4uL5E&QF
zh=MWwW~1Q^hFkEO!mxnrlrW=kFeVA^5CK_S1WTnPN#F$zuwR@BBk(;Oz*oQ&mS(Krx6$W}2+%{{xS-
zDmEh*iHx+6rza*5U&Nv3dG(ErAPoI5)Kyh649o^`j23r*aDfZxtM*Ks-_pkTdSeSd
zOcEU!CNsT6_xo*FY?Q=~7OlaEeMgtwKv@g^?kAh&B
zitTt+VO-&q5s)p*C1j3*2|8&UHtRQK
zbLMV%f1*_2@-!(zgsiajZ8+O(HnA>8p82g{=#6}z
zk`U2OXc_i|f~q9y{igN{xCw
z78w%lk^Qz_uAqdVnr^{Q*w*bEpFO^0D|||1ml+t@Y&H@7W~T$YDA8afm^y9|9Nau=
zbs|JzJxSs;AGtTc!fv+{uv{QyU&n{Tfk_As8uhQGSLMu2kX!SEIfW>fx+SJ58wOf+Th81krz@(
zE{#)MW~xl+NVDXB{e6k+jsZW
zYLE?F4=$`yE^pK~I;}?P_ax{+ny`UfDo<1biCg7D52p7+s7!39Io5+#Ytxs#NDV^4
zc`1{NO_VE@FjFnZL6*+W-m^^)`mP^^L1yv_@T?#mW!$oLgBN*z52i5c
z_ItQGyk|fd6jCV_w#iYHAg!21)pQIUg)fXkRFtpq?M?^pjl1aq^us_28RHq=kwL3q
z1-LzU)2l!poG~
z(2vP#HHl-0Hd1{6J&(d^PT%{>=`o(gBAAU`+4kj6N
uu$VrvoS@{PKm{z@K@a4y9=!AJ?fcHY{L=^L7ta?~R}LRPbndB>fBr9w=B5My

literal 0
HcmV?d00001

diff --git a/src/main/resources/assets/gtceu/textures/item/face_mask.png b/src/main/resources/assets/gtceu/textures/item/face_mask.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab59647b4a668e9d867a225db78841eb25263017
GIT binary patch
literal 1203
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)0<%xOdj8RX`EW0*}aI
z1_nK45N51cYF`EvWH0gbb!C6SD$S>5b?Z=wAy7!N#5JPCIX^cyHLrxhxhOTUBsE2$
zJhLQ2!QIn0AiR-JoPmKw+SA1`#6pl!faU#fpq^1cX$UalGC)a5=|8gEy?gg?szp}E
z0MdxA8KeN0IEH2v0W2JJ!c}*5j~)%+dH@Z&xk8GJ%&97FykOb(QrN?M_&@MKr3^VCNU^Stcr)dVNjV2M_ii
zUDe#Zc^%)nCWRl2kKR03@(O7vq`+b+9|(NZ}*>LJKt=W4*G_sp!vx`VYIKH=CHgRBIJ-cyM%^{jr7zdKdC;efz#Kce_8sf8&CsrGLMQ
z8GQGw+PvDezhPnSgGakopR7Lcl+WPP67RMr9(A*vR_c
z&H|6fVg?3oArNM~bhqvgP>{XE)7O>#1*;6ZI-^hGfjkBV7HLlx#}EraMgf-hzd_nZ
z!9a%qBQ^&-xU%~{vbchdD^_(NHB86~L2R(*zuy=bknn@!6HyFA)`Qh#bPWoY`B>E<
e8#Kxu(joBWyI9%sORtWCJmKl;=d#Wzp$Pzt^7oSf

literal 0
HcmV?d00001

diff --git a/src/main/resources/assets/gtceu/textures/item/pill_casting_mold.png b/src/main/resources/assets/gtceu/textures/item/pill_casting_mold.png
new file mode 100644
index 0000000000000000000000000000000000000000..fde142fa8a13d4fcd259b047597edaaa388536fb
GIT binary patch
literal 5233
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