diff --git a/injected_interfaces/interfaces.json b/injected_interfaces/interfaces.json
index 9704941a618..1ab154b3032 100644
--- a/injected_interfaces/interfaces.json
+++ b/injected_interfaces/interfaces.json
@@ -1,5 +1,9 @@
{
"net/minecraft/client/renderer/block/model/BakedQuad": [
"com/gregtechceu/gtceu/core/IGTBakedQuad"
+ ],
+ "net/minecraft/world/entity/Entity": [
+ "com/gregtechceu/gtceu/core/IFireImmuneEntity",
+ "com/gregtechceu/gtceu/core/IBreathingEntity"
]
}
diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json
index 892d9e3836c..bf0a7e5ea8e 100644
--- a/src/generated/resources/assets/gtceu/lang/en_ud.json
+++ b/src/generated/resources/assets/gtceu/lang/en_ud.json
@@ -1737,10 +1737,22 @@
"command.gtceu.cape.use.success": "%s ǝdɐɔ buısn ʍou sı %s",
"command.gtceu.cape.use.success.none": "ǝdɐɔ ɐ buısn ɹǝbuoן ou sı %s",
"command.gtceu.dump_data.success": "%s oʇ %s ʎɹʇsıbǝɹ ɯoɹɟ sǝɔɹnosǝɹ %s pǝdɯnᗡ",
- "command.gtceu.medical_condition.get": ":suoıʇıpuoɔ ןɐɔıpǝɯ ǝsǝɥʇ sɐɥ %s ɹǝʎɐןԀ",
- "command.gtceu.medical_condition.get.element": "spuoɔǝs %s sǝʇnuıɯ %s :ɹ§%s uoıʇıpuoƆ",
- "command.gtceu.medical_condition.get.element.permanent": ")ʇuǝuɐɯɹǝd( spuoɔǝs %s sǝʇnuıɯ %s :ɹ§%s uoıʇıpuoƆ",
- "command.gtceu.medical_condition.get.empty": "˙suoıʇıpuoɔ ןɐɔıpǝɯ ou sɐɥ %s ɹǝʎɐןԀ",
+ "command.gtceu.medical_condition.clear.everything.failed": "ǝʌoɯǝɹ oʇ suoıʇıpuoɔ ou sɐɥ ʇǝbɹɐ⟘",
+ "command.gtceu.medical_condition.clear.everything.success.multiple": "sʇǝbɹɐʇ %s ɯoɹɟ suoıʇıpuoɔ ןןɐ pǝʌoɯǝᴚ",
+ "command.gtceu.medical_condition.clear.everything.success.single": "%s ɯoɹɟ suoıʇıpuoɔ ןןɐ pǝʌoɯǝᴚ",
+ "command.gtceu.medical_condition.clear.specific.failed": "uoıʇıpuoɔ pǝʇsǝnbǝɹ ǝɥʇ ǝʌɐɥ ʇ,usǝop ʇǝbɹɐ⟘",
+ "command.gtceu.medical_condition.clear.specific.success.multiple": "sʇǝbɹɐʇ %s ɯoɹɟ %s pǝʌoɯǝᴚ",
+ "command.gtceu.medical_condition.clear.specific.success.single": "%s ɯoɹɟ %s pǝʌoɯǝᴚ",
+ "command.gtceu.medical_condition.get": "sɐɥ %s",
+ "command.gtceu.medical_condition.get.element": "spuoɔǝs %s sǝʇnuıɯ %s ɹoɟ %s -",
+ "command.gtceu.medical_condition.get.element.permanent": ")ʇuǝuɐɯɹǝd( spuoɔǝs %s sǝʇnuıɯ %s ɹoɟ %s -",
+ "command.gtceu.medical_condition.get.empty": "˙ʎɥʇןɐǝɥ ʎןʇɔǝɟɹǝd sı %s",
+ "command.gtceu.medical_condition.get.symptoms": ":sɯoʇdɯʎs ǝsǝɥʇ sɐɥ %s ʎןʇuǝɹɹnƆ",
+ "command.gtceu.medical_condition.get.symptoms.element": "%s -",
+ "command.gtceu.medical_condition.get.symptoms.empty": "˙sɯoʇdɯʎs ou sɐɥ %s",
+ "command.gtceu.medical_condition.give.failed": ")ʇǝbɹɐʇ pıןɐʌuı( uoıʇıpuoɔ sıɥʇ ʎןddɐ oʇ ǝןqɐu∩",
+ "command.gtceu.medical_condition.give.success.multiple": "sʇǝbɹɐʇ %s oʇ %s pǝıןddⱯ",
+ "command.gtceu.medical_condition.give.success.single": "%s oʇ %s pǝıןddⱯ",
"command.gtceu.place_vein.failure": "%s uoıʇısod ʇɐ %s uıǝʌ ǝɔɐןd oʇ pǝןıɐℲ",
"command.gtceu.place_vein.success": "%s uoıʇısod ʇɐ %s uıǝʌ pǝɔɐןԀ",
"command.gtceu.share_prospection_data.notification": "¡noʎ ɥʇıʍ ɐʇɐp buıʇɔǝdsoɹd buıɹɐɥs sı %s",
@@ -1751,6 +1763,7 @@
"config.gtceu.option.animationTime": "ǝɯı⟘uoıʇɐɯıuɐ",
"config.gtceu.option.arcRecyclingYield": "pןǝıʎbuıןɔʎɔǝᴚɔɹɐ",
"config.gtceu.option.armorHud": "pnHɹoɯɹɐ",
+ "config.gtceu.option.autoRebuildResources": "sǝɔɹnosǝᴚpןınqǝᴚoʇnɐ",
"config.gtceu.option.batchDuration": "uoıʇɐɹnᗡɥɔʇɐq",
"config.gtceu.option.bedrockOreDistance": "ǝɔuɐʇsıᗡǝɹOʞɔoɹpǝq",
"config.gtceu.option.bedrockOreDropTagPrefix": "xıɟǝɹԀbɐ⟘doɹᗡǝɹOʞɔoɹpǝq",
@@ -2162,11 +2175,11 @@
"death.attack.gtceu.medical_condition/chemical_burns": "ʇuǝpıɔɔɐ ןɐɔıɯǝɥɔ ɐ pɐɥ %s",
"death.attack.gtceu.medical_condition/irritant": "ɥsɐɹ pɐq ɹ§ʎꞀꞀⱯƎᴚן§u§ ɐ ʇob %s",
"death.attack.gtceu.medical_condition/methanol_poisoning": "uoıʇıqıɥoɹd ǝɥʇ buıɹnp ǝuıɥsuooɯ ʞuıɹp oʇ pǝıɹʇ %s",
- "death.attack.gtceu.medical_condition/nausea": "ɐǝsnɐu ɟo pǝıp %s",
+ "death.attack.gtceu.medical_condition/nausea": "ɐǝsnɐu oʇ pǝqɯnɔɔns %s",
"death.attack.gtceu.medical_condition/none": "¿buıɥʇou ˙˙˙ɟo pǝıp %s",
"death.attack.gtceu.medical_condition/poison": "snouosıod 'ʇɔɐɟ uı 'ǝɹɐ sןɐıɹǝʇɐɯ snouosıod ʇɐɥʇ ʇobɹoɟ %s",
- "death.attack.gtceu.medical_condition/silicosis": "˙sısoɔıןıs sɐʍ ʇı ˙sısoןnɔɹǝqnʇ ɟo ǝıp ʇ,upıp %s",
- "death.attack.gtceu.medical_condition/weak_poison": ")¡ʎɹnɔɹǝɯ ɹo( pɐǝן ǝʇɐ %s",
+ "death.attack.gtceu.medical_condition/silicosis": "sısoɔıןıs sɐʍ ʇI ˙sısoןnɔɹǝqnʇ ɟo ǝıp ʇ,upıp %s",
+ "death.attack.gtceu.medical_condition/weak_poison": "pɐǝן ǝʇɐ %s",
"death.attack.gtceu.mining_hammer": "%s ʎq ǝɹO ɹoɟ uǝʞɐʇsıɯ sɐʍ %s",
"death.attack.gtceu.mortar": "%s ʎq ʇsnp oʇ punoɹb sɐʍ %s",
"death.attack.gtceu.pickaxe": "%s ʎq pǝuıɯ ʇob %s",
@@ -2295,6 +2308,8 @@
"gtceu.creative_tooltip.3": "sıɥʇ ǝsn oʇ ㄥ§",
"gtceu.cutter": "ɹǝʇʇnƆ",
"gtceu.debug.f3_h.enabled": "ǝɹoɯ ǝǝs oʇ ǝןıɟ bıɟuoɔ ɥɔǝ⟘bǝɹ⅁ ǝɥʇ uı uoıʇdo bıɟuoɔ bnqǝp:ɔsıɯ ǝɥʇ ǝןqɐuǝ :sɹǝdoןǝʌǝᗡ ɹoℲ ¡oɟuı bnqǝp ǝɥʇ pǝıɟıpoɯ sɐɥ ɥɔǝ⟘bǝɹ⅁",
+ "gtceu.debug.resource_rebuild.done": "%s uı ǝuop pןınqǝɹ ǝɔɹnosǝɹ ǝןpɐɹ⅁",
+ "gtceu.debug.resource_rebuild.start": ")sǝɔɹnosǝᴚssǝɔoɹd: ʍǝןpɐɹb/˙( pןınqǝɹ ǝɔɹnosǝɹ ǝןpɐɹb buıʞoʌuI",
"gtceu.direction.tooltip.back": "ʞɔɐᗺ",
"gtceu.direction.tooltip.down": "uʍoᗡ",
"gtceu.direction.tooltip.front": "ʇuoɹℲ",
@@ -2492,12 +2507,6 @@
"gtceu.gui.toggle_view.disabled": ")spınןℲ( ʍǝıΛ ǝןbbo⟘",
"gtceu.gui.toggle_view.enabled": ")sɯǝʇI( ʍǝıΛ ǝןbbo⟘",
"gtceu.gui.waiting_list": ":ǝnǝnὉ buıpuǝS",
- "gtceu.hazard_trigger.any": "ʇɔɐʇuoɔ ʎuⱯ",
- "gtceu.hazard_trigger.description": ":ʎq pǝsnɐƆ",
- "gtceu.hazard_trigger.inhalation": "uoıʇɐןɐɥuI",
- "gtceu.hazard_trigger.none": "buıɥʇoN",
- "gtceu.hazard_trigger.protection.description": ":ɯoɹɟ sʇɔǝʇoɹԀ",
- "gtceu.hazard_trigger.skin_contact": "ʇɔɐʇuoɔ uıʞS",
"gtceu.implosion_compressor": "ɹossǝɹdɯoƆ uoısoןdɯI",
"gtceu.io.both": "ɥʇoᗺ",
"gtceu.io.export": "ʇɹodxƎ",
@@ -3253,25 +3262,6 @@
"gtceu.maintenance.configurable_time": "xɟ% :ǝɯı⟘",
"gtceu.maintenance.configurable_time.changed_description": "˙ǝʇɐɹ ןɐɯɹou ǝɥʇ xɟ% ʇɐ ɹnɔɔo ןןıʍ sɯǝןqoɹd ǝɔuɐuǝʇuıɐW",
"gtceu.maintenance.configurable_time.unchanged_description": "˙ǝʇɐpdn oʇ uoıʇɐɹnbıɟuoɔ ǝbuɐɥƆ ˙ǝʇɐɹ ןɐɯɹou ʇɐ ɹnɔɔo ןןıʍ sɯǝןqoɹd ǝɔuɐuǝʇuıɐW",
- "gtceu.medical_condition.antidote.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ ǝʇopıʇuⱯɐ§",
- "gtceu.medical_condition.antidote.description.effect_removed": "sʇɔǝɟɟǝ ,suoıʇıpuoɔ ʇuǝɹɹnɔ ɟo %s%% sǝʌoɯǝᴚ",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "sʇɔǝɟɟǝ ,suoıʇıpuoɔ ʇuǝɹɹnɔ ɟo ןןɐ sǝʌoɯǝᴚ",
- "gtceu.medical_condition.antidote.description_shift": ":suoıʇıpuoɔ ǝsǝɥʇ sǝɹnƆɐ§",
- "gtceu.medical_condition.arsenicosis": "sısoɔıuǝsɹⱯq§",
- "gtceu.medical_condition.asbestosis": "sısoʇsǝqsⱯp§",
- "gtceu.medical_condition.berylliosis": "sısoıןןʎɹǝᗺϛ§",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "buıuosıoԀ ǝpıxouoW uoqɹɐƆㄥ§",
- "gtceu.medical_condition.carcinogen": "ɔıuǝbouıɔɹɐƆǝ§",
- "gtceu.medical_condition.chemical_burns": "suɹnq ןɐɔıɯǝɥƆϛ§",
- "gtceu.medical_condition.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ S∩OᗡᴚⱯZⱯHɔ§ן§",
- "gtceu.medical_condition.description_shift": ":S∩OᗡᴚⱯZⱯHɔ§ן§",
- "gtceu.medical_condition.irritant": "ʇuɐʇıɹɹI9§",
- "gtceu.medical_condition.methanol_poisoning": "buıuosıoԀ ןouɐɥʇǝW9§",
- "gtceu.medical_condition.nausea": "buıʇɐǝsnɐNƐ§",
- "gtceu.medical_condition.none": "snoɹǝbuɐᗡ ʇoNᄅ§",
- "gtceu.medical_condition.poison": "snouosıoԀᄅ§",
- "gtceu.medical_condition.silicosis": "sısoɔıןıSƖ§",
- "gtceu.medical_condition.weak_poison": "snouosıod ʎןʞɐǝMɐ§",
"gtceu.minimap.ore_vein.depleted": "pǝʇǝןdǝᗡ",
"gtceu.mixer": "ɹǝxıW",
"gtceu.mode.both": "ɹ§)ɯǝʇI puⱯ pınןℲ( ɥʇoᗺp§",
@@ -3655,6 +3645,9 @@
"gtceu.placeholder_info.if.0": "˙0 oʇ ןɐnbǝ ʇou sı puɐ buıɹʇs ʎʇdɯǝ uɐ ʇou sı ʇı ɟı ǝnɹʇ pǝɹǝpısuoɔ sı uoıʇıpuoɔ ǝɥ⟘ ˙uoıʇıpuoɔ ǝɥʇ uo buıpuǝdǝp sʇuǝɯnbɹɐ ǝɥʇ ɟo ǝuo suɹnʇǝᴚ",
"gtceu.placeholder_info.if.1": ":ǝbɐs∩",
"gtceu.placeholder_info.if.2": "}]ǝsןɐɟ‾ɟı‾pǝuɹnʇǝɹ[ >ǝnɹʇ‾ɟı‾pǝuɹnʇǝɹ< >uoıʇıpuoɔ< ɟı{ ",
+ "gtceu.placeholder_info.item.0": "ʇoןs pǝıɟıɔǝds ɐ uı ɯǝʇı ǝɥʇ ɟo pı puɐ ʇunoɯɐ ǝɥʇ suɹnʇǝᴚ",
+ "gtceu.placeholder_info.item.1": ":ǝbɐs∩",
+ "gtceu.placeholder_info.item.2": ")ǝןdɯɐxǝ ɹoɟ( \"puoɯɐıp:ʇɟɐɹɔǝuıɯ ƖƐ\" >- }>ʇoןs< ɯǝʇı{ ",
"gtceu.placeholder_info.itemCount.0": "˙)pǝɹǝʇןıɟ ǝq uɐɔ( sɯǝʇı ɟo ʇunoɯɐ ǝɥʇ suɹnʇǝᴚ",
"gtceu.placeholder_info.itemCount.1": ":ǝbɐs∩",
"gtceu.placeholder_info.itemCount.2": "ʇunoɯɐ ɯǝʇı ןɐʇoʇ >- }ʇunoƆɯǝʇı{ ",
@@ -3668,6 +3661,9 @@
"gtceu.placeholder_info.maxProgress.1": ",%}00Ɩ * }}ssǝɹboɹԀxɐɯ{ / }ssǝɹboɹd{ ɔןɐɔ{ ɔןɐɔ{ :ssǝɹboɹԀ, :ǝןdɯɐxƎ",
"gtceu.placeholder_info.maxProgress.2": ":ǝbɐs∩",
"gtceu.placeholder_info.maxProgress.3": "ǝdıɔǝɹ buıuunɹ ʎןʇuǝɹɹnɔ ǝɥʇ ɟo ssǝɹboɹd xɐɯ ǝɥʇ >- }ssǝɹboɹԀxɐɯ{ ",
+ "gtceu.placeholder_info.module.0": ")ɹǝʌoɔ ɐ uı ʞɹoʍ ʇou sǝop( ɹoʇıuoɯ ןɐɹʇuǝɔ ǝɥʇ oʇuo ʇoןs pǝıɟıɔǝds ǝɥʇ uı ǝןnpoɯ ǝɥʇ sɹǝpuǝᴚ",
+ "gtceu.placeholder_info.module.1": ":ǝbɐs∩",
+ "gtceu.placeholder_info.module.2": "buıɹʇs ʎʇdɯǝ >- }>ʎ< >x< >ʇoןs< ǝןnpoɯ{ ",
"gtceu.placeholder_info.nbt.0": "ʇoןs pǝıɟıɔǝds ǝɥʇ uı ɯǝʇı ǝɥʇ ɟo ɐʇɐp ʇqu ǝɥʇ suɹnʇǝᴚ",
"gtceu.placeholder_info.nbt.1": ":ǝbɐs∩",
"gtceu.placeholder_info.nbt.2": "]˙˙˙[]Ɛʎǝʞ[]ᄅʎǝʞ[]Ɩʎǝʞ[ʇqu‾ɯǝʇı >- }˙˙˙ ]Ɛʎǝʞ[ ]ᄅʎǝʞ[ ]Ɩʎǝʞ[ >ʇoןs< ʇqu{ ",
@@ -3681,9 +3677,16 @@
"gtceu.placeholder_info.progress.1": "}ssǝɹboɹԀxɐɯ{ puɐ 0 uǝǝʍʇǝq ɹǝbǝʇuı uɐ sı ssǝɹboɹd ʇɐɥʇ ǝʇoN",
"gtceu.placeholder_info.progress.2": ":ǝbɐs∩",
"gtceu.placeholder_info.progress.3": "ǝdıɔǝɹ buıuunɹ ʎןʇuǝɹɹnɔ ǝɥʇ ɟo ssǝɹboɹd ǝɥʇ >- }ssǝɹboɹd{ ",
+ "gtceu.placeholder_info.quad.0": ")sǝɔıʇɹǝʌ ㄣ ןןɐ ɹoɟ sɹǝʇǝɯɐɹɐd ʎɟıɔǝds ʇsnɯ( pɐnb ɐ sʍɐɹᗡ",
+ "gtceu.placeholder_info.quad.1": ":ǝbɐs∩",
+ "gtceu.placeholder_info.quad.2": "buıɹʇs ʎʇdɯǝ >- }>ㄣɹoןoɔ< >Ɛɹoןoɔ< >ᄅɹoןoɔ< >Ɩɹoןoɔ< >ㄣʎ< >ㄣx< >Ɛʎ< >Ɛx< >ᄅʎ< >ᄅx< >Ɩʎ< >Ɩx< pɐnb{ ",
"gtceu.placeholder_info.random.0": "˙)ǝʌısnןɔuı( ןɐʌɹǝʇuı pǝıɟıɔǝds ǝɥʇ uı ɹǝqɯnu ɯopuɐɹ ɐ suɹnʇǝᴚ",
"gtceu.placeholder_info.random.1": ":ǝbɐs∩",
"gtceu.placeholder_info.random.2": ")ǝʌısnןɔuı( xɐɯ puɐ uıɯ uǝǝʍʇǝq ɹǝqɯnu ɯopuɐɹ ɐ >- }>xɐɯ< >uıɯ< ɯopuɐɹ{ ",
+ "gtceu.placeholder_info.rect.0": "ǝzıs puɐ sǝʇɐuıpɹooɔ pǝıɟıɔǝds ǝɥʇ ɥʇıʍ uoıʇısod pǝıɟıɔǝds ǝɥʇ ʇɐ ǝןbuɐʇɔǝɹ ɐ sʍɐɹᗡ",
+ "gtceu.placeholder_info.rect.1": ":ǝbɐs∩",
+ "gtceu.placeholder_info.rect.2": "buıɹʇs ʎʇdɯǝ >- }>ᗺ⅁ᴚⱯɹoןoɔ< >ʇɥbıǝɥ< >ɥʇpıʍ< >ʎ< >x< ʇɔǝɹ{ ",
+ "gtceu.placeholder_info.rect.3": ")Ɩ 'ᄅ( ǝzıs ǝɥʇ ɥʇıʍ )ϛᄅ˙0 'ϛ˙0( ʇɐ ǝןbuɐʇɔǝɹ ǝʇıɥʍ ɐ sʍɐɹp >- }ℲℲℲℲℲℲℲℲx0 Ɩ ᄅ ϛᄅ˙0 ϛ˙0 ʇɔǝɹ{ ",
"gtceu.placeholder_info.redstone.0": "ɥʇbuǝɹʇs ʇndʇno ǝuoʇspǝɹ ǝɥʇ sʇǝs ɹo ɥʇbuǝɹʇs ןɐubıs ǝuoʇspǝɹ ǝɥʇ suɹnʇǝᴚ",
"gtceu.placeholder_info.redstone.1": ":ǝbɐs∩",
"gtceu.placeholder_info.redstone.2": "ǝpıs pǝıɟıɔǝds ǝɥʇ ʇɐ )ϛƖ-0( ɥʇbuǝɹʇs ןɐubıs ǝuoʇspǝɹ >- }>ʇsǝʍ|ʇsɐǝ|ɥʇnos|ɥʇɹou|uʍop|dn< ʇǝb ǝuoʇspǝɹ{ ",
@@ -3696,6 +3699,9 @@
"gtceu.placeholder_info.select.0": ")0 ɯoɹɟ buıʇɹɐʇs( xǝpuı pǝıɟıɔǝds ǝɥʇ ʇɐ ʇuǝɯnbɹɐ ǝɥʇ suɹnʇǝᴚ",
"gtceu.placeholder_info.select.1": ":ǝbɐs∩",
"gtceu.placeholder_info.select.2": "xǝpuı pǝıɟıɔǝds ǝɥʇ ʇɐ ʇuǝɯnbɹɐ >- ˙˙˙ ]Ɛbɹɐ[ ]ᄅbɹɐ[ ]Ɩbɹɐ[ >xǝpuı< ʇɔǝןǝs{ ",
+ "gtceu.placeholder_info.setImage.0": "ʇoןs pǝıɟıɔǝds ǝɥʇ uı ǝןnpoɯ ǝbɐɯı uɐ uı Ꞁᴚ∩ ǝbɐɯı ǝɥʇ sʇǝS",
+ "gtceu.placeholder_info.setImage.1": ":ǝbɐs∩",
+ "gtceu.placeholder_info.setImage.2": "buıɹʇs ʎʇdɯǝ >- }>ןɹn< >ʇoןs< ǝbɐɯIʇǝs{ ",
"gtceu.placeholder_info.strike.0": "ʇno pǝssoɹɔ sɐʍ ʇı ɟı sɐ ʇı buıʎɐןdsıp 'ʇxǝʇ ʇsɹıɟ ǝɥʇ ɯoɹɟ ʇxǝʇ ǝɥʇ suɹnʇǝᴚ",
"gtceu.placeholder_info.strike.1": ":ǝbɐs∩",
"gtceu.placeholder_info.strike.2": "ʇxǝʇ ʇno-pǝssoɹɔ >- }>ʇxǝʇ< ǝʞıɹʇs{ ",
@@ -4789,7 +4795,7 @@
"item.gtceu.tool.behavior.block_rotation": "sʞɔoןᗺ sǝʇɐʇoᴚɟ§ :ɔıuɐɥɔǝWᄅ§",
"item.gtceu.tool.behavior.crop_harvesting": "sdoɹƆ sʇsǝʌɹɐHɟ§ :ɹǝʇsǝʌɹɐHɐ§",
"item.gtceu.tool.behavior.damage_boost": "%s ʇsuıɐbɐ ǝbɐɯɐp ɐɹʇxƎɟ§ :ʇsooᗺ ǝbɐɯɐᗡㄣ§",
- "item.gtceu.tool.behavior.dowse_campfire": "sǝɹıɟdɯɐƆ sǝsʍoᗡɟ§ :ɹǝʇɥbıɟǝɹıℲƖ§",
+ "item.gtceu.tool.behavior.dowse_campfire": "sǝɹıɟdɯɐƆ sǝsʍoᗡɟ§ :ɹǝʇɥbıɟǝɹıℲ9§",
"item.gtceu.tool.behavior.grass_path": "sɥʇɐԀ ssɐɹ⅁ sǝʇɐǝɹƆɟ§ :ɹǝdɐɔspuɐꞀǝ§",
"item.gtceu.tool.behavior.ground_tilling": "punoɹ⅁ sןןı⟘ɟ§ :ɹǝɯɹɐℲǝ§",
"item.gtceu.tool.behavior.plunger": "spınןℲ suıɐɹᗡɟ§ :ɹǝqɯnןԀ6§",
@@ -5687,6 +5693,23 @@
"material.gtceu.zinc_sulfide": "ǝpıɟןnS ɔuıZ",
"material.gtceu.zincite": "ǝʇıɔuıZ",
"material.gtceu.zirconium": "ɯnıuoɔɹıZ",
+ "medical_condition.gtceu.arsenicosis": "sısoɔıuǝsɹⱯq§",
+ "medical_condition.gtceu.asbestosis": "sısoʇsǝqsⱯp§",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "buıuosıoԀ ǝpıxouoW uoqɹɐƆㄥ§",
+ "medical_condition.gtceu.carcinogen": "ɔıuǝbouıɔɹɐƆǝ§",
+ "medical_condition.gtceu.carcinogen.affected": "ɹǝɔuɐƆǝ§",
+ "medical_condition.gtceu.chemical_burns": "suɹnq ןɐɔıɯǝɥƆϛ§",
+ "medical_condition.gtceu.irritant": "ʇuɐʇıɹɹI9§",
+ "medical_condition.gtceu.irritant.affected": "uoıʇɐʇıɹɹI9§",
+ "medical_condition.gtceu.methanol_poisoning": "buıuosıoԀ ןouɐɥʇǝW9§",
+ "medical_condition.gtceu.nausea": "buıʇɐǝsnɐNƐ§",
+ "medical_condition.gtceu.nausea.affected": "ɐǝsnɐNƐ§",
+ "medical_condition.gtceu.none": "snoɹǝbuɐᗡ ʇoNᄅ§",
+ "medical_condition.gtceu.none.affected": "¿buıɥʇoNᄅ§",
+ "medical_condition.gtceu.poison": "snouosıoԀᄅ§",
+ "medical_condition.gtceu.poison.affected": "buıuosıoԀᄅ§",
+ "medical_condition.gtceu.weak_poison": "snouosıod ʎןʞɐǝMɐ§",
+ "medical_condition.gtceu.weak_poison.affected": "buıuosıod ɹouıWɐ§",
"message.gtceu.new_veins.amount": "¡suıǝʌ ʍǝu %d pǝʇɔǝdsoɹԀ",
"message.gtceu.new_veins.name": "¡%s pǝʇɔǝdsoɹԀ",
"metaarmor.energy_share.disable": "pǝןqɐsıp buıbɹɐɥɔ sʇǝbpɐ⅁ :ʎןddnS ʎbɹǝuƎ",
@@ -5809,6 +5832,20 @@
"recipe.condition.rain.tooltip": "%d :ןǝʌǝꞀ uıɐᴚ",
"recipe.condition.steam_vent.tooltip": "ʇuǝʌ ɯɐǝʇs uɐǝןƆ",
"recipe.condition.thunder.tooltip": "%d :ןǝʌǝꞀ ɹǝpunɥ⟘",
+ "symptom.gtceu.air_supply_debuff": "ʎʇıɔɐdɐɔ bunן pǝɹǝʍoꞀ",
+ "symptom.gtceu.blindness": "ssǝupuıןᗺ",
+ "symptom.gtceu.darkness": "ssǝuʞɹɐᗡ",
+ "symptom.gtceu.death": "ɥʇɐǝᗡ",
+ "symptom.gtceu.health_debuff": "ɥʇןɐǝɥ ɯnɯıxɐɯ pǝɹǝʍoꞀ",
+ "symptom.gtceu.hunger": "ǝʇıʇǝddɐ pǝsɐǝɹɔuI",
+ "symptom.gtceu.mining_fatigue": "ǝnbıʇɐℲ",
+ "symptom.gtceu.nausea": "ɐǝsnɐN",
+ "symptom.gtceu.poisoning": "buıuosıoԀ",
+ "symptom.gtceu.random_damage": "ǝbɐɯɐp ןɐuoısɐɔɔO",
+ "symptom.gtceu.slowness": "ssǝuʍoןS",
+ "symptom.gtceu.weak_poisoning": "buıuosıod ʞɐǝM",
+ "symptom.gtceu.weakness": "ssǝuʞɐǝM",
+ "symptom.gtceu.wither": "sısoɹɔǝN",
"tagprefix.andesite": "ǝɹO %s ǝʇısǝpuⱯ",
"tagprefix.basalt": "ǝɹO %s ʇןɐsɐᗺ",
"tagprefix.blackstone": "ǝɹO %s ǝuoʇsʞɔɐןᗺ",
@@ -5920,5 +5957,17 @@
"tile.gtceu.petrified_foam.name": "ɯɐoℲ pǝıɟıɹʇǝԀ",
"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"
+ "tile.gtceu.seal.name": "ʞɔoןᗺ pǝןɐǝS",
+ "tooltip.gtceu.antidote.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ ǝʇopıʇuⱯɐ§",
+ "tooltip.gtceu.antidote.description.effect_removed": "sʇɔǝɟɟǝ ,suoıʇıpuoɔ ʇuǝɹɹnɔ ɟo %s%% sǝʌoɯǝᴚ",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "sʇɔǝɟɟǝ ,suoıʇıpuoɔ ʇuǝɹɹnɔ ɟo ןןɐ sǝʌoɯǝᴚ",
+ "tooltip.gtceu.antidote.description_shift": ":suoıʇıpuoɔ ǝsǝɥʇ sǝɹnƆɐ§",
+ "tooltip.gtceu.hazard_trigger": ":ʎq pǝsnɐƆ",
+ "tooltip.gtceu.hazard_trigger.any": "ʇɔɐʇuoɔ ʎuⱯ",
+ "tooltip.gtceu.hazard_trigger.inhalation": "uoıʇɐןɐɥuI",
+ "tooltip.gtceu.hazard_trigger.none": "buıɥʇoN",
+ "tooltip.gtceu.hazard_trigger.protection": ":ɯoɹɟ sʇɔǝʇoɹԀ",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "ʇɔɐʇuoɔ uıʞS",
+ "tooltip.gtceu.medical_condition.description": "sןıɐʇǝp ʍoɥs oʇ ʇɟıɥS pןoHㄥ§ S∩OᗡᴚⱯZⱯHɔ§ן§",
+ "tooltip.gtceu.medical_condition.description_shift": ":S∩OᗡᴚⱯZⱯHɔ§ן§"
}
\ 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 35d0223ccab..46c94563701 100644
--- a/src/generated/resources/assets/gtceu/lang/en_us.json
+++ b/src/generated/resources/assets/gtceu/lang/en_us.json
@@ -1737,10 +1737,22 @@
"command.gtceu.cape.use.success": "%s is now using cape %s",
"command.gtceu.cape.use.success.none": "%s is no longer using a cape",
"command.gtceu.dump_data.success": "Dumped %s resources from registry %s to %s",
- "command.gtceu.medical_condition.get": "Player %s has these medical conditions:",
- "command.gtceu.medical_condition.get.element": "Condition %s§r: %s minutes %s seconds",
- "command.gtceu.medical_condition.get.element.permanent": "Condition %s§r: %s minutes %s seconds (permanent)",
- "command.gtceu.medical_condition.get.empty": "Player %s has no medical conditions.",
+ "command.gtceu.medical_condition.clear.everything.failed": "Target has no conditions to remove",
+ "command.gtceu.medical_condition.clear.everything.success.multiple": "Removed all conditions from %s targets",
+ "command.gtceu.medical_condition.clear.everything.success.single": "Removed all conditions from %s",
+ "command.gtceu.medical_condition.clear.specific.failed": "Target doesn't have the requested condition",
+ "command.gtceu.medical_condition.clear.specific.success.multiple": "Removed %s from %s targets",
+ "command.gtceu.medical_condition.clear.specific.success.single": "Removed %s from %s",
+ "command.gtceu.medical_condition.get": "%s has",
+ "command.gtceu.medical_condition.get.element": "- %s for %s minutes %s seconds",
+ "command.gtceu.medical_condition.get.element.permanent": "- %s for %s minutes %s seconds (permanent)",
+ "command.gtceu.medical_condition.get.empty": "%s is perfectly healthy.",
+ "command.gtceu.medical_condition.get.symptoms": "Currently %s has these symptoms:",
+ "command.gtceu.medical_condition.get.symptoms.element": "- %s",
+ "command.gtceu.medical_condition.get.symptoms.empty": "%s has no symptoms.",
+ "command.gtceu.medical_condition.give.failed": "Unable to apply this condition (invalid target)",
+ "command.gtceu.medical_condition.give.success.multiple": "Applied %s to %s targets",
+ "command.gtceu.medical_condition.give.success.single": "Applied %s to %s",
"command.gtceu.place_vein.failure": "Failed to place vein %s at position %s",
"command.gtceu.place_vein.success": "Placed vein %s at position %s",
"command.gtceu.share_prospection_data.notification": "%s is sharing prospecting data with you!",
@@ -1751,6 +1763,7 @@
"config.gtceu.option.animationTime": "animationTime",
"config.gtceu.option.arcRecyclingYield": "arcRecyclingYield",
"config.gtceu.option.armorHud": "armorHud",
+ "config.gtceu.option.autoRebuildResources": "autoRebuildResources",
"config.gtceu.option.batchDuration": "batchDuration",
"config.gtceu.option.bedrockOreDistance": "bedrockOreDistance",
"config.gtceu.option.bedrockOreDropTagPrefix": "bedrockOreDropTagPrefix",
@@ -2162,11 +2175,11 @@
"death.attack.gtceu.medical_condition/chemical_burns": "%s had a chemical accident",
"death.attack.gtceu.medical_condition/irritant": "%s got a §n§lREALLY§r bad rash",
"death.attack.gtceu.medical_condition/methanol_poisoning": "%s tried to drink moonshine during the prohibition",
- "death.attack.gtceu.medical_condition/nausea": "%s died of nausea",
+ "death.attack.gtceu.medical_condition/nausea": "%s succumbed to nausea",
"death.attack.gtceu.medical_condition/none": "%s died of... nothing?",
"death.attack.gtceu.medical_condition/poison": "%s forgot that poisonous materials are, in fact, poisonous",
- "death.attack.gtceu.medical_condition/silicosis": "%s didn't die of tuberculosis. it was silicosis.",
- "death.attack.gtceu.medical_condition/weak_poison": "%s ate lead (or mercury!)",
+ "death.attack.gtceu.medical_condition/silicosis": "%s didn't die of tuberculosis. It was silicosis",
+ "death.attack.gtceu.medical_condition/weak_poison": "%s ate lead",
"death.attack.gtceu.mining_hammer": "%s was mistaken for Ore by %s",
"death.attack.gtceu.mortar": "%s was ground to dust by %s",
"death.attack.gtceu.pickaxe": "%s got mined by %s",
@@ -2295,6 +2308,8 @@
"gtceu.creative_tooltip.3": "§7 to use this",
"gtceu.cutter": "Cutter",
"gtceu.debug.f3_h.enabled": "GregTech has modified the debug info! For Developers: enable the misc:debug config option in the GregTech config file to see more",
+ "gtceu.debug.resource_rebuild.done": "Gradle resource rebuild done in %s",
+ "gtceu.debug.resource_rebuild.start": "Invoking gradle resource rebuild (./gradlew :processResources)",
"gtceu.direction.tooltip.back": "Back",
"gtceu.direction.tooltip.down": "Down",
"gtceu.direction.tooltip.front": "Front",
@@ -2492,12 +2507,6 @@
"gtceu.gui.toggle_view.disabled": "Toggle View (Fluids)",
"gtceu.gui.toggle_view.enabled": "Toggle View (Items)",
"gtceu.gui.waiting_list": "Sending Queue:",
- "gtceu.hazard_trigger.any": "Any contact",
- "gtceu.hazard_trigger.description": "Caused by:",
- "gtceu.hazard_trigger.inhalation": "Inhalation",
- "gtceu.hazard_trigger.none": "Nothing",
- "gtceu.hazard_trigger.protection.description": "Protects from:",
- "gtceu.hazard_trigger.skin_contact": "Skin contact",
"gtceu.implosion_compressor": "Implosion Compressor",
"gtceu.io.both": "Both",
"gtceu.io.export": "Export",
@@ -3253,25 +3262,6 @@
"gtceu.maintenance.configurable_time": "Time: %fx",
"gtceu.maintenance.configurable_time.changed_description": "Maintenance problems will occur at %fx the normal rate.",
"gtceu.maintenance.configurable_time.unchanged_description": "Maintenance problems will occur at normal rate. Change configuration to update.",
- "gtceu.medical_condition.antidote.description": "§aAntidote §7Hold Shift to show details",
- "gtceu.medical_condition.antidote.description.effect_removed": "Removes %s%% of current conditions' effects",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "Removes all of current conditions' effects",
- "gtceu.medical_condition.antidote.description_shift": "§aCures these conditions:",
- "gtceu.medical_condition.arsenicosis": "§bArsenicosis",
- "gtceu.medical_condition.asbestosis": "§dAsbestosis",
- "gtceu.medical_condition.berylliosis": "§5Berylliosis",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7Carbon Monoxide Poisoning",
- "gtceu.medical_condition.carcinogen": "§eCarcinogenic",
- "gtceu.medical_condition.chemical_burns": "§5Chemical burns",
- "gtceu.medical_condition.description": "§l§cHAZARDOUS §7Hold Shift to show details",
- "gtceu.medical_condition.description_shift": "§l§cHAZARDOUS:",
- "gtceu.medical_condition.irritant": "§6Irritant",
- "gtceu.medical_condition.methanol_poisoning": "§6Methanol Poisoning",
- "gtceu.medical_condition.nausea": "§3Nauseating",
- "gtceu.medical_condition.none": "§2Not Dangerous",
- "gtceu.medical_condition.poison": "§2Poisonous",
- "gtceu.medical_condition.silicosis": "§1Silicosis",
- "gtceu.medical_condition.weak_poison": "§aWeakly poisonous",
"gtceu.minimap.ore_vein.depleted": "Depleted",
"gtceu.mixer": "Mixer",
"gtceu.mode.both": "§dBoth (Fluid And Item)§r",
@@ -3655,6 +3645,9 @@
"gtceu.placeholder_info.if.0": "Returns one of the arguments depending on the condition. The condition is considered true if it is not an empty string and is not equal to 0.",
"gtceu.placeholder_info.if.1": "Usage:",
"gtceu.placeholder_info.if.2": " {if [returned_if_false]}",
+ "gtceu.placeholder_info.item.0": "Returns the amount and id of the item in a specified slot",
+ "gtceu.placeholder_info.item.1": "Usage:",
+ "gtceu.placeholder_info.item.2": " {item } -> \"31 minecraft:diamond\" (for example)",
"gtceu.placeholder_info.itemCount.0": "Returns the amount of items (can be filtered).",
"gtceu.placeholder_info.itemCount.1": "Usage:",
"gtceu.placeholder_info.itemCount.2": " {itemCount} -> total item amount",
@@ -3668,6 +3661,9 @@
"gtceu.placeholder_info.maxProgress.1": "Example: 'Progress: {calc {calc {progress} / {maxProgress}} * 100}%'",
"gtceu.placeholder_info.maxProgress.2": "Usage:",
"gtceu.placeholder_info.maxProgress.3": " {maxProgress} -> the max progress of the currently running recipe",
+ "gtceu.placeholder_info.module.0": "Renders the module in the specified slot onto the central monitor (does not work in a cover)",
+ "gtceu.placeholder_info.module.1": "Usage:",
+ "gtceu.placeholder_info.module.2": " {module } -> empty string",
"gtceu.placeholder_info.nbt.0": "Returns the nbt data of the item in the specified slot",
"gtceu.placeholder_info.nbt.1": "Usage:",
"gtceu.placeholder_info.nbt.2": " {nbt [key1] [key2] [key3] ...} -> item_nbt[key1][key2][key3][...]",
@@ -3681,9 +3677,16 @@
"gtceu.placeholder_info.progress.1": "Note that progress is an integer between 0 and {maxProgress}",
"gtceu.placeholder_info.progress.2": "Usage:",
"gtceu.placeholder_info.progress.3": " {progress} -> the progress of the currently running recipe",
+ "gtceu.placeholder_info.quad.0": "Draws a quad (must specify parameters for all 4 vertices)",
+ "gtceu.placeholder_info.quad.1": "Usage:",
+ "gtceu.placeholder_info.quad.2": " {quad } -> empty string",
"gtceu.placeholder_info.random.0": "Returns a random number in the specified interval (inclusive).",
"gtceu.placeholder_info.random.1": "Usage:",
"gtceu.placeholder_info.random.2": " {random } -> a random number between min and max (inclusive)",
+ "gtceu.placeholder_info.rect.0": "Draws a rectangle at the specified position with the specified coordinates and size",
+ "gtceu.placeholder_info.rect.1": "Usage:",
+ "gtceu.placeholder_info.rect.2": " {rect } -> empty string",
+ "gtceu.placeholder_info.rect.3": " {rect 0.5 0.25 2 1 0xFFFFFFFF} -> draws a white rectangle at (0.5, 0.25) with the size (2, 1)",
"gtceu.placeholder_info.redstone.0": "Returns the redstone signal strength or sets the redstone output strength",
"gtceu.placeholder_info.redstone.1": "Usage:",
"gtceu.placeholder_info.redstone.2": " {redstone get } -> redstone signal strength (0-15) at the specified side",
@@ -3696,6 +3699,9 @@
"gtceu.placeholder_info.select.0": "Returns the argument at the specified index (starting from 0)",
"gtceu.placeholder_info.select.1": "Usage:",
"gtceu.placeholder_info.select.2": " {select [arg1] [arg2] [arg3] ... -> argument at the specified index",
+ "gtceu.placeholder_info.setImage.0": "Sets the image URL in an image module in the specified slot",
+ "gtceu.placeholder_info.setImage.1": "Usage:",
+ "gtceu.placeholder_info.setImage.2": " {setImage } -> empty string",
"gtceu.placeholder_info.strike.0": "Returns the text from the first text, displaying it as if it was crossed out",
"gtceu.placeholder_info.strike.1": "Usage:",
"gtceu.placeholder_info.strike.2": " {strike } -> crossed-out text",
@@ -4789,7 +4795,7 @@
"item.gtceu.tool.behavior.block_rotation": "§2Mechanic: §fRotates Blocks",
"item.gtceu.tool.behavior.crop_harvesting": "§aHarvester: §fHarvests Crops",
"item.gtceu.tool.behavior.damage_boost": "§4Damage Boost: §fExtra damage against %s",
- "item.gtceu.tool.behavior.dowse_campfire": "§1Firefighter: §fDowses Campfires",
+ "item.gtceu.tool.behavior.dowse_campfire": "§6Firefighter: §fDowses Campfires",
"item.gtceu.tool.behavior.grass_path": "§eLandscaper: §fCreates Grass Paths",
"item.gtceu.tool.behavior.ground_tilling": "§eFarmer: §fTills Ground",
"item.gtceu.tool.behavior.plunger": "§9Plumber: §fDrains Fluids",
@@ -5687,6 +5693,23 @@
"material.gtceu.zinc_sulfide": "Zinc Sulfide",
"material.gtceu.zincite": "Zincite",
"material.gtceu.zirconium": "Zirconium",
+ "medical_condition.gtceu.arsenicosis": "§bArsenicosis",
+ "medical_condition.gtceu.asbestosis": "§dAsbestosis",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7Carbon Monoxide Poisoning",
+ "medical_condition.gtceu.carcinogen": "§eCarcinogenic",
+ "medical_condition.gtceu.carcinogen.affected": "§eCancer",
+ "medical_condition.gtceu.chemical_burns": "§5Chemical burns",
+ "medical_condition.gtceu.irritant": "§6Irritant",
+ "medical_condition.gtceu.irritant.affected": "§6Irritation",
+ "medical_condition.gtceu.methanol_poisoning": "§6Methanol Poisoning",
+ "medical_condition.gtceu.nausea": "§3Nauseating",
+ "medical_condition.gtceu.nausea.affected": "§3Nausea",
+ "medical_condition.gtceu.none": "§2Not Dangerous",
+ "medical_condition.gtceu.none.affected": "§2Nothing?",
+ "medical_condition.gtceu.poison": "§2Poisonous",
+ "medical_condition.gtceu.poison.affected": "§2Poisoning",
+ "medical_condition.gtceu.weak_poison": "§aWeakly poisonous",
+ "medical_condition.gtceu.weak_poison.affected": "§aMinor poisoning",
"message.gtceu.new_veins.amount": "Prospected %d new veins!",
"message.gtceu.new_veins.name": "Prospected %s!",
"metaarmor.energy_share.disable": "Energy Supply: Gadgets charging disabled",
@@ -5809,6 +5832,20 @@
"recipe.condition.rain.tooltip": "Rain Level: %d",
"recipe.condition.steam_vent.tooltip": "Clean steam vent",
"recipe.condition.thunder.tooltip": "Thunder Level: %d",
+ "symptom.gtceu.air_supply_debuff": "Lowered lung capacity",
+ "symptom.gtceu.blindness": "Blindness",
+ "symptom.gtceu.darkness": "Darkness",
+ "symptom.gtceu.death": "Death",
+ "symptom.gtceu.health_debuff": "Lowered maximum health",
+ "symptom.gtceu.hunger": "Increased appetite",
+ "symptom.gtceu.mining_fatigue": "Fatigue",
+ "symptom.gtceu.nausea": "Nausea",
+ "symptom.gtceu.poisoning": "Poisoning",
+ "symptom.gtceu.random_damage": "Occasional damage",
+ "symptom.gtceu.slowness": "Slowness",
+ "symptom.gtceu.weak_poisoning": "Weak poisoning",
+ "symptom.gtceu.weakness": "Weakness",
+ "symptom.gtceu.wither": "Necrosis",
"tagprefix.andesite": "Andesite %s Ore",
"tagprefix.basalt": "Basalt %s Ore",
"tagprefix.blackstone": "Blackstone %s Ore",
@@ -5920,5 +5957,17 @@
"tile.gtceu.petrified_foam.name": "Petrified Foam",
"tile.gtceu.reinforced_foam.name": "Reinforced Foam",
"tile.gtceu.reinforced_stone.name": "Reinforced Stone",
- "tile.gtceu.seal.name": "Sealed Block"
+ "tile.gtceu.seal.name": "Sealed Block",
+ "tooltip.gtceu.antidote.description": "§aAntidote §7Hold Shift to show details",
+ "tooltip.gtceu.antidote.description.effect_removed": "Removes %s%% of current conditions' effects",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "Removes all of current conditions' effects",
+ "tooltip.gtceu.antidote.description_shift": "§aCures these conditions:",
+ "tooltip.gtceu.hazard_trigger": "Caused by:",
+ "tooltip.gtceu.hazard_trigger.any": "Any contact",
+ "tooltip.gtceu.hazard_trigger.inhalation": "Inhalation",
+ "tooltip.gtceu.hazard_trigger.none": "Nothing",
+ "tooltip.gtceu.hazard_trigger.protection": "Protects from:",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "Skin contact",
+ "tooltip.gtceu.medical_condition.description": "§l§cHAZARDOUS §7Hold Shift to show details",
+ "tooltip.gtceu.medical_condition.description_shift": "§l§cHAZARDOUS:"
}
\ No newline at end of file
diff --git a/src/generated/resources/data/gtceu/damage_type/medical_condition/berylliosis.json b/src/generated/resources/data/gtceu/damage_type/medical_condition/berylliosis.json
deleted file mode 100644
index d7f7f62336a..00000000000
--- a/src/generated/resources/data/gtceu/damage_type/medical_condition/berylliosis.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "exhaustion": 0.0,
- "message_id": "gtceu.medical_condition/berylliosis",
- "scaling": "never"
-}
\ No newline at end of file
diff --git a/src/generated/resources/data/gtceu/damage_type/medical_condition/silicosis.json b/src/generated/resources/data/gtceu/damage_type/medical_condition/silicosis.json
deleted file mode 100644
index 917b648aecf..00000000000
--- a/src/generated/resources/data/gtceu/damage_type/medical_condition/silicosis.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "exhaustion": 0.0,
- "message_id": "gtceu.medical_condition/silicosis",
- "scaling": "never"
-}
\ No newline at end of file
diff --git a/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json
index fc6bd8cfd19..cc2216956ca 100644
--- a/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json
+++ b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_armor.json
@@ -9,8 +9,6 @@
"gtceu:medical_condition/carcinogen",
"gtceu:medical_condition/asbestosis",
"gtceu:medical_condition/arsenicosis",
- "gtceu:medical_condition/silicosis",
- "gtceu:medical_condition/berylliosis",
"gtceu:medical_condition/methanol_poisoning",
"gtceu:medical_condition/carbon_monoxide_poisoning",
"gtceu:heat",
diff --git a/src/generated/resources/data/minecraft/tags/damage_type/bypasses_cooldown.json b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_cooldown.json
new file mode 100644
index 00000000000..7789592165e
--- /dev/null
+++ b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_cooldown.json
@@ -0,0 +1,15 @@
+{
+ "values": [
+ "gtceu:medical_condition/none",
+ "gtceu:medical_condition/chemical_burns",
+ "gtceu:medical_condition/poison",
+ "gtceu:medical_condition/weak_poison",
+ "gtceu:medical_condition/irritant",
+ "gtceu:medical_condition/nausea",
+ "gtceu:medical_condition/carcinogen",
+ "gtceu:medical_condition/asbestosis",
+ "gtceu:medical_condition/arsenicosis",
+ "gtceu:medical_condition/methanol_poisoning",
+ "gtceu:medical_condition/carbon_monoxide_poisoning"
+ ]
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/minecraft/tags/damage_type/bypasses_invulnerability.json b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_invulnerability.json
new file mode 100644
index 00000000000..7789592165e
--- /dev/null
+++ b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_invulnerability.json
@@ -0,0 +1,15 @@
+{
+ "values": [
+ "gtceu:medical_condition/none",
+ "gtceu:medical_condition/chemical_burns",
+ "gtceu:medical_condition/poison",
+ "gtceu:medical_condition/weak_poison",
+ "gtceu:medical_condition/irritant",
+ "gtceu:medical_condition/nausea",
+ "gtceu:medical_condition/carcinogen",
+ "gtceu:medical_condition/asbestosis",
+ "gtceu:medical_condition/arsenicosis",
+ "gtceu:medical_condition/methanol_poisoning",
+ "gtceu:medical_condition/carbon_monoxide_poisoning"
+ ]
+}
\ No newline at end of file
diff --git a/src/generated/resources/data/minecraft/tags/damage_type/bypasses_resistance.json b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_resistance.json
new file mode 100644
index 00000000000..7789592165e
--- /dev/null
+++ b/src/generated/resources/data/minecraft/tags/damage_type/bypasses_resistance.json
@@ -0,0 +1,15 @@
+{
+ "values": [
+ "gtceu:medical_condition/none",
+ "gtceu:medical_condition/chemical_burns",
+ "gtceu:medical_condition/poison",
+ "gtceu:medical_condition/weak_poison",
+ "gtceu:medical_condition/irritant",
+ "gtceu:medical_condition/nausea",
+ "gtceu:medical_condition/carcinogen",
+ "gtceu:medical_condition/asbestosis",
+ "gtceu:medical_condition/arsenicosis",
+ "gtceu:medical_condition/methanol_poisoning",
+ "gtceu:medical_condition/carbon_monoxide_poisoning"
+ ]
+}
\ No newline at end of file
diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java
index 66a0aa5c6b3..5ebaccf61d1 100644
--- a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java
+++ b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapability.java
@@ -1,6 +1,7 @@
package com.gregtechceu.gtceu.api.capability;
import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine;
+import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
@@ -33,7 +34,7 @@ public class GTCapability {
public static final Capability CAPABILITY_MONITOR_COMPONENT = CapabilityManager
.get(new CapabilityToken<>() {});
- public static final Capability CAPABILITY_MEDICAL_CONDITION_TRACKER = CapabilityManager
+ public static final Capability CAPABILITY_MEDICAL_CONDITION_TRACKER = CapabilityManager
.get(new CapabilityToken<>() {});
public static void register(RegisterCapabilitiesEvent event) {
@@ -48,7 +49,7 @@ public static void register(RegisterCapabilitiesEvent event) {
event.register(ILaserContainer.class);
event.register(IOpticalComputationProvider.class);
event.register(IDataAccessHatch.class);
- event.register(IMedicalConditionTracker.class);
+ event.register(MedicalConditionTracker.class);
event.register(IHazardParticleContainer.class);
event.register(IMonitorComponent.class);
}
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 ddd096e5fab..973d8f534d2 100644
--- a/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java
+++ b/src/main/java/com/gregtechceu/gtceu/api/capability/GTCapabilityHelper.java
@@ -1,6 +1,7 @@
package com.gregtechceu.gtceu.api.capability;
import com.gregtechceu.gtceu.api.machine.feature.multiblock.IMaintenanceMachine;
+import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@@ -123,7 +124,7 @@ private static T getBlockEntityCapability(Capability capability, Level le
}
@Nullable
- public static IMedicalConditionTracker getMedicalConditionTracker(@NotNull Entity entity) {
+ public static MedicalConditionTracker getMedicalConditionTracker(@NotNull Entity entity) {
return entity.getCapability(GTCapability.CAPABILITY_MEDICAL_CONDITION_TRACKER, null).resolve().orElse(null);
}
}
diff --git a/src/main/java/com/gregtechceu/gtceu/api/capability/IMedicalConditionTracker.java b/src/main/java/com/gregtechceu/gtceu/api/capability/IMedicalConditionTracker.java
deleted file mode 100644
index 2479a48a36e..00000000000
--- a/src/main/java/com/gregtechceu/gtceu/api/capability/IMedicalConditionTracker.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.gregtechceu.gtceu.api.capability;
-
-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.medicalcondition.MedicalCondition;
-
-import net.minecraft.world.effect.MobEffect;
-
-import it.unimi.dsi.fastutil.objects.Object2FloatMap;
-import org.jetbrains.annotations.NotNull;
-
-public interface IMedicalConditionTracker {
-
- /**
- * @return Map of medical condition to its progression.
- */
- Object2FloatMap getMedicalConditions();
-
- /**
- * @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 tick();
-
- default void progressRelatedCondition(@NotNull Material material) {
- HazardProperty materialHazard = material.getProperty(PropertyKey.HAZARD);
- progressCondition(materialHazard.condition, materialHazard.progressionMultiplier);
- }
-
- void progressCondition(@NotNull MedicalCondition condition, float strength);
-
- void heal(MedicalCondition condition, int progression);
-
- void setMobEffect(MobEffect effect, int amplifier);
-
- void removeMedicalCondition(MedicalCondition condition);
-}
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 6f3a184a71a..dc39dbb59b9 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,7 +2,6 @@
import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper;
-import com.gregtechceu.gtceu.api.data.chemical.material.Material;
import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialEntry;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
import com.gregtechceu.gtceu.api.data.tag.TagPrefix;
@@ -13,6 +12,7 @@
import com.gregtechceu.gtceu.config.ConfigHolder;
import com.gregtechceu.gtceu.data.recipe.CustomTags;
+import net.minecraft.network.chat.Component;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
@@ -21,6 +21,7 @@
import net.minecraft.world.item.ItemStack;
import lombok.Getter;
+import org.jetbrains.annotations.NotNull;
import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.SlotResult;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
@@ -57,6 +58,8 @@ public record HazardTrigger(String name, ProtectionType protectionType, Set CONDITIONS = new HashMap<>();
- public static final Codec CODEC = Codec.STRING.xmap(MedicalCondition.CONDITIONS::get,
- MedicalCondition::getName);
+ public static final Codec CODEC = GTRegistries.MEDICAL_CONDITIONS.codec();
+ public static final String AFFECTED_SUFFIX = ".affected";
- @Getter
- public final String name;
+ /**
+ * The ID of this medical condition in the registry.
+ * The tooltip text is derived from this in the form of {@code "medical_condition.."}
+ *
+ * If the name of this medical condition is queried in the context of affecting a player, and a language key
+ * {@code "medical_condition...affected"} exists, it'll be used instead of the generic one.
+ * For example, the {@code gtceu:carcinogenic} medical condition's tooltip name is "Carcinogenic".
+ * When a player with cancer checks their status with {@code /medical_condition query},
+ * the command will display "Player <player> has cancer" instead of "... has Carcinogenic"
+ *
+ */
+ public final ResourceLocation id;
public final int color;
public final float maxProgression; // amount of seconds until maximum progression is reached
public final Set symptoms = new HashSet<>();
@@ -36,47 +50,74 @@ public class MedicalCondition {
public final float idleProgressionRate;
public final boolean canBePermanent;
/**
- * This should mirror the {@link AirScrubberRecipes} recipe's outputs for this condition.
+ * This should mirror the associated {@linkplain AirScrubberRecipes air scrubber recipe's} outputs for this
+ * condition.
*/
@Getter
@Setter
@NotNull
public Consumer recipeModifier = builder -> {};
- public MedicalCondition(String name, int color, int maxProgression, IdleProgressionType idleProgressionType,
- float idleProgressionRate, boolean canBePermanent, Symptom.ConfiguredSymptom... symptoms) {
- this.name = name;
+ public MedicalCondition(ResourceLocation id, int color,
+ int maxProgression, IdleProgressionType progressionType, float progressionRate,
+ boolean canBePermanent, Symptom.ConfiguredSymptom... symptoms) {
+ this.id = id;
this.color = color;
this.maxProgression = maxProgression;
this.damageTypeData = new DamageTypeData.Builder()
- .simpleId("medical_condition/" + name)
+ .simpleId(id.withPrefix("medical_condition/"))
.scaling(DamageScaling.NEVER)
- .tag(DamageTypeTags.BYPASSES_ARMOR)
+ // all medical conditions' damage types MUST have the bypasses_invulnerability and bypasses_cooldown
+ // tags so the death symptom works properly
+ .tag(DamageTypeTags.BYPASSES_ARMOR, DamageTypeTags.BYPASSES_RESISTANCE,
+ DamageTypeTags.BYPASSES_INVULNERABILITY, DamageTypeTags.BYPASSES_COOLDOWN)
.build();
- this.symptoms.addAll(Arrays.asList(symptoms));
- this.idleProgressionType = idleProgressionType;
- this.idleProgressionRate = idleProgressionRate;
+ for (Symptom.ConfiguredSymptom symptom : symptoms) {
+ symptom.addedToCondition(this, this.symptoms.size());
+ this.symptoms.add(symptom);
+ }
+ this.idleProgressionType = progressionType;
+ this.idleProgressionRate = progressionRate;
this.canBePermanent = canBePermanent;
+ }
- CONDITIONS.put(name, this);
+ public DamageSource getDamageSource(MedicalConditionTracker tracker) {
+ return this.damageTypeData.source(tracker.getPlayer().level());
}
- public MedicalCondition(String name, int color, int maxProgression, IdleProgressionType progressionType,
- boolean canBePermanent, Symptom.ConfiguredSymptom... symptoms) {
- this(name, color, maxProgression, progressionType, 1, canBePermanent, symptoms);
+ public DamageSource getDamageSource(Level level) {
+ return this.damageTypeData.source(level);
}
- public MedicalCondition(String name, int color, int maxProgression, Symptom.ConfiguredSymptom... symptoms) {
- this(name, color, maxProgression, IdleProgressionType.NONE, 0, false, symptoms);
+ public String getTranslationKey() {
+ return this.id.toLanguageKey("medical_condition");
}
- public DamageSource getDamageSource(MedicalConditionTracker tracker) {
- return damageTypeData.source(tracker.getPlayer().level());
+ public Component getTranslatableName() {
+ return Component.translatable(this.getTranslationKey()).withStyle(style -> style.withColor(this.color));
}
- public DamageSource getDamageSource(Level level) {
- return damageTypeData.source(level);
+ public Component getAffectedName() {
+ String key = this.getTranslationKey();
+ String affectedKey = key + AFFECTED_SUFFIX;
+ if (Language.getInstance().has(affectedKey)) {
+ key = affectedKey;
+ }
+ return Component.translatable(key).withStyle(style -> style.withColor(this.color));
+ }
+
+ @Override
+ public String toString() {
+ StringJoiner stringJoiner = new StringJoiner(", ", "[", "]");
+ stringJoiner.add("color=#" + FormattingUtil.HEX_FORMAT.toHexDigits(this.color));
+ stringJoiner.add("maxProgression=" + this.maxProgression);
+ stringJoiner.add("symptoms=" + this.symptoms);
+ stringJoiner.add("damageType=" + this.damageTypeData.id);
+ stringJoiner.add("idleProgressionType=" + this.idleProgressionType.name().toLowerCase(Locale.ROOT));
+ stringJoiner.add("idleProgressionRate=" + this.idleProgressionRate);
+
+ return this.id.toString() + stringJoiner.toString();
}
public enum IdleProgressionType {
diff --git a/src/main/java/com/gregtechceu/gtceu/api/data/medicalcondition/Symptom.java b/src/main/java/com/gregtechceu/gtceu/api/data/medicalcondition/Symptom.java
index 154a2a69b99..9d933417b5d 100644
--- a/src/main/java/com/gregtechceu/gtceu/api/data/medicalcondition/Symptom.java
+++ b/src/main/java/com/gregtechceu/gtceu/api/data/medicalcondition/Symptom.java
@@ -1,86 +1,146 @@
package com.gregtechceu.gtceu.api.data.medicalcondition;
-import com.gregtechceu.gtceu.api.GTValues;
import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker;
import com.gregtechceu.gtceu.common.data.GTMobEffects;
+import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.ai.attributes.Attribute;
+import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
-import org.jetbrains.annotations.Nullable;
+import com.google.common.base.Preconditions;
+import lombok.Getter;
+import java.util.StringJoiner;
import java.util.UUID;
import java.util.function.Supplier;
public class Symptom {
+ // spotless:off
public static final UUID SYMPTOM_HEALTH_DEBUFF_UUID = UUID.fromString("607aa6d9-a7e4-4919-9962-f007104c4be8");
- public static final UUID SYMPTOM_ATTACK_SPEED_DEBUFF_UUID = UUID.fromString("f2378ee6-3427-45b5-8440-4b797f7b664a");
+ public static final UUID SYMPTOM_MINING_FATIGUE_UUID = UUID.fromString("f2378ee6-3427-45b5-8440-4b797f7b664a");
public static final UUID SYMPTOM_WEAKNESS_UUID = UUID.fromString("482e64e0-de77-49cd-b9bc-96b7e7eb16db");
public static final UUID SYMPTOM_SLOWNESS_UUID = UUID.fromString("b3ac6b40-2d30-419f-9cac-5b2cf998ad72");
- public static final Symptom DEATH = new Symptom(defaultKey("death"), 1, 1,
- ((medicalConditionTracker, condition, configuredSymptom, baseSymptom, modifier) -> {
- if (modifier > 0) {
- Player player = medicalConditionTracker.getPlayer();
- player.hurt(condition.getDamageSource(medicalConditionTracker), Float.MAX_VALUE);
+ public static final Symptom DEATH = new Symptom(defaultKey("death"), 1, 1.0f, 1.0f,
+ (tracker, condition, configuredSymptom, baseSymptom, stage) -> {
+ if (stage > 0) {
+ Player player = tracker.getPlayer();
+ // this should replicate the logic in LivingEntity#kill, but
+ // with the medical condition's damage type instead of `generic_kill`.
+ player.hurt(condition.getDamageSource(tracker), Float.MAX_VALUE);
}
- }));
- public static final Symptom RANDOM_DAMAGE = new Symptom(defaultKey("random_damage"), 10, 1,
- (medicalConditionTracker, condition, configuredSymptom, baseSymptom, modifier) -> {},
- (medicalConditionTracker, condition, configuredSymptom, baseSymptom, modifier) -> {
- int stages = configuredSymptom != null ? configuredSymptom.stages : baseSymptom.defaultStages;
- if (modifier > 0 && GTValues.RNG.nextInt(stages * 500 / modifier) == 0) {
- medicalConditionTracker.getPlayer().hurt(condition.getDamageSource(medicalConditionTracker), 0.5f);
+ });
+ public static final Symptom RANDOM_DAMAGE = new Symptom(defaultKey("random_damage"), 10, 0.2f, 1.0f,
+ Effect.NO_OP,
+ (tracker, condition, configuredSymptom, baseSymptom, stage) -> {
+ int stages = configuredSymptom.getStages();
+ if (stage > 0 && tracker.getPlayer().getRandom().nextInt(stages * 500 / stage) == 0) {
+ tracker.getPlayer().hurt(condition.getDamageSource(tracker), 0.5f);
}
});
- public static final Symptom HEALTH_DEBUFF = new Symptom(defaultKey("health_debuff"), 10, 1, 1,
- Attributes.MAX_HEALTH, SYMPTOM_HEALTH_DEBUFF_UUID);
- public static final Symptom ATTACK_SPEED_DEBUFF = new Symptom(defaultKey("attack_speed_debuff"), 10, 1, .2f,
- Attributes.ATTACK_SPEED, SYMPTOM_ATTACK_SPEED_DEBUFF_UUID);
- public static final Symptom WEAKNESS = new Symptom(defaultKey("weakness"), 10, 1, .1f, Attributes.ATTACK_DAMAGE,
- SYMPTOM_WEAKNESS_UUID);
- public static final Symptom SLOWNESS = new Symptom(defaultKey("slowness"), 7, 1, .005f, Attributes.MOVEMENT_SPEED,
- SYMPTOM_SLOWNESS_UUID);
- public static final Symptom AIR_SUPPLY_DEBUFF = new Symptom(defaultKey("air_supply_debuff"), 10, 1,
- (hazardEffectTracker, damageSource, configuredSymptom, baseSymptom, modifier) -> hazardEffectTracker
- .setMaxAirSupply(300 - 10 * modifier));
- public static final Symptom BLINDNESS = new Symptom(defaultKey("blindness"), 10, 0, MobEffects.BLINDNESS);
- public static final Symptom NAUSEA = new Symptom(defaultKey("nausea"), 10, 0, MobEffects.CONFUSION);
- public static final Symptom MINING_FATIGUE = new Symptom(defaultKey("mining_fatigue"), 10, 1,
- MobEffects.DIG_SLOWDOWN);
- public static final Symptom WITHER = new Symptom(defaultKey("wither"), 1, 1,
- MobEffects.WITHER);
- public static final Symptom WEAK_POISONING = new Symptom(defaultKey("weak_poisoning"), 10,
- 1, GTMobEffects.WEAK_POISON::get);
- public static final Symptom POISONING = new Symptom(defaultKey("poisoning"), 10,
- 1, MobEffects.POISON);
- public static final Symptom HUNGER = new Symptom(defaultKey("hunger"), 5, 1, MobEffects.HUNGER);
+ // default is 20, stage 10 result will be 10
+ // the health debuff stage is a special case because it has to resync the player's current health to the client
+ public static final Symptom HEALTH_DEBUFF = new Symptom(defaultKey("health_debuff"), 10, 0.0f, 1.0f,
+ (tracker, $1, $2, symptom, stage) -> {
+ Player player = tracker.getPlayer();
+ AttributeInstance instance = player.getAttribute(Attributes.MAX_HEALTH);
+ if (instance == null) {
+ return;
+ }
+ instance.removeModifier(SYMPTOM_HEALTH_DEBUFF_UUID);
+
+ if (stage != 0) {
+ instance.addPermanentModifier(new AttributeModifier(SYMPTOM_HEALTH_DEBUFF_UUID, symptom.name,
+ -stage, AttributeModifier.Operation.ADDITION));
+ }
+ // reset the health data value so the max health change is applied immediately
+ if (player.getHealth() > player.getMaxHealth()) {
+ player.setHealth(player.getHealth());
+ }
+ });
+ // default is 4, stage 10 result will be 1.6
+ public static final Symptom MINING_FATIGUE = Symptom.ofAttributeModifier(defaultKey("mining_fatigue"), 10, 0.0f, 1.0f,
+ 0.04f, Attributes.ATTACK_SPEED, SYMPTOM_MINING_FATIGUE_UUID);
+ // default is 2, stage 10 result will be 0.5
+ public static final Symptom WEAKNESS = Symptom.ofAttributeModifier(defaultKey("weakness"), 10, 0.0f, 1.0f,
+ 0.025f, Attributes.ATTACK_DAMAGE, SYMPTOM_WEAKNESS_UUID);
+ // default is 0.1, stage 7 result will be 0.065
+ // REMEMBER TO UPDATE TESTS IF YOU CHANGE THIS
+ public static final Symptom SLOWNESS = Symptom.ofAttributeModifier(defaultKey("slowness"), 7, 0.0f, 1.0f,
+ 0.05f, Attributes.MOVEMENT_SPEED, SYMPTOM_SLOWNESS_UUID);
+ // default is 300, stage 10 result will be 200
+ public static final Symptom AIR_SUPPLY_DEBUFF = new Symptom(defaultKey("air_supply_debuff"), 10, 0.0f, 1.0f,
+ (tracker, condition, configuredSymptom, baseSymptom, stage) -> {
+ if (stage != 0) {
+ tracker.getPlayer().gtceu$setMaxAirSupply(tracker.getPlayer().gtceu$getOriginalMaxAirSupply() - 10 * stage);
+ } else {
+ tracker.getPlayer().gtceu$setMaxAirSupply(-1);
+ }
+ });
+
+ public static final Symptom BLINDNESS = Symptom.ofEffect(defaultKey("blindness"), 10, 0.0f, 1.0f, MobEffects.BLINDNESS);
+ public static final Symptom DARKNESS = Symptom.ofEffect(defaultKey("darkness"), 10, 0.0f, 1.0f, MobEffects.DARKNESS);
+ public static final Symptom NAUSEA = Symptom.ofEffect(defaultKey("nausea"), 1, 0.95f, 1.0f, MobEffects.CONFUSION);
+ public static final Symptom WITHER = Symptom.ofEffect(defaultKey("wither"), 1, 1.0f, 1.0f, MobEffects.WITHER);
+ public static final Symptom WEAK_POISONING = Symptom.ofEffect(defaultKey("weak_poisoning"), 10, 0.0f, 1.0f, GTMobEffects.WEAK_POISON);
+ public static final Symptom POISONING = Symptom.ofEffect(defaultKey("poisoning"), 10, 0.0f, 1.0f, MobEffects.POISON);
+ public static final Symptom HUNGER = Symptom.ofEffect(defaultKey("hunger"), 5, 0.0f, 1.0f, MobEffects.HUNGER);
+ // spotless:on
public final String name;
public final int defaultStages;
- public final float defaultProgressionThreshold;
+ /**
+ * The (relative) threshold this symptom will start occurring at.
+ * The range is [0.0,1.0], with 0.0 meaning "as soon as the player gains the condition"
+ * and 1.0 meaning "at the condition's max progress value".
+ *
+ * If this symptom's {@link #defaultStages} is >0, the symptom will start occurring at
+ * {@link #minThreshold} and the maximum stage will be reached at {@link #maxThreshold}.
+ *
+ *
+ * For example: The relative minimum threshold of this symptom is 0.5 and
+ * the condition's maximum progress is 200 seconds.
+ * This symptom will start occurring when the player has had the condition for 100 seconds.
+ *
+ */
+ public final float minThreshold;
+ /**
+ * The (relative) threshold at which this symptom will be reach its maximum potential.
+ * The range is [0.0,1.0], with 0.0 meaning "as soon as the player gains the condition"
+ * and 1.0 meaning "at the condition's max progress value".
+ *
+ * If this symptom's {@link #defaultStages} is >0, the symptom will start occurring at
+ * {@link #minThreshold} and the maximum stage will be reached at {@link #maxThreshold}.
+ *
+ *
+ * For example: tThe relative maximum threshold of this symptom is 0.75 and the
+ * condition's maximum progress is 200 seconds.
+ * This symptom will reach its peak when the player has had the condition for 150 seconds.
+ *
+ */
+ public final float maxThreshold;
- // integer corresponds to symptom stage, if integer is 0 symptom effects should be removed
private final Effect progressionEffect;
private final Effect tickEffect;
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold,
+ public Symptom(String name, int defaultStages, float minThreshold, float maxThreshold,
Effect progressionEffect, Effect tickEffect) {
this.name = name;
this.defaultStages = defaultStages;
- this.defaultProgressionThreshold = defaultProgressionThreshold;
+ this.minThreshold = minThreshold;
+ this.maxThreshold = maxThreshold;
this.progressionEffect = progressionEffect;
this.tickEffect = tickEffect;
}
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, Effect progressionEffect) {
- this(name, defaultStages, defaultProgressionThreshold, progressionEffect,
- (tracker, condition, configuredSymptom, baseSymptom, amplifier) -> {});
+ public Symptom(String name, int defaultStages, float minThreshold, float maxThreshold, Effect progressionEffect) {
+ this(name, defaultStages, minThreshold, maxThreshold, progressionEffect, Effect.NO_OP);
}
/**
@@ -88,107 +148,201 @@ public Symptom(String name, int defaultStages, float defaultProgressionThreshold
* @param attribute Attribute to modify
* @param uuid AttributeModifier UUID
*/
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, float multiplier,
- Attribute attribute, UUID uuid) {
- this(name, defaultStages, defaultProgressionThreshold,
- ((medicalConditionTracker, $1, $2, $3, modifier) -> {
- if (!medicalConditionTracker.getPlayer().getAttributes().hasAttribute(attribute)) {
+ public static Symptom ofAttributeModifier(String name, int defaultStages, float minThreshold, float maxThreshold,
+ float multiplier, Attribute attribute, UUID uuid) {
+ return new Symptom(name, defaultStages, minThreshold, maxThreshold,
+ (tracker, condition, symptom, baseSymptom, stage) -> {
+ Player player = tracker.getPlayer();
+ AttributeInstance instance = player.getAttribute(attribute);
+ if (instance == null) {
return;
}
- medicalConditionTracker.getPlayer().getAttribute(attribute).removeModifier(uuid);
- if (modifier != 0) {
- medicalConditionTracker.getPlayer().getAttribute(attribute).addPermanentModifier(
- new AttributeModifier(uuid, name, -modifier * multiplier,
- AttributeModifier.Operation.ADDITION));
- }
- // re-set the health data value so the max health change is applied immediately
- if (attribute == Attributes.MAX_HEALTH) {
- medicalConditionTracker.getPlayer().setHealth(medicalConditionTracker.getPlayer().getHealth());
+ instance.removeModifier(uuid);
+
+ if (stage != 0) {
+ instance.addPermanentModifier(new AttributeModifier(uuid, name,
+ -stage * multiplier, AttributeModifier.Operation.MULTIPLY_BASE));
}
- }));
+ });
}
/**
- * @param mobEffect MobEffect to apply
- * @param amplifierMultiplier amplifier added to MobEffect every progression
+ * @param mobEffect effect to apply
+ * @param amplifierMultiplier amplifier added to effect every progression tick
*/
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, MobEffect mobEffect,
- int amplifierMultiplier) {
- this(name, defaultStages, defaultProgressionThreshold,
- (medicalConditionTracker, $1, $2, $3, modifier) -> medicalConditionTracker.setMobEffect(mobEffect,
- amplifierMultiplier * modifier));
+ public static Symptom ofEffect(String name, int defaultStages, float minThreshold, float maxThreshold,
+ Supplier mobEffect, int amplifierMultiplier) {
+ return new Symptom(name, defaultStages, minThreshold, maxThreshold,
+ (tracker, $1, $2, $3, stage) -> {
+ MobEffect effect = mobEffect.get();
+ tracker.setMobEffect(effect, amplifierMultiplier * stage);
+ if (stage == 0) {
+ tracker.getPlayer().removeEffect(effect);
+ }
+ });
}
/**
* @param mobEffect MobEffect to apply
* @param amplifierMultiplier amplifier added to MobEffect every progression
*/
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, Supplier mobEffect,
- int amplifierMultiplier) {
- this(name, defaultStages, defaultProgressionThreshold,
- (hazardEffectTracker, $1, $2, $3, modifier) -> hazardEffectTracker.setMobEffect(mobEffect.get(),
- amplifierMultiplier * modifier));
+ public static Symptom ofEffect(String name, int defaultStages, float minThreshold, float maxThreshold,
+ MobEffect mobEffect, int amplifierMultiplier) {
+ return ofEffect(name, defaultStages, minThreshold, maxThreshold,
+ () -> mobEffect, amplifierMultiplier);
}
/**
- * @param mobEffect MobEffect to apply
+ * @param mobEffect effect to apply
*/
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, MobEffect mobEffect) {
- this(name, defaultStages, defaultProgressionThreshold,
- (hazardEffectTracker, $1, $2, $3, modifier) -> hazardEffectTracker.setMobEffect(mobEffect, modifier));
+ public static Symptom ofEffect(String name, int defaultStages, float minThreshold, float maxThreshold,
+ Supplier mobEffect) {
+ return ofEffect(name, defaultStages, minThreshold, maxThreshold, mobEffect, 1);
}
/**
- * @param mobEffect MobEffect to apply
+ * @param mobEffect effect to apply
*/
- public Symptom(String name, int defaultStages, float defaultProgressionThreshold, Supplier mobEffect) {
- this(name, defaultStages, defaultProgressionThreshold,
- (hazardEffectTracker, $1, $2, $3, modifier) -> hazardEffectTracker.setMobEffect(mobEffect.get(),
- modifier));
+ public static Symptom ofEffect(String name, int defaultStages, float minThreshold, float maxThreshold,
+ MobEffect mobEffect) {
+ return ofEffect(name, defaultStages, minThreshold, maxThreshold, () -> mobEffect);
}
public void applyProgression(MedicalConditionTracker subject, MedicalCondition condition,
- @Nullable ConfiguredSymptom symptom, int modifier) {
- progressionEffect.apply(subject, condition, symptom, this, modifier);
+ ConfiguredSymptom symptom, int stage) {
+ progressionEffect.apply(subject, condition, symptom, this, stage);
}
public void tick(MedicalConditionTracker subject, MedicalCondition condition,
- @Nullable ConfiguredSymptom symptom, int modifier) {
- tickEffect.apply(subject, condition, symptom, this, modifier);
+ ConfiguredSymptom symptom, int stage) {
+ tickEffect.apply(subject, condition, symptom, this, stage);
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
}
public static class ConfiguredSymptom {
- public final Symptom symptom;
- public final int stages;
- public final float progressionThreshold;
- public final float relativeHarshness;
+ @Getter
+ private final Symptom symptom;
+ @Getter
+ private final int stages;
+ @Getter
+ private final float relativeHarshness;
+ /**
+ * The threshold this symptom will start occurring at.
+ *
+ * If this symptom's {@link #stages} is >0, the symptom will start occurring at {@link #minThreshold}
+ * and the maximum stage will be reached at {@link #maxThreshold}.
+ *
+ *
+ * For example: The minimum threshold of this symptom is 100 and
+ * the condition's maximum progress is 200 seconds.
+ * This symptom will start occurring when the player has had the condition for 100 seconds.
+ *
+ */
+ @Getter
+ private float minThreshold;
+ /**
+ * The threshold at which this symptom will be reach its maximum potential.
+ *
+ * If this symptom's {@link #stages} is >0, the symptom will start occurring at {@link #minThreshold}
+ * and the maximum stage will be reached at {@link #maxThreshold}.
+ *
+ *
+ * For example: The maximum threshold of this symptom is 150 and
+ * the condition's maximum progress is 200 seconds.
+ * This symptom will reach its peak when the player has had the condition for 150 seconds.
+ *
+ */
+ @Getter
+ private float maxThreshold;
- public ConfiguredSymptom(Symptom symptom, int stages, float progressionThreshold) {
+ /**
+ * Whether this {@code ConfiguredSymptom} uses the default progression thresholds for its {@link #symptom}
+ * and should recalculate absolute progression values for the {@linkplain MedicalCondition} it's a part of
+ */
+ private boolean relativeThresholds = false;
+
+ protected ConfiguredSymptom(Symptom symptom, int stages,
+ float relativeMinThreshold, float relativeMaxThreshold) {
this.symptom = symptom;
this.stages = stages;
- this.progressionThreshold = progressionThreshold;
this.relativeHarshness = (float) stages / symptom.defaultStages;
+
+ this.minThreshold = relativeMinThreshold;
+ this.maxThreshold = relativeMaxThreshold;
}
- public ConfiguredSymptom(Symptom symptom) {
- this(symptom, symptom.defaultStages, symptom.defaultProgressionThreshold);
+ public ConfiguredSymptom(Symptom symptom, int stages, int absMinThreshold, int absMaxThreshold) {
+ this(symptom, stages, (float) absMinThreshold, (float) absMaxThreshold);
+ }
+
+ public ConfiguredSymptom(Symptom symptom, int absMinThreshold, int absMaxThreshold) {
+ this(symptom, symptom.defaultStages, absMinThreshold, absMaxThreshold);
}
public ConfiguredSymptom(Symptom symptom, int stages) {
- this(symptom, stages, symptom.defaultProgressionThreshold);
+ this(symptom, stages, symptom.minThreshold, symptom.maxThreshold);
+ this.relativeThresholds = true;
}
- public ConfiguredSymptom(Symptom symptom, float progressionThreshold) {
- this(symptom, symptom.defaultStages, progressionThreshold);
+ public ConfiguredSymptom(Symptom symptom) {
+ this(symptom, symptom.defaultStages);
+ }
+
+ /**
+ * Update the stored progression threshold values based on the passed condition's
+ * {@link MedicalCondition#maxProgression maxProgression} value
+ *
+ * @param condition the medical condition that the threshold values will be based on
+ * @param index the index in the condition's symptom list this symptom will be added to
+ */
+ public void addedToCondition(MedicalCondition condition, int index) {
+ if (this.relativeThresholds) {
+ this.relativeThresholds = false;
+ this.minThreshold = this.minThreshold * condition.maxProgression;
+ this.maxThreshold = this.maxThreshold * condition.maxProgression;
+ }
+
+ this.minThreshold = Mth.clamp(this.minThreshold, 0.0f, condition.maxProgression);
+ this.maxThreshold = Mth.clamp(this.maxThreshold, 0.0f, condition.maxProgression);
+
+ Preconditions.checkArgument(minThreshold <= maxThreshold,
+ "minProgressThreshold must be <= maxProgressThreshold for symptom %s (%s) of condition %s (min %s > max %s)",
+ index, symptom.name, condition.id.toString(), minThreshold, maxThreshold);
+ }
+
+ @Override
+ public String toString() {
+ StringJoiner stringJoiner = new StringJoiner(", ", "[", "]");
+ stringJoiner.add("stages=" + this.stages);
+ stringJoiner.add("relativeHarshness=" + this.relativeHarshness);
+ stringJoiner.add("minTreshold=" + this.minThreshold);
+ stringJoiner.add("maxTreshold=" + this.maxThreshold);
+
+ return this.symptom.toString() + stringJoiner;
}
}
@FunctionalInterface
public interface Effect {
+ Effect NO_OP = (tracker, condition, configuredSymptom, baseSymptom, amplifier) -> {};
+
+ /**
+ * If {@code stage} is 0, any effects should be removed.
+ *
+ * @param tracker the medical condition tracker processing this effect
+ * @param condition the medical condition this symptom belongs to
+ * @param configuredSymptom the symptom this effect belongs to
+ * @param baseSymptom the unconfigured symptom
+ * @param stage the stage of this symptom
+ */
void apply(MedicalConditionTracker tracker, MedicalCondition condition,
- @Nullable ConfiguredSymptom configuredSymptom, Symptom baseSymptom, int amplifier);
+ ConfiguredSymptom configuredSymptom, Symptom baseSymptom, int stage);
}
private static String defaultKey(String name) {
diff --git a/src/main/java/com/gregtechceu/gtceu/api/registry/GTRegistries.java b/src/main/java/com/gregtechceu/gtceu/api/registry/GTRegistries.java
index 67f38bf2942..a42b600a203 100644
--- a/src/main/java/com/gregtechceu/gtceu/api/registry/GTRegistries.java
+++ b/src/main/java/com/gregtechceu/gtceu/api/registry/GTRegistries.java
@@ -5,6 +5,7 @@
import com.gregtechceu.gtceu.api.cover.CoverDefinition;
import com.gregtechceu.gtceu.api.data.DimensionMarker;
import com.gregtechceu.gtceu.api.data.chemical.Element;
+import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
import com.gregtechceu.gtceu.api.data.worldgen.GTOreDefinition;
import com.gregtechceu.gtceu.api.data.worldgen.bedrockfluid.BedrockFluidDefinition;
import com.gregtechceu.gtceu.api.data.worldgen.bedrockore.BedrockOreDefinition;
@@ -65,6 +66,9 @@ public final class GTRegistries {
public static final GTRegistry.RL ORE_VEINS = new GTRegistry.RL<>(GTCEu.id("ore_vein"));
public static final GTRegistry.RL DIMENSION_MARKERS = new GTRegistry.RL<>(
GTCEu.id("dimension_marker"));
+ public static final GTRegistry.RL MEDICAL_CONDITIONS = new GTRegistry.RL<>(
+ GTCEu.id("medical_condition"));
+
public static final DeferredRegister> TRUNK_PLACER_TYPE = DeferredRegister
.create(Registries.TRUNK_PLACER_TYPE, GTCEu.MOD_ID);
public static final DeferredRegister> PLACEMENT_MODIFIER = DeferredRegister
diff --git a/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java b/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java
index 780f55eeadb..bcdb461bd08 100644
--- a/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java
+++ b/src/main/java/com/gregtechceu/gtceu/client/TooltipsHandler.java
@@ -73,7 +73,7 @@ public static void appendTooltips(ItemStack stack, TooltipFlag flag, List event) {
if (event.getObject() instanceof Player entity) {
final MedicalConditionTracker tracker = new MedicalConditionTracker(entity);
- event.addCapability(GTCEu.id("medical_condition_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_MEDICAL_CONDITION_TRACKER.orEmpty(capability,
- LazyOptional.of(() -> tracker));
- }
- });
+ event.addCapability(GTCEu.id("medical_condition_tracker"), tracker);
}
}
@@ -171,13 +149,18 @@ public static void registerCapes(RegisterGTCapesEvent event) {
}
@SubscribeEvent
- public static void tickPlayerInventoryHazards(TickEvent.PlayerTickEvent event) {
+ public static void tickPlayerHazards(TickEvent.PlayerTickEvent event) {
if (event.side == LogicalSide.CLIENT || event.phase != TickEvent.Phase.END) {
return;
}
Player player = event.player;
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ // update the tracker every second, including clearing everything when the config changes.
+ if (player.tickCount % 20 != 0) {
+ return;
+ }
+
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
if (tracker == null) {
return;
}
@@ -192,22 +175,23 @@ public static void tickPlayerInventoryHazards(TickEvent.PlayerTickEvent event) {
if (inventory == null) {
return;
}
+
tracker.tick();
for (int i = 0; i < inventory.getSlots(); ++i) {
ItemStack stack = inventory.getStackInSlot(i);
- Material material = HazardProperty.getValidHazardMaterial(stack);
- if (material.isNull() || !material.hasProperty(PropertyKey.HAZARD)) {
+ MaterialEntry entry = HazardProperty.getValidHazardMaterial(stack);
+ if (entry.material().isNull()) {
continue;
}
- HazardProperty property = material.getProperty(PropertyKey.HAZARD);
+ HazardProperty property = entry.material().getProperty(PropertyKey.HAZARD);
if (property.hazardTrigger.protectionType().isProtected(player)) {
// entity has proper safety equipment, so damage it per material every 5 seconds.
property.hazardTrigger.protectionType().damageEquipment(player, 1);
// don't progress this material condition if entity is protected
continue;
}
- tracker.progressRelatedCondition(material);
+ tracker.progressRelatedCondition(entry, stack.getCount());
}
}
@@ -230,6 +214,31 @@ public static void onMobEffectEvent(MobEffectEvent.Applicable event) {
}
}
+ @SubscribeEvent
+ public static void onItemUseFinished(LivingEntityUseItemEvent.Finish event) {
+ if (!(event.getEntity() instanceof Player player) || player.level().isClientSide) {
+ return;
+ }
+
+ ItemStack usedItem = event.getItem();
+ if (!usedItem.isEdible()) {
+ return;
+ }
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ if (tracker == null) {
+ return;
+ }
+
+ MaterialEntry entry = HazardProperty.getValidHazardMaterial(usedItem);
+ if (entry.material().isNull()) {
+ return;
+ }
+ HazardProperty property = entry.material().getProperty(PropertyKey.HAZARD);
+ if (property.hazardTrigger == HazardProperty.HazardTrigger.CONSUMPTION) {
+ tracker.progressRelatedCondition(entry, 1);
+ }
+ }
+
@SubscribeEvent
public static void onLeftClickBlock(PlayerInteractEvent.LeftClickBlock event) {
var machine = MetaMachine.getMachine(event.getLevel(), event.getPos());
@@ -432,7 +441,7 @@ public static void stepAssistHandler(LivingEvent.LivingTickEvent event) {
@SubscribeEvent
public static void onEntityDie(LivingDeathEvent event) {
if (event.getEntity() instanceof Player player) {
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
if (tracker == null) {
return;
}
@@ -504,6 +513,77 @@ public static void onEquipmentChange(LivingEquipmentChangeEvent event) {
}
}
+ @SubscribeEvent
+ public static void modifyBreakSpeed(PlayerEvent.BreakSpeed event) {
+ Player player = event.getEntity();
+ for (ItemStack stack : player.getArmorSlots()) {
+ if (!(stack.getItem() instanceof ArmorComponentItem componentItem)) {
+ continue;
+ }
+ if (!(componentItem.getArmorLogic() instanceof IJetpack jetpack) || !jetpack.removeMiningSpeedPenalty()) {
+ continue;
+ }
+ // undo flight mining speed debuff
+ if (!player.onGround()) {
+ event.setNewSpeed(event.getNewSpeed() * 5);
+ }
+ // and also underwater debuff
+ if (player.isEyeInFluidType(ForgeMod.WATER_TYPE.get()) && !EnchantmentHelper.hasAquaAffinity(player)) {
+ event.setNewSpeed(event.getNewSpeed() * 5);
+ }
+ }
+
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ if (tracker == null || !ConfigHolder.INSTANCE.gameplay.hazardsEnabled) {
+ return;
+ }
+ if (player.getAttributes().hasModifier(Attributes.ATTACK_SPEED, Symptom.SYMPTOM_MINING_FATIGUE_UUID)) {
+ float miningFatigueModifier = (float) player.getAttributes()
+ .getModifierValue(Attributes.ATTACK_SPEED, Symptom.SYMPTOM_MINING_FATIGUE_UUID);
+ // mimic how AttributeInstance handles MULTIPLY_BASE modifiers
+ event.setNewSpeed(event.getNewSpeed() + event.getNewSpeed() * miningFatigueModifier);
+ }
+ }
+
+ @SubscribeEvent
+ public static void addAlloyBlastProperties(PostMaterialEvent event) {
+ for (Material material : GTCEuAPI.materialManager.getRegisteredMaterials()) {
+ if (!material.hasFlag(MaterialFlags.DISABLE_ALLOY_PROPERTY)) {
+ addAlloyBlastProperty(material);
+ }
+ }
+ // Alloy Blast Overriding
+ GTMaterials.NiobiumNitride.getProperty(PropertyKey.ALLOY_BLAST)
+ .setRecipeProducer(new CustomAlloyBlastRecipeProducer(1, 11, -1));
+
+ GTMaterials.IndiumTinBariumTitaniumCuprate.getProperty(PropertyKey.ALLOY_BLAST)
+ .setRecipeProducer(new CustomAlloyBlastRecipeProducer(-1, -1, 16));
+ }
+
+ public static void addAlloyBlastProperty(@NotNull Material material) {
+ final List components = material.getMaterialComponents();
+ // ignore materials which are not alloys
+ if (components.size() < 2) return;
+
+ BlastProperty blastProperty = material.getProperty(PropertyKey.BLAST);
+ if (blastProperty == null) return;
+
+ if (!material.hasProperty(PropertyKey.FLUID)) return;
+
+ // if there are more than 2 fluid-only components in the material, do not generate a hot fluid
+ if (components.stream().filter(CommonEventListener::isMaterialStackFluidOnly).limit(3).count() > 2) {
+ return;
+ }
+
+ material.setProperty(PropertyKey.ALLOY_BLAST, new AlloyBlastProperty(material.getBlastTemperature()));
+ material.getProperty(PropertyKey.FLUID).getStorage().enqueueRegistration(FluidStorageKeys.MOLTEN,
+ new FluidBuilder().state(FluidState.LIQUID));
+ }
+
+ private static boolean isMaterialStackFluidOnly(@NotNull MaterialStack ms) {
+ return !ms.material().hasProperty(PropertyKey.DUST) && ms.material().hasProperty(PropertyKey.FLUID);
+ }
+
@SubscribeEvent
public static void remapIds(MissingMappingsEvent event) {
event.getMappings(Registries.BLOCK, GTCEu.MOD_ID).forEach(mapping -> {
@@ -663,55 +743,4 @@ public static void remapIds(MissingMappingsEvent event) {
});
}
}
-
- @SubscribeEvent
- public static void breakSpeed(PlayerEvent.BreakSpeed event) {
- Player player = event.getEntity();
- for (ItemStack stack : player.getArmorSlots()) {
- if (stack.getItem() instanceof ArmorComponentItem componentItem) {
- if (componentItem.getArmorLogic() instanceof IJetpack jetpack && jetpack.removeMiningSpeedPenalty()) {
- if (!player.onGround() || player.isUnderWater()) event.setNewSpeed(event.getOriginalSpeed() * 5);
- }
- }
- }
- }
-
- @SubscribeEvent
- public static void addAlloyBlastProperties(PostMaterialEvent event) {
- for (Material material : GTCEuAPI.materialManager.getRegisteredMaterials()) {
- if (!material.hasFlag(MaterialFlags.DISABLE_ALLOY_PROPERTY)) {
- addAlloyBlastProperty(material);
- }
- }
- // Alloy Blast Overriding
- GTMaterials.NiobiumNitride.getProperty(PropertyKey.ALLOY_BLAST)
- .setRecipeProducer(new CustomAlloyBlastRecipeProducer(1, 11, -1));
-
- GTMaterials.IndiumTinBariumTitaniumCuprate.getProperty(PropertyKey.ALLOY_BLAST)
- .setRecipeProducer(new CustomAlloyBlastRecipeProducer(-1, -1, 16));
- }
-
- public static void addAlloyBlastProperty(@NotNull Material material) {
- final List components = material.getMaterialComponents();
- // ignore materials which are not alloys
- if (components.size() < 2) return;
-
- BlastProperty blastProperty = material.getProperty(PropertyKey.BLAST);
- if (blastProperty == null) return;
-
- if (!material.hasProperty(PropertyKey.FLUID)) return;
-
- // if there are more than 2 fluid-only components in the material, do not generate a hot fluid
- if (components.stream().filter(CommonEventListener::isMaterialStackFluidOnly).limit(3).count() > 2) {
- return;
- }
-
- material.setProperty(PropertyKey.ALLOY_BLAST, new AlloyBlastProperty(material.getBlastTemperature()));
- material.getProperty(PropertyKey.FLUID).getStorage().enqueueRegistration(FluidStorageKeys.MOLTEN,
- new FluidBuilder().state(FluidState.LIQUID));
- }
-
- private static boolean isMaterialStackFluidOnly(@NotNull MaterialStack ms) {
- return !ms.material().hasProperty(PropertyKey.DUST) && ms.material().hasProperty(PropertyKey.FLUID);
- }
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
index 68b203df551..ccd0d830521 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
@@ -128,6 +128,7 @@ public static void init() {
MaterialIconSet.init();
MaterialIconType.init();
initMaterials();
+ GTMedicalConditions.init();
TagPrefix.init();
GTSoundEntries.init();
GTDamageTypes.init();
diff --git a/src/main/java/com/gregtechceu/gtceu/common/capability/EnvironmentalHazardSavedData.java b/src/main/java/com/gregtechceu/gtceu/common/capability/EnvironmentalHazardSavedData.java
index c15fe81bafc..b47e9e9f210 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/capability/EnvironmentalHazardSavedData.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/capability/EnvironmentalHazardSavedData.java
@@ -1,9 +1,10 @@
package com.gregtechceu.gtceu.common.capability;
+import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.common.network.GTNetwork;
import com.gregtechceu.gtceu.common.network.packets.hazard.SPacketAddHazardZone;
import com.gregtechceu.gtceu.common.network.packets.hazard.SPacketRemoveHazardZone;
@@ -16,6 +17,7 @@
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
@@ -71,6 +73,9 @@ public EnvironmentalHazardSavedData(ServerLevel serverLevel, CompoundTag tag) {
ChunkPos source = new ChunkPos(zoneTag.getLong("pos"));
HazardZone zone = HazardZone.deserializeNBT(zoneTag);
+ if (zone == null) {
+ continue;
+ }
this.hazardZones.put(source, zone);
}
@@ -153,7 +158,7 @@ public void tickPlayerHazards(final HazardZone zone, Stream player
return;
}
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
if (tracker == null) {
return;
}
@@ -285,19 +290,22 @@ public CompoundTag serializeNBT(CompoundTag zoneTag) {
zoneTag.putFloat("strength", strength);
zoneTag.putBoolean("can_spread", canSpread);
zoneTag.putString("trigger", trigger.name());
- zoneTag.putString("condition", condition.name);
+ zoneTag.putString("condition", condition.id.toString());
return zoneTag;
}
- public static HazardZone deserializeNBT(CompoundTag zoneTag) {
+ public static @Nullable HazardZone deserializeNBT(CompoundTag zoneTag) {
BlockPos source = NbtUtils.readBlockPos(zoneTag.getCompound("source"));
float strength = zoneTag.getFloat("strength");
boolean canSpread = zoneTag.getBoolean("can_spread");
HazardProperty.HazardTrigger trigger = HazardProperty.HazardTrigger.ALL_TRIGGERS
.get(zoneTag.getString("trigger"));
- MedicalCondition condition = com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition.CONDITIONS
- .get(zoneTag.getString("condition"));
+ ResourceLocation id = GTCEu.id(zoneTag.getString("condition"));
+ if (!GTRegistries.MEDICAL_CONDITIONS.containKey(id)) {
+ return null;
+ }
+ MedicalCondition condition = GTRegistries.MEDICAL_CONDITIONS.get(id);
return new HazardZone(source, strength, canSpread, trigger, condition);
}
@@ -307,7 +315,7 @@ public void toNetwork(FriendlyByteBuf buf) {
buf.writeFloat(strength);
buf.writeBoolean(canSpread);
buf.writeUtf(trigger.name());
- buf.writeUtf(condition.name);
+ buf.writeResourceLocation(condition.id);
}
public static HazardZone fromNetwork(FriendlyByteBuf buf) {
@@ -315,7 +323,7 @@ public static HazardZone fromNetwork(FriendlyByteBuf buf) {
float strength = buf.readFloat();
boolean canSpread = buf.readBoolean();
HazardProperty.HazardTrigger trigger = HazardProperty.HazardTrigger.ALL_TRIGGERS.get(buf.readUtf());
- MedicalCondition condition = MedicalCondition.CONDITIONS.get(buf.readUtf());
+ MedicalCondition condition = GTRegistries.MEDICAL_CONDITIONS.get(buf.readResourceLocation());
return new HazardZone(source, strength, canSpread, trigger, condition);
}
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/capability/LocalizedHazardSavedData.java b/src/main/java/com/gregtechceu/gtceu/common/capability/LocalizedHazardSavedData.java
index 3e345aa7b74..497f787dfa2 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/capability/LocalizedHazardSavedData.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/capability/LocalizedHazardSavedData.java
@@ -1,10 +1,11 @@
package com.gregtechceu.gtceu.common.capability;
+import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.GTValues;
import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
import com.gregtechceu.gtceu.api.data.chemical.material.properties.HazardProperty;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.common.particle.HazardParticleOptions;
import com.gregtechceu.gtceu.config.ConfigHolder;
import com.gregtechceu.gtceu.utils.BreadthFirstBlockSearch;
@@ -14,6 +15,7 @@
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
+import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
@@ -119,7 +121,7 @@ public void tickPlayerHazards(final HazardZone zone, Stream player
return;
}
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
if (tracker == null) {
return;
}
@@ -318,7 +320,7 @@ public CompoundTag serializeNBT(CompoundTag zoneTag) {
zoneTag.put("blocks", blocksTag);
zoneTag.putBoolean("can_spread", canSpread);
zoneTag.putString("trigger", trigger.name());
- zoneTag.putString("condition", condition.name);
+ zoneTag.putString("condition", condition.id.toString());
return zoneTag;
}
@@ -331,7 +333,12 @@ public static HazardZone deserializeNBT(CompoundTag zoneTag) {
boolean canSpread = zoneTag.getBoolean("can_spread");
HazardProperty.HazardTrigger trigger = HazardProperty.HazardTrigger.ALL_TRIGGERS
.get(zoneTag.getString("trigger"));
- MedicalCondition condition = MedicalCondition.CONDITIONS.get(zoneTag.getString("condition"));
+
+ ResourceLocation id = GTCEu.id(zoneTag.getString("condition"));
+ if (!GTRegistries.MEDICAL_CONDITIONS.containKey(id)) {
+ return null;
+ }
+ MedicalCondition condition = GTRegistries.MEDICAL_CONDITIONS.get(id);
return new HazardZone(blocks, canSpread, trigger, condition);
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTracker.java b/src/main/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTracker.java
index 4a38d76fe08..b2754afada1 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTracker.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTracker.java
@@ -1,123 +1,137 @@
package com.gregtechceu.gtceu.common.capability;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
+import com.gregtechceu.gtceu.GTCEu;
+import com.gregtechceu.gtceu.api.GTValues;
+import com.gregtechceu.gtceu.api.capability.forge.GTCapability;
+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.MaterialEntry;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition.IdleProgressionType;
import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom;
+import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom.ConfiguredSymptom;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
+import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.player.Player;
-import net.minecraftforge.common.util.INBTSerializable;
+import net.minecraftforge.common.capabilities.Capability;
+import net.minecraftforge.common.capabilities.ICapabilitySerializable;
+import net.minecraftforge.common.util.LazyOptional;
-import it.unimi.dsi.fastutil.objects.Object2FloatMap;
-import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.*;
import lombok.Getter;
-import lombok.Setter;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.VisibleForTesting;
import java.util.*;
-public class MedicalConditionTracker implements IMedicalConditionTracker, INBTSerializable {
+public class MedicalConditionTracker implements ICapabilitySerializable {
@Getter
- private final Object2FloatMap medicalConditions = new Object2FloatOpenHashMap<>();
- private final Set permanentConditions = new HashSet<>();
- private final Object2IntMap activeSymptoms = new Object2IntOpenHashMap<>();
- private final Object2IntMap activeMobEffects = new Object2IntOpenHashMap<>();
-
- private final Set flaggedForRemoval = new HashSet<>();
+ @VisibleForTesting
+ final Reference2FloatOpenHashMap medicalConditions = new Reference2FloatOpenHashMap<>();
+ private final Set permanentConditions = new ReferenceOpenHashSet<>();
+ @Getter
+ private final Object2IntMap activeSymptoms = new Object2IntOpenHashMap<>();
+ private final Reference2IntMap activeMobEffects = new Reference2IntOpenHashMap<>();
- @Setter
- private int maxAirSupply = -1;
+ private final Set flaggedForRemoval = new ReferenceOpenHashSet<>();
@Getter
private final Player player;
+ private final LazyOptional holder = LazyOptional.of(() -> this);
+
public MedicalConditionTracker(Player player) {
this.player = player;
}
- @Override
public void tick() {
if (player.isCreative()) return;
- for (var entry : activeMobEffects.object2IntEntrySet()) {
+ for (var entry : activeMobEffects.reference2IntEntrySet()) {
player.addEffect(new MobEffectInstance(entry.getKey(), 100, entry.getIntValue()));
}
- if (player.level().getGameTime() % 20 == 0) { // apply idle progression every second
- for (MedicalCondition condition : medicalConditions.keySet()) {
- if (condition.idleProgressionType == MedicalCondition.IdleProgressionType.NONE) {
- continue;
- }
- if (permanentConditions.contains(condition) &&
- condition.idleProgressionType == MedicalCondition.IdleProgressionType.HEAL) {
- // can't automatically heal permanent conditions.
- continue;
- }
- int multiplier = (condition.idleProgressionType == MedicalCondition.IdleProgressionType.HEAL) ? -1 : 1;
- medicalConditions.replace(condition,
- medicalConditions.getFloat(condition) + condition.idleProgressionRate * multiplier);
- evaluateMedicalCondition(condition);
+ for (MedicalCondition condition : medicalConditions.keySet()) {
+ if (condition.idleProgressionType == IdleProgressionType.NONE ||
+ condition.idleProgressionRate == 0.0f) {
+ continue;
}
- if (!medicalConditions.isEmpty()) {
- updateActiveSymptoms();
+ if (permanentConditions.contains(condition) &&
+ condition.idleProgressionType == IdleProgressionType.HEAL) {
+ // can't automatically heal permanent conditions.
+ continue;
}
+ int multiplier = (condition.idleProgressionType == IdleProgressionType.HEAL) ? -1 : 1;
+ medicalConditions.addTo(condition, condition.idleProgressionRate * multiplier);
+ evaluateMedicalCondition(condition);
+ }
+ if (!medicalConditions.isEmpty()) {
+ updateActiveSymptoms();
}
}
- public void progressCondition(@NotNull MedicalCondition condition, float strength) {
- if (player.isCreative()) return;
+ public void progressRelatedCondition(@NotNull MaterialEntry materialEntry, int count) {
+ HazardProperty materialHazard = materialEntry.material().getProperty(PropertyKey.HAZARD);
+ float strength = (float) (materialEntry.getMaterialAmount() / GTValues.M) * count *
+ materialHazard.progressionMultiplier;
+ progressCondition(materialHazard.condition, strength);
+ }
- medicalConditions.put(condition, medicalConditions.getOrDefault(condition, 0) + strength);
+ public void progressCondition(@NotNull MedicalCondition condition, float progression) {
+ if (player.isCreative()) return;
+ medicalConditions.addTo(condition, progression);
updateActiveSymptoms();
}
- private void updateActiveSymptoms() {
+ @VisibleForTesting
+ void updateActiveSymptoms() {
for (MedicalCondition condition : medicalConditions.keySet()) {
if (medicalConditions.getFloat(condition) >= condition.maxProgression * 2) {
// If condition has been applied for 2x the maximum time, make it permanent.
permanentConditions.add(condition);
}
- for (Symptom.ConfiguredSymptom symptom : condition.symptoms) {
+ for (ConfiguredSymptom symptom : condition.symptoms) {
+ int lastStage = activeSymptoms.getInt(symptom);
int stage = calculateStage(condition, symptom);
if (stage <= 0) {
continue;
}
- symptom.symptom.tick(this, condition, symptom, stage);
+ Symptom baseSymptom = symptom.getSymptom();
+ baseSymptom.tick(this, condition, symptom, stage);
- Optional currentSymptomOptional = activeSymptoms.keySet()
+ Optional maybeExistingSymptom = activeSymptoms.keySet()
.stream()
- .filter(symptom1 -> symptom1.symptom == symptom.symptom)
+ .filter(s -> s.getSymptom() == baseSymptom)
.findFirst();
- if (currentSymptomOptional.isEmpty()) {
+ if (maybeExistingSymptom.isEmpty()) {
activeSymptoms.put(symptom, stage);
- symptom.symptom.applyProgression(this, condition, null, stage);
+ baseSymptom.applyProgression(this, condition, symptom, stage);
continue;
}
- Symptom.ConfiguredSymptom currentSymptom = currentSymptomOptional.get();
- if (currentSymptom == symptom && stage > activeSymptoms.getOrDefault(symptom, 0)) {
- symptom.symptom.applyProgression(this, condition, symptom,
- activeSymptoms.getOrDefault(symptom, 0));
- activeSymptoms.replace(symptom, stage);
- symptom.symptom.applyProgression(this, condition, symptom, stage);
+ ConfiguredSymptom existingSymptom = maybeExistingSymptom.get();
+ int existingStage = activeSymptoms.getInt(existingSymptom);
+ if (existingSymptom == symptom && stage > lastStage) {
+ activeSymptoms.put(symptom, stage);
+ baseSymptom.applyProgression(this, condition, symptom, stage);
continue;
}
- if (symptom.relativeHarshness * stage >
- currentSymptom.relativeHarshness * activeSymptoms.getOrDefault(currentSymptom, 0)) {
- currentSymptom.symptom.applyProgression(this, condition, symptom,
- activeSymptoms.getOrDefault(currentSymptom, 0));
- activeSymptoms.removeInt(currentSymptom);
+ if (symptom.getRelativeHarshness() * stage > existingSymptom.getRelativeHarshness() * existingStage) {
+ activeSymptoms.removeInt(existingSymptom);
activeSymptoms.put(symptom, stage);
- symptom.symptom.applyProgression(this, condition, symptom, stage);
+ baseSymptom.applyProgression(this, condition, symptom, stage);
}
}
}
@@ -126,25 +140,41 @@ private void updateActiveSymptoms() {
return;
}
for (MedicalCondition condition : flaggedForRemoval) {
- for (Symptom.ConfiguredSymptom configuredSymptom : activeSymptoms.keySet().stream()
- .filter(condition.symptoms::contains).toList()) {
- // reset all symptom effects for this condition
- configuredSymptom.symptom.applyProgression(this, condition, configuredSymptom, 0);
+ Set toRemove = new HashSet<>();
+ activeSymptoms.keySet().stream()
+ .filter(condition.symptoms::contains)
+ .forEach(symptom -> {
+ // reset all symptom effects for this condition
+ symptom.getSymptom().applyProgression(this, condition, symptom, 0);
+ toRemove.add(symptom);
+ });
+ for (ConfiguredSymptom symptom : toRemove) {
+ activeSymptoms.removeInt(symptom);
}
+
medicalConditions.removeFloat(condition);
}
flaggedForRemoval.clear();
}
- @Override
public void removeMedicalCondition(MedicalCondition condition) {
flaggedForRemoval.add(condition);
permanentConditions.remove(condition);
}
- private int calculateStage(MedicalCondition condition, Symptom.ConfiguredSymptom symptom) {
- return (int) Math.floor(Math.min(medicalConditions.getFloat(condition), condition.maxProgression) /
- (symptom.progressionThreshold * condition.maxProgression * symptom.stages));
+ private int calculateStage(MedicalCondition condition, ConfiguredSymptom symptom) {
+ float minThreshold = symptom.getMinThreshold();
+ float maxThreshold = symptom.getMaxThreshold();
+ float progression = medicalConditions.getFloat(condition);
+
+ if (progression < minThreshold) {
+ return 0;
+ }
+ if (progression >= maxThreshold) {
+ return symptom.getStages();
+ }
+ float delta = Mth.inverseLerp(Math.min(progression, condition.maxProgression), minThreshold, maxThreshold);
+ return (int) (delta * symptom.getStages());
}
// removes MedicalConditions without progression
@@ -163,28 +193,21 @@ private void evaluateMedicalCondition(MedicalCondition condition) {
* @param condition MedicalCondition to heal
* @param progression amount of progression to decrease
*/
- @Override
public void heal(MedicalCondition condition, int progression) {
- if (progression >= medicalConditions.getOrDefault(condition, 0)) {
+ if (progression >= medicalConditions.getFloat(condition)) {
medicalConditions.removeFloat(condition);
permanentConditions.remove(condition);
return;
}
- medicalConditions.replace(condition, medicalConditions.getOrDefault(condition, 0) - progression);
+ medicalConditions.addTo(condition, -progression);
}
- @Override
- public int getMaxAirSupply() {
- return maxAirSupply;
- }
-
- @Override
public void setMobEffect(MobEffect effect, int amplifier) {
if (amplifier <= 0) {
activeMobEffects.removeInt(effect);
- } else if (amplifier >= activeMobEffects.getOrDefault(effect, -1)) {
- activeMobEffects.put(effect, amplifier);
+ return;
}
+ activeMobEffects.mergeInt(effect, amplifier, Math::max);
}
@Override
@@ -192,9 +215,9 @@ public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
ListTag effectsTag = new ListTag();
- for (var entry : medicalConditions.object2FloatEntrySet()) {
+ for (var entry : medicalConditions.reference2FloatEntrySet()) {
CompoundTag medicalConditionTag = new CompoundTag();
- medicalConditionTag.putString("condition", entry.getKey().name);
+ medicalConditionTag.putString("condition", entry.getKey().id.toString());
medicalConditionTag.putFloat("progression", entry.getFloatValue());
effectsTag.add(medicalConditionTag);
}
@@ -202,7 +225,7 @@ public CompoundTag serializeNBT() {
ListTag permanentsTag = new ListTag();
for (MedicalCondition condition : permanentConditions) {
- permanentsTag.add(StringTag.valueOf(condition.name));
+ permanentsTag.add(StringTag.valueOf(condition.id.toString()));
}
tag.put("permanent_conditions", permanentsTag);
@@ -211,10 +234,19 @@ public CompoundTag serializeNBT() {
@Override
public void deserializeNBT(CompoundTag arg) {
+ // ensure the medical condition map(s) is actually empty before loading.
+ // IDK if this actually happens, but better be safe than sorry.
+ medicalConditions.clear();
+ permanentConditions.clear();
+
ListTag medicalConditionsTag = arg.getList("medical_conditions", Tag.TAG_COMPOUND);
for (int i = 0; i < medicalConditionsTag.size(); ++i) {
CompoundTag compoundTag = medicalConditionsTag.getCompound(i);
- MedicalCondition condition = MedicalCondition.CONDITIONS.get(compoundTag.getString("condition"));
+ ResourceLocation id = GTCEu.id(compoundTag.getString("condition"));
+ if (!GTRegistries.MEDICAL_CONDITIONS.containKey(id)) {
+ continue;
+ }
+ MedicalCondition condition = GTRegistries.MEDICAL_CONDITIONS.get(id);
float progression = compoundTag.getFloat("progression");
medicalConditions.put(condition, progression);
@@ -222,7 +254,16 @@ public void deserializeNBT(CompoundTag arg) {
ListTag permanentConditionsTag = arg.getList("permanent_conditions", Tag.TAG_STRING);
for (int i = 0; i < permanentConditionsTag.size(); ++i) {
- permanentConditions.add(MedicalCondition.CONDITIONS.get(permanentConditionsTag.getString(i)));
+ ResourceLocation id = GTCEu.id(permanentConditionsTag.getString(i));
+ if (!GTRegistries.MEDICAL_CONDITIONS.containKey(id)) {
+ continue;
+ }
+ permanentConditions.add(GTRegistries.MEDICAL_CONDITIONS.get(id));
}
}
+
+ @Override
+ public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) {
+ return GTCapability.CAPABILITY_MEDICAL_CONDITION_TRACKER.orEmpty(cap, this.holder);
+ }
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java b/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java
index 3b9463eb764..49c7a7f71bb 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/commands/GTCommands.java
@@ -96,7 +96,7 @@ public static void register(CommandDispatcher dispatcher, Co
GTOreDefinition.FULL_CODEC,
GTOreLoader.FOLDER))))
.then(literal("place_vein")
- .requires(ctx -> ctx.hasPermission(LEVEL_ADMINS))
+ .requires(ctx -> ctx.hasPermission(LEVEL_GAMEMASTERS))
.then(argument("vein", GTRegistryArgument.registry(GTRegistries.ORE_VEINS, ResourceLocation.class))
.executes(context -> {
return GTCommands.placeVein(context, BlockPos.containing(context.getSource().getPosition()));
diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/MedicalConditionCommands.java b/src/main/java/com/gregtechceu/gtceu/common/commands/MedicalConditionCommands.java
index 602408e1666..3055c97a4ac 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/commands/MedicalConditionCommands.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/commands/MedicalConditionCommands.java
@@ -1,8 +1,9 @@
package com.gregtechceu.gtceu.common.commands;
import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom;
+import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker;
import com.gregtechceu.gtceu.common.commands.arguments.MedicalConditionArgument;
import net.minecraft.commands.CommandBuildContext;
@@ -15,6 +16,7 @@
import com.mojang.brigadier.arguments.FloatArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -25,9 +27,11 @@
public class MedicalConditionCommands {
private static final SimpleCommandExceptionType ERROR_CLEAR_EVERYTHING_FAILED = new SimpleCommandExceptionType(
- Component.translatable("commands.effect.clear.everything.failed"));
+ Component.translatable("command.gtceu.medical_condition.clear.everything.failed"));
private static final SimpleCommandExceptionType ERROR_GIVE_FAILED = new SimpleCommandExceptionType(
- Component.translatable("commands.effect.give.failed"));
+ Component.translatable("command.gtceu.medical_condition.give.failed"));
+ private static final SimpleCommandExceptionType ERROR_CLEAR_SPECIFIC_FAILED = new SimpleCommandExceptionType(
+ Component.translatable("command.gtceu.medical_condition.clear.specific.failed"));
// spotless:off
public static void register(CommandDispatcher dispatcher, CommandBuildContext buildContext) {
@@ -35,122 +39,200 @@ public static void register(CommandDispatcher dispatcher, Co
literal("medical_condition")
.then(literal("query")
.executes(ctx -> {
- return queryMedicalConditions(ctx.getSource().getPlayerOrException());
+ return queryMedicalConditions(ctx.getSource(), ctx.getSource().getPlayerOrException());
})
.then(argument("target", EntityArgument.player())
.requires(source -> source.hasPermission(LEVEL_GAMEMASTERS))
.executes(context -> {
- return queryMedicalConditions(EntityArgument.getPlayer(context, "target"));
- })))
+ return queryMedicalConditions(context.getSource(), EntityArgument.getPlayer(context, "target"));
+ }))
+ .then(literal("symptoms")
+ .executes(ctx -> {
+ return querySymptoms(ctx.getSource(), ctx.getSource().getPlayerOrException());
+ })
+ .then(argument("target", EntityArgument.player())
+ .requires(source -> source.hasPermission(LEVEL_GAMEMASTERS))
+ .executes(context -> {
+ return querySymptoms(context.getSource(), EntityArgument.getPlayer(context, "target"));
+ }))))
.then(literal("clear")
- .requires(ctx -> ctx.hasPermission(LEVEL_ADMINS))
+ .requires(ctx -> ctx.hasPermission(LEVEL_GAMEMASTERS))
.executes(ctx -> {
- return clearMedicalConditions(
- Collections.singleton(ctx.getSource().getPlayerOrException()), null);
+ return clearMedicalConditions(ctx.getSource(), Collections.singleton(ctx.getSource().getPlayerOrException()), null);
})
.then(argument("targets", EntityArgument.players())
.executes(ctx -> {
- return clearMedicalConditions(EntityArgument.getPlayers(ctx, "targets"),
- null);
+ return clearMedicalConditions(ctx.getSource(), EntityArgument.getPlayers(ctx, "targets"), null);
})
.then(argument("condition", MedicalConditionArgument.medicalCondition())
.executes(ctx -> {
- Collection targets = EntityArgument.getPlayers(ctx,
- "targets");
- MedicalCondition condition = MedicalConditionArgument
- .getCondition(ctx, "condition");
- return clearMedicalConditions(targets, condition);
+ Collection targets = EntityArgument.getPlayers(ctx, "targets");
+ MedicalCondition condition = MedicalConditionArgument.getCondition(ctx, "condition");
+ return clearMedicalConditions(ctx.getSource(), targets, condition);
}))))
.then(literal("apply")
.requires(ctx -> ctx.hasPermission(LEVEL_GAMEMASTERS))
.then(argument("targets", EntityArgument.players())
.then(argument("condition", MedicalConditionArgument.medicalCondition())
.executes(ctx -> {
- MedicalCondition condition = MedicalConditionArgument
- .getCondition(ctx, "condition");
- Collection players = EntityArgument.getPlayers(ctx,
- "targets");
- return applyMedicalConditions(players, condition, 1);
+ MedicalCondition condition = MedicalConditionArgument.getCondition(ctx, "condition");
+ Collection players = EntityArgument.getPlayers(ctx, "targets");
+ return applyMedicalConditions(ctx.getSource(), players, condition, 20);
})
- .then(argument("progression_multiplier", FloatArgumentType.floatArg(0))
+ .then(argument("progression", FloatArgumentType.floatArg())
.executes(ctx -> {
- MedicalCondition condition = MedicalConditionArgument
- .getCondition(ctx, "condition");
- Collection players = EntityArgument
- .getPlayers(ctx, "targets");
- float strength = FloatArgumentType.getFloat(ctx,
- "progression_multiplier");
- return applyMedicalConditions(players, condition, strength);
+ MedicalCondition condition = MedicalConditionArgument.getCondition(ctx, "condition");
+ Collection players = EntityArgument.getPlayers(ctx, "targets");
+ float progression = FloatArgumentType.getFloat(ctx, "progression");
+ return applyMedicalConditions(ctx.getSource(), players, condition, progression);
}))))));
}
- // spotless:off
+ // spotless:on
- private static int queryMedicalConditions(ServerPlayer target) throws CommandSyntaxException {
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(target);
- if (tracker == null) {
- throw EntityArgument.NO_PLAYERS_FOUND.create();
- }
- int count = tracker.getMedicalConditions().size();
- if (count == 0) {
- target.sendSystemMessage(
- Component.translatable("command.gtceu.medical_condition.get.empty", target.getName()));
+ private static int queryMedicalConditions(CommandSourceStack source,
+ ServerPlayer target) throws CommandSyntaxException {
+ MedicalConditionTracker tracker = getMedicalConditionTracker(target);
+
+ int conditions = tracker.getMedicalConditions().size();
+ if (conditions == 0) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.get.empty", target.getName());
+ }, false);
+ return 0;
} else {
- target.sendSystemMessage(
- Component.translatable("command.gtceu.medical_condition.get", target.getName()));
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.get", target.getName());
+ }, false);
}
- for (var entry : tracker.getMedicalConditions().object2FloatEntrySet()) {
- String langKey = "command.gtceu.medical_condition.get.element";
- if (entry.getKey().maxProgression * 2 <= entry.getFloatValue() &&
- entry.getKey().canBePermanent) {
+ for (var entry : tracker.getMedicalConditions().reference2FloatEntrySet()) {
+ String langKey;
+ if (!entry.getKey().canBePermanent || entry.getFloatValue() < entry.getKey().maxProgression * 2) {
+ langKey = "command.gtceu.medical_condition.get.element";
+ } else {
langKey = "command.gtceu.medical_condition.get.element.permanent";
}
float time = entry.getFloatValue();
- target.sendSystemMessage(
- Component.translatable(langKey,
- Component.translatable("gtceu.medical_condition." + entry.getKey().name),
- (int) (time / 60), (int) (time % 60)));
+ source.sendSuccess(() -> {
+ return Component.translatable(langKey,
+ entry.getKey().getAffectedName(), (int) (time / 60), (int) (time % 60));
+ }, false);
}
- return count;
+ return conditions;
}
- private static int clearMedicalConditions(Collection targets,
+ private static int querySymptoms(CommandSourceStack source, ServerPlayer target) throws CommandSyntaxException {
+ MedicalConditionTracker tracker = getMedicalConditionTracker(target);
+
+ int symptoms = tracker.getActiveSymptoms().size();
+ if (symptoms == 0) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.get.symptoms.empty", target.getName());
+ }, false);
+ return 0;
+ } else {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.get.symptoms", target.getName());
+ }, false);
+ }
+ for (Symptom.ConfiguredSymptom symptom : tracker.getActiveSymptoms().keySet()) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.get.symptoms.element",
+ Component.translatable(symptom.getSymptom().name));
+ }, false);
+ }
+ return symptoms;
+ }
+
+ private static int clearMedicalConditions(CommandSourceStack source, Collection targets,
@Nullable MedicalCondition condition) throws CommandSyntaxException {
- int count = 0;
+ int removed = 0;
for (ServerPlayer target : targets) {
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(target);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(target);
if (tracker == null) {
continue;
}
if (condition == null) {
- count += tracker.getMedicalConditions().keySet().size();
+ removed += tracker.getMedicalConditions().size();
for (MedicalCondition medicalCondition : tracker.getMedicalConditions().keySet()) {
tracker.removeMedicalCondition(medicalCondition);
}
} else {
- count++;
+ removed++;
tracker.removeMedicalCondition(condition);
}
}
- if (count == 0) {
- throw ERROR_CLEAR_EVERYTHING_FAILED.create();
+
+ if (removed == 0) {
+ if (condition == null) {
+ throw ERROR_CLEAR_EVERYTHING_FAILED.create();
+ } else {
+ throw ERROR_CLEAR_SPECIFIC_FAILED.create();
+ }
+ }
+ if (targets.size() == 1) {
+ if (condition == null) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.clear.everything.success.single",
+ targets.iterator().next().getDisplayName());
+ }, true);
+ } else {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.clear.specific.success.single",
+ condition.getAffectedName(), targets.iterator().next().getDisplayName());
+ }, true);
+ }
+ } else {
+ if (condition == null) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.clear.everything.success.multiple",
+ targets.size());
+ }, true);
+ } else {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.clear.specific.success.multiple",
+ condition.getAffectedName(), targets.size());
+ }, true);
+ }
}
- return count;
+
+ return removed;
}
- private static int applyMedicalConditions(Collection targets, MedicalCondition condition,
- float strength) throws CommandSyntaxException {
- int success = 0;
+ private static int applyMedicalConditions(CommandSourceStack source, Collection targets,
+ MedicalCondition condition,
+ float progression) throws CommandSyntaxException {
+ int applied = 0;
for (ServerPlayer player : targets) {
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
if (tracker == null) {
continue;
}
- tracker.progressCondition(condition, strength);
- success++;
+ tracker.progressCondition(condition, progression);
+ applied++;
}
- if (success == 0) {
+ if (applied == 0) {
throw ERROR_GIVE_FAILED.create();
}
- return success;
+
+ if (targets.size() == 1) {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.give.success.single",
+ condition.getAffectedName(), targets.iterator().next().getDisplayName());
+ }, true);
+ } else {
+ source.sendSuccess(() -> {
+ return Component.translatable("command.gtceu.medical_condition.give.success.multiple",
+ condition.getAffectedName(), targets.size());
+ }, true);
+ }
+ return applied;
+ }
+
+ private static @NotNull MedicalConditionTracker getMedicalConditionTracker(@Nullable ServerPlayer target) throws CommandSyntaxException {
+ if (target == null) throw EntityArgument.NO_PLAYERS_FOUND.create();
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(target);
+ if (tracker == null) throw EntityArgument.NO_PLAYERS_FOUND.create();
+
+ return tracker;
}
}
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
index 1f200964014..1fd78749b78 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MaterialParser.java
@@ -14,7 +14,6 @@
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;
@@ -71,12 +70,14 @@ public static CompletableFuture fillSuggestions(IMaterialRegistryMa
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(() -> {
+ ResourceLocation id = ResourceLocation.read(this.reader);
+
+ Material material = this.materials.getRegistry(id.getNamespace()).get(id.getPath());
+ if (material == null || material.isNull()) {
this.reader.setCursor(i);
- return ERROR_UNKNOWN_ITEM.createWithContext(this.reader, resourceLocation);
- });
+ throw ERROR_UNKNOWN_ITEM.createWithContext(this.reader, id);
+ }
+ this.result = material;
}
private void parse() throws CommandSyntaxException {
diff --git a/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MedicalConditionParser.java b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MedicalConditionParser.java
index 201b06a4fbc..596557038f8 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MedicalConditionParser.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/commands/arguments/MedicalConditionParser.java
@@ -1,6 +1,7 @@
package com.gregtechceu.gtceu.common.commands.arguments;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.network.chat.Component;
@@ -12,7 +13,6 @@
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;
@@ -59,16 +59,14 @@ public static CompletableFuture fillSuggestions(SuggestionsBuilder
private void readMedicalCondition() throws CommandSyntaxException {
int i = this.reader.getCursor();
+ ResourceLocation id = ResourceLocation.read(this.reader);
- while (reader.canRead() && ResourceLocation.isAllowedInResourceLocation(reader.peek())) {
- reader.skip();
- }
- String name = reader.getString().substring(i, reader.getCursor());
- MedicalCondition material = MedicalCondition.CONDITIONS.get(name);
- this.result = Optional.ofNullable(material).orElseThrow(() -> {
+ MedicalCondition condition = GTRegistries.MEDICAL_CONDITIONS.get(id);
+ if (condition == null) {
this.reader.setCursor(i);
- return ERROR_UNKNOWN_ITEM.createWithContext(this.reader, name);
- });
+ throw ERROR_UNKNOWN_ITEM.createWithContext(this.reader, id.toString());
+ }
+ this.result = condition;
}
private void parse() throws CommandSyntaxException {
@@ -77,6 +75,6 @@ private void parse() throws CommandSyntaxException {
}
private CompletableFuture suggestMedicalCondition(SuggestionsBuilder builder) {
- return SharedSuggestionProvider.suggest(MedicalCondition.CONDITIONS.keySet(), builder);
+ return SharedSuggestionProvider.suggestResource(GTRegistries.MEDICAL_CONDITIONS.keys(), builder);
}
}
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 4ce5ab3e790..7cef69333c5 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java
@@ -2337,8 +2337,8 @@ public static ItemEntry createFluidCell(Material mat, int capacit
.tag(Tags.Items.ARMORS_HELMETS)
.tag(CustomTags.PPE_ARMOR)
.onRegister(attach(new TooltipBehavior(tooltips -> {
- tooltips.add(Component.translatable("gtceu.hazard_trigger.protection.description"));
- tooltips.add(Component.translatable("gtceu.hazard_trigger.inhalation"));
+ tooltips.add(Component.translatable("tooltip.gtceu.hazard_trigger.protection"));
+ tooltips.add(Component.translatable("tooltip.gtceu.hazard_trigger.inhalation"));
})))
.register();
public static ItemEntry RUBBER_GLOVES = REGISTRATE
@@ -2349,8 +2349,8 @@ public static ItemEntry createFluidCell(Material mat, int capacit
.tag(Tags.Items.ARMORS_CHESTPLATES)
.tag(CustomTags.PPE_ARMOR)
.onRegister(attach(new TooltipBehavior(tooltips -> {
- tooltips.add(Component.translatable("gtceu.hazard_trigger.protection.description"));
- tooltips.add(Component.translatable("gtceu.hazard_trigger.skin_contact"));
+ tooltips.add(Component.translatable("tooltip.gtceu.hazard_trigger.protection"));
+ tooltips.add(Component.translatable("tooltip.gtceu.hazard_trigger.skin_contact"));
})))
.register();
public static ItemEntry HAZMAT_CHESTPLATE = REGISTRATE
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMedicalConditions.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMedicalConditions.java
index 5781aec5d5c..795b25d83d9 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/data/GTMedicalConditions.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMedicalConditions.java
@@ -1,100 +1,153 @@
package com.gregtechceu.gtceu.common.data;
+import com.gregtechceu.gtceu.GTCEu;
+import com.gregtechceu.gtceu.api.GTCEuAPI;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
+
+import net.minecraft.resources.ResourceLocation;
+import net.minecraftforge.fml.ModLoader;
import static com.gregtechceu.gtceu.api.data.tag.TagPrefix.dust;
import static com.gregtechceu.gtceu.common.data.GTMaterials.*;
public class GTMedicalConditions {
+ static {
+ GTRegistries.MEDICAL_CONDITIONS.unfreeze();
+ }
+
// General Conditions
- public static final MedicalCondition NONE = new MedicalCondition("none", 0xffffff, 0);
- public static final MedicalCondition CHEMICAL_BURNS = new MedicalCondition("chemical_burns", 0xbc305a, 200,
+ public static final MedicalCondition NONE = register("none", 0xffffff, 0,
+ MedicalCondition.IdleProgressionType.NONE, 0, false);
+ // takes 5 minutes of having burn-causing items in the player's inventory for them to get the weakness effect
+ // heals 2 seconds' worth of progression every second when not holding those items
+ public static final MedicalCondition CHEMICAL_BURNS = register("chemical_burns", 0xbc305a, 300,
MedicalCondition.IdleProgressionType.HEAL, 2, false,
new Symptom.ConfiguredSymptom(Symptom.WEAKNESS))
.setRecipeModifier(builder -> builder
.outputFluids(DilutedHydrochloricAcid.getFluid(500))
.outputFluids(DilutedSulfuricAcid.getFluid(750)));
- public static final MedicalCondition POISON = new MedicalCondition("poison", 0xA36300, 600,
+ // takes 5 minutes of having poisonous items in the player's inventory for them to get the weakness effect
+ // at 10 minutes, they get a weaker version of the poison effect
+ // heals 2 seconds' worth of progression every second when not holding those items
+ public static final MedicalCondition POISON = register("poison", 0xA36300, 600,
MedicalCondition.IdleProgressionType.HEAL, 2, true,
new Symptom.ConfiguredSymptom(Symptom.WEAK_POISONING),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, .5f))
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 300, 600))
.setRecipeModifier(builder -> builder
.outputFluids(SulfurTrioxide.getFluid(1000)));
- public static final MedicalCondition WEAK_POISON = new MedicalCondition("weak_poison", 0x6D7917, 3000,
+ // having weakly poisonous items in the player's inventory gives them the weak poison effect
+ // the effect ramps up in 6 "stages", getting progressively worse every stage. It caps out at Weak Poison 10.
+ // does NOT heal automatically
+ public static final MedicalCondition WEAK_POISON = register("weak_poison", 0x6D7917, 1800,
MedicalCondition.IdleProgressionType.NONE, 0, false,
- new Symptom.ConfiguredSymptom(Symptom.WEAK_POISONING, 6, .3f))
+ new Symptom.ConfiguredSymptom(Symptom.WEAK_POISONING, 6, 1800))
.setRecipeModifier(builder -> builder
.outputFluids(NitricOxide.getFluid(1000)));
- public static final MedicalCondition IRRITANT = new MedicalCondition("irritant", 0x02512f, 600,
+ // takes 2.5 minutes of having irritating items in the player's inventory for them to get the weakness effect
+ // at 5 minutes, they begin getting random damage every so often
+ // heals 5 seconds' worth of progression every second when not holding those items
+ public static final MedicalCondition IRRITANT = register("irritant", 0x02512f, 600,
MedicalCondition.IdleProgressionType.HEAL, 5, false,
new Symptom.ConfiguredSymptom(Symptom.RANDOM_DAMAGE),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 0.5f))
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 300, 600))
.setRecipeModifier(builder -> builder
.outputItems(dust, DarkAsh, 4));
- public static final MedicalCondition NAUSEA = new MedicalCondition("nausea", 0x1D4A00, 600,
+ // takes 5 minutes of having nauseating items in the player's inventory for them to get the nausea effect
+ // heals 5 seconds' worth of progression every second when not holding those items
+ public static final MedicalCondition NAUSEA = register("nausea", 0x1D4A00, 600,
MedicalCondition.IdleProgressionType.HEAL, 5, false,
- new Symptom.ConfiguredSymptom(Symptom.NAUSEA))
+ new Symptom.ConfiguredSymptom(Symptom.NAUSEA, 1, 420, 600))
.setRecipeModifier(builder -> builder
.outputFluids(CarbonMonoxide.getFluid(50)));
- public static final MedicalCondition CARCINOGEN = new MedicalCondition("carcinogen", 0x0f570f, 20000,
+ /**
+ * All effects:
+ *
+ * - After an hour, the player's attack damage and mining speed will start lowering.
+ * - After 2 hours, the player's max air supply and movement speed will start lowering.
+ * - After 3 hours, the player's max health will start lowering.
+ * - After 4 hours, the player's attack damage and mining speed are at their lowest.
+ * - After 5 hours, the player will have the lowest max air supply of 200/300 (so 6/10 bubbles) and their speed is
+ * at its lowest.
+ * - After 6 hours, the player will have the lowest max HP of 10/20 (so 5/10 hearts).
+ * - After 10 real-life hours (30 MC days) of having cancer, the player will die.
+ *
+ *
+ * Do note that while the effects do not get worse when the player isn't holding anything radioactive,
+ * the progression they've already gained will stay as is and reactivate if they pick up e.g. a uranium ingot.
+ *
+ * This condition does NOT heal automatically. You can use {@linkplain GTItems#RAD_AWAY_PILL
+ * rad-away pills} to heal it.
+ */
+ public static final MedicalCondition CARCINOGEN = register("carcinogen", 0x0f570f, 36000,
MedicalCondition.IdleProgressionType.NONE, 0, true,
new Symptom.ConfiguredSymptom(Symptom.DEATH),
- new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, .75f),
- new Symptom.ConfiguredSymptom(Symptom.AIR_SUPPLY_DEBUFF, .5f),
- new Symptom.ConfiguredSymptom(Symptom.MINING_FATIGUE, .4f),
- new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, .4f),
- new Symptom.ConfiguredSymptom(Symptom.HUNGER, .3f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, .2f));
+ new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, 10800, 21600),
+ new Symptom.ConfiguredSymptom(Symptom.AIR_SUPPLY_DEBUFF, 7200, 18000),
+ new Symptom.ConfiguredSymptom(Symptom.MINING_FATIGUE, 3600, 14400),
+ new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 7200, 18000),
+ // new Symptom.ConfiguredSymptom(Symptom.HUNGER, 0, 10800),
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 3600, 14400));
// Material specific Conditions
- public static final MedicalCondition ASBESTOSIS = new MedicalCondition("asbestosis", 0xe3e3e3, 5000,
+ public static final MedicalCondition ASBESTOSIS = register("asbestosis", 0xe3e3e3, 5000,
MedicalCondition.IdleProgressionType.HEAL, 1, true,
- new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, .6f),
- new Symptom.ConfiguredSymptom(Symptom.AIR_SUPPLY_DEBUFF, .3f),
- new Symptom.ConfiguredSymptom(Symptom.HUNGER, .2f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, .2f))
+ // new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, 3000, 5000),
+ // new Symptom.ConfiguredSymptom(Symptom.AIR_SUPPLY_DEBUFF, 1500, 3500),
+ // new Symptom.ConfiguredSymptom(Symptom.HUNGER, 500, 4000),
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 1200, 5000))
.setRecipeModifier(builder -> builder
.outputItems(dust, Asbestos, 4));
- public static final MedicalCondition ARSENICOSIS = new MedicalCondition("arsenicosis", 0xbd4b15, 1000,
+ public static final MedicalCondition ARSENICOSIS = register("arsenicosis", 0xbd4b15, 1000,
MedicalCondition.IdleProgressionType.HEAL, 1, true,
new Symptom.ConfiguredSymptom(Symptom.WITHER),
- new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, .6f),
- new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 2, .5f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, .3f),
- new Symptom.ConfiguredSymptom(Symptom.HUNGER, 2, .2f),
- new Symptom.ConfiguredSymptom(Symptom.NAUSEA, .1f))
+ new Symptom.ConfiguredSymptom(Symptom.NAUSEA),
+ new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 2, 500, 1000),
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, 330, 1000))
+ // new Symptom.ConfiguredSymptom(Symptom.HUNGER, 2, .2f))
.setRecipeModifier(builder -> builder
.outputItems(dust, Arsenic, 4));
- public static final MedicalCondition SILICOSIS = new MedicalCondition("silicosis", 0x5d6c91, 15000,
- MedicalCondition.IdleProgressionType.HEAL, .5f, true,
- new Symptom.ConfiguredSymptom(Symptom.HEALTH_DEBUFF, 4, .75f),
- new Symptom.ConfiguredSymptom(Symptom.AIR_SUPPLY_DEBUFF, .6f))
- .setRecipeModifier(builder -> builder
- .outputItems(dust, SiliconDioxide, 4));
- public static final MedicalCondition BERYLLIOSIS = new MedicalCondition("berylliosis", 0x0c6539, 10000,
- MedicalCondition.IdleProgressionType.HEAL, .5f, true,
- new Symptom.ConfiguredSymptom(Symptom.WITHER),
- new Symptom.ConfiguredSymptom(Symptom.RANDOM_DAMAGE, 1, .7f),
- new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 2, .5f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, .4f))
- .setRecipeModifier(builder -> builder
- .outputItems(dust, Beryllium, 4));
- public static final MedicalCondition METHANOL_POISONING = new MedicalCondition("methanol_poisoning", 0xaa8800, 500,
+ public static final MedicalCondition METHANOL_POISONING = register("methanol_poisoning", 0xaa8800, 600,
MedicalCondition.IdleProgressionType.HEAL, .5f, true,
new Symptom.ConfiguredSymptom(Symptom.POISONING),
- new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 1, .75f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, .5f),
- new Symptom.ConfiguredSymptom(Symptom.BLINDNESS, 2, .25f))
+ new Symptom.ConfiguredSymptom(Symptom.BLINDNESS, 2, 450, 600),
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, 300, 600),
+ new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 1, 150, 600))
.setRecipeModifier(builder -> builder
.outputFluids(Methanol.getFluid(1000)));
- public static final MedicalCondition CARBON_MONOXIDE_POISONING = new MedicalCondition("carbon_monoxide_poisoning",
+ public static final MedicalCondition CARBON_MONOXIDE_POISONING = register("carbon_monoxide_poisoning",
0x041525, 2000, MedicalCondition.IdleProgressionType.HEAL, 1, true,
new Symptom.ConfiguredSymptom(Symptom.DEATH),
- new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 2, .75f),
- new Symptom.ConfiguredSymptom(Symptom.NAUSEA, 2, .5f),
- new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, .25f))
+ new Symptom.ConfiguredSymptom(Symptom.NAUSEA),
+ new Symptom.ConfiguredSymptom(Symptom.SLOWNESS, 2, 1500, 2000),
+ new Symptom.ConfiguredSymptom(Symptom.WEAKNESS, 2, 500, 2000))
.setRecipeModifier(builder -> builder
.outputFluids(CarbonMonoxide.getFluid(1000)));
+
+ public static MedicalCondition register(ResourceLocation id, int color,
+ int maxProgression, MedicalCondition.IdleProgressionType progressionType,
+ float progressionRate, boolean canBePermanent,
+ Symptom.ConfiguredSymptom... symptoms) {
+ var condition = new MedicalCondition(id, color, maxProgression,
+ progressionType, progressionRate, canBePermanent, symptoms);
+ GTRegistries.MEDICAL_CONDITIONS.register(id, condition);
+ return condition;
+ }
+
+ // internal variant of the above that skips having to write `register(GTCEu.id(...`
+ private static MedicalCondition register(String id, int color,
+ int maxProgression, MedicalCondition.IdleProgressionType progressionType,
+ float progressionRate, boolean canBePermanent,
+ Symptom.ConfiguredSymptom... symptoms) {
+ return register(GTCEu.id(id), color, maxProgression, progressionType, progressionRate, canBePermanent,
+ symptoms);
+ }
+
+ public static void init() {
+ ModLoader.get()
+ .postEvent(new GTCEuAPI.RegisterEvent<>(GTRegistries.MEDICAL_CONDITIONS, MedicalCondition.class));
+ GTRegistries.MEDICAL_CONDITIONS.freeze();
+ }
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java b/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java
index ea0041cdc44..921d81e03b3 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/GTMobEffects.java
@@ -15,7 +15,7 @@ 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",
+ public static final RegistryObject WEAK_POISON = MOB_EFFECTS.register("weak_poison",
() -> new GTPoisonEffect(MobEffectCategory.HARMFUL, 0x6D7917));
public static void init(IEventBus modBus) {
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/machines/GTMachineUtils.java b/src/main/java/com/gregtechceu/gtceu/common/data/machines/GTMachineUtils.java
index 2f881c2b87b..811b6093911 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/data/machines/GTMachineUtils.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/machines/GTMachineUtils.java
@@ -896,8 +896,7 @@ public static Component explosion() {
}
public static Component environmentRequirement(MedicalCondition condition) {
- return Component.translatable("gtceu.recipe.environmental_hazard.reverse",
- Component.translatable("gtceu.medical_condition." + condition.name));
+ return Component.translatable("gtceu.recipe.environmental_hazard.reverse", condition.getTranslatableName());
}
public static Component defaultEnvironmentRequirement() {
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 62409787155..432009190f2 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
@@ -100,7 +100,6 @@ public static void register() {
.ore()
.color(0x73d73d).secondaryColor(0x184537).iconSet(METALLIC)
.appendFlags(STD_METAL)
- .hazard(HazardProperty.HazardTrigger.SKIN_CONTACT, GTMedicalConditions.BERYLLIOSIS, false)
.element(GTElements.Be)
.buildAndRegister();
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 ee7a481a008..9869897279d 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
@@ -887,7 +887,6 @@ public static void register() {
.color(0xf2f2f2).secondaryColor(0xb2c4c7).iconSet(QUARTZ)
.flags(NO_SMASHING, NO_SMELTING)
.components(Silicon, 1, Oxygen, 2)
- .hazard(HazardProperty.HazardTrigger.INHALATION, GTMedicalConditions.SILICOSIS, false)
.buildAndRegister();
MagnesiumChloride = new Material.Builder(GTCEu.id("magnesium_chloride"))
diff --git a/src/main/java/com/gregtechceu/gtceu/common/item/behavior/AntidoteBehavior.java b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/AntidoteBehavior.java
index 3046608a508..abceafab1f8 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/item/behavior/AntidoteBehavior.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/item/behavior/AntidoteBehavior.java
@@ -1,10 +1,10 @@
package com.gregtechceu.gtceu.common.item.behavior;
import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
import com.gregtechceu.gtceu.api.item.component.IAddInformation;
import com.gregtechceu.gtceu.api.item.component.IInteractionItem;
+import com.gregtechceu.gtceu.common.capability.MedicalConditionTracker;
import com.gregtechceu.gtceu.config.ConfigHolder;
import com.gregtechceu.gtceu.utils.GTUtil;
@@ -25,25 +25,25 @@
* Defines an antidote for a hazard (e.g. poisoning)
*
* @param types the type of the hazard to remove
- * @param removePercent the time to remove from the chosen hazard, as a percentage of the current time [0, 100].
- * -1 for all.
+ * @param removePercent how many 'counts' should be removed from the chosen condition(s),
+ * as a percentage of the current 'counts' in the range [0, 100]. -1 for all.
*/
public record AntidoteBehavior(Set types, int removePercent)
implements IInteractionItem, IAddInformation {
- public AntidoteBehavior(int timeToRemove, MedicalCondition... types) {
- this(new HashSet<>(), timeToRemove);
+ public AntidoteBehavior(int removePercent, MedicalCondition... types) {
+ this(new HashSet<>(), removePercent);
this.types.addAll(Arrays.asList(types));
}
@Override
public ItemStack finishUsingItem(ItemStack stack, Level level, LivingEntity livingEntity) {
ItemStack itemstack = IInteractionItem.super.finishUsingItem(stack, level, livingEntity);
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(livingEntity);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(livingEntity);
if (tracker == null) {
return itemstack;
}
- for (var entry : tracker.getMedicalConditions().object2FloatEntrySet()) {
+ for (var entry : tracker.getMedicalConditions().reference2FloatEntrySet()) {
MedicalCondition condition = entry.getKey();
if (condition == null) {
continue;
@@ -72,20 +72,20 @@ public void appendHoverText(ItemStack stack, @Nullable Level level, List getType() {
@Override
public Component getTooltips() {
return isReverse ?
- Component.translatable("gtceu.recipe.environmental_hazard.reverse",
- Component.translatable("gtceu.medical_condition." + condition.name)) :
- Component.translatable("gtceu.recipe.environmental_hazard",
- Component.translatable("gtceu.medical_condition." + condition.name));
+ Component.translatable("gtceu.recipe.environmental_hazard.reverse", condition.getTranslatableName()) :
+ Component.translatable("gtceu.recipe.environmental_hazard", condition.getTranslatableName());
}
@Override
diff --git a/src/main/java/com/gregtechceu/gtceu/core/IBreathingEntity.java b/src/main/java/com/gregtechceu/gtceu/core/IBreathingEntity.java
new file mode 100644
index 00000000000..372a43ad6e8
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/core/IBreathingEntity.java
@@ -0,0 +1,12 @@
+package com.gregtechceu.gtceu.core;
+
+public interface IBreathingEntity {
+
+ default int gtceu$getOriginalMaxAirSupply() {
+ throw new AssertionError("Mixin didn't apply");
+ }
+
+ default void gtceu$setMaxAirSupply(int newMaxAirSupply) {
+ throw new AssertionError("Mixin didn't apply");
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/core/IFireImmuneEntity.java b/src/main/java/com/gregtechceu/gtceu/core/IFireImmuneEntity.java
index ebbdfff3cd2..f31d534985f 100644
--- a/src/main/java/com/gregtechceu/gtceu/core/IFireImmuneEntity.java
+++ b/src/main/java/com/gregtechceu/gtceu/core/IFireImmuneEntity.java
@@ -2,5 +2,7 @@
public interface IFireImmuneEntity {
- void gtceu$setFireImmune(boolean isImmune);
+ default void gtceu$setFireImmune(boolean isImmune) {
+ throw new AssertionError("Mixin didn't apply");
+ }
}
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 f8e65ae9d87..6a2201c3a9d 100644
--- a/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java
+++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/EntityMixin.java
@@ -1,8 +1,7 @@
package com.gregtechceu.gtceu.core.mixins;
-import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
-import com.gregtechceu.gtceu.api.capability.IMedicalConditionTracker;
import com.gregtechceu.gtceu.config.ConfigHolder;
+import com.gregtechceu.gtceu.core.IBreathingEntity;
import com.gregtechceu.gtceu.core.IFireImmuneEntity;
import net.minecraft.world.entity.Entity;
@@ -15,19 +14,23 @@
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Entity.class)
-public abstract class EntityMixin implements IFireImmuneEntity {
+public abstract class EntityMixin implements IFireImmuneEntity, IBreathingEntity {
@Shadow
- public abstract EntityType> getType();
+ public abstract int getMaxAirSupply();
@Unique
private boolean gtceu$fireImmune = false;
@Unique
private boolean gtceu$isEntityInit = false;
+ @Unique
+ private int gtceu$modifiedMaxAirSupply = -1;
+
@ModifyReturnValue(method = "fireImmune", at = @At("RETURN"))
private boolean gtceu$changeFireImmune(boolean original) {
return original || gtceu$fireImmune;
@@ -38,19 +41,55 @@ public abstract class EntityMixin implements IFireImmuneEntity {
gtceu$isEntityInit = true;
}
- public void gtceu$setFireImmune(boolean isImmune) {
- this.gtceu$fireImmune = isImmune;
+ @ModifyReturnValue(method = "getMaxAirSupply", at = @At("RETURN"))
+ private int gtceu$limitGetMaxAirSupply(int original) {
+ return gtceu$limitAirSupply(original);
}
- @ModifyReturnValue(method = "getMaxAirSupply", at = @At("RETURN"))
- private int gtceu$hazardModifyMaxAir(int original) {
+ @ModifyVariable(method = "setAirSupply", at = @At("HEAD"), argsOnly = true)
+ private int gtceu$limitSetAirSupply(int original) {
+ return gtceu$limitAirSupply(original);
+ }
+
+ @ModifyReturnValue(method = "getAirSupply", at = @At("RETURN"))
+ private int gtceu$limitGetAirSupply(int original) {
+ return gtceu$limitAirSupply(original);
+ }
+
+ @Unique
+ private int gtceu$limitAirSupply(int original) {
if (!gtceu$isEntityInit) return original;
if (!ConfigHolder.INSTANCE.gameplay.hazardsEnabled) return original;
- IMedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker((Entity) (Object) this);
- if (tracker != null && tracker.getMaxAirSupply() != -1) {
- return tracker.getMaxAirSupply();
+ if (gtceu$modifiedMaxAirSupply > 0 && gtceu$modifiedMaxAirSupply < original) {
+ return gtceu$modifiedMaxAirSupply;
}
return original;
}
+
+ @Override
+ public void gtceu$setFireImmune(boolean isImmune) {
+ this.gtceu$fireImmune = isImmune;
+ }
+
+ @Override
+ public int gtceu$getOriginalMaxAirSupply() {
+ if (!this.gtceu$isEntityInit) {
+ return getMaxAirSupply();
+ }
+
+ try {
+ // set the "in init" flag when getting the original value so the mixin to change it doesn't do anything
+ this.gtceu$isEntityInit = false;
+ return this.getMaxAirSupply();
+ } finally {
+ // then set it back after
+ this.gtceu$isEntityInit = true;
+ }
+ }
+
+ @Override
+ public void gtceu$setMaxAirSupply(int newMaxAirSupply) {
+ this.gtceu$modifiedMaxAirSupply = newMaxAirSupply;
+ }
}
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 f36f4b91036..5ad68a29427 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java
@@ -124,11 +124,30 @@ public static void init(RegistrateLangProvider provider) {
provider.add("gtceu.tool.class.shears", "Shears");
provider.add("gtceu.tool.class.drill", "Drill");
- provider.add("command.gtceu.medical_condition.get", "Player %s has these medical conditions:");
- provider.add("command.gtceu.medical_condition.get.empty", "Player %s has no medical conditions.");
- provider.add("command.gtceu.medical_condition.get.element", "Condition %s§r: %s minutes %s seconds");
+ provider.add("command.gtceu.medical_condition.clear.everything.failed", "Target has no conditions to remove");
+ provider.add("command.gtceu.medical_condition.clear.everything.success.multiple",
+ "Removed all conditions from %s targets");
+ provider.add("command.gtceu.medical_condition.clear.everything.success.single",
+ "Removed all conditions from %s");
+ provider.add("command.gtceu.medical_condition.clear.specific.failed",
+ "Target doesn't have the requested condition");
+ provider.add("command.gtceu.medical_condition.clear.specific.success.multiple", "Removed %s from %s targets");
+ provider.add("command.gtceu.medical_condition.clear.specific.success.single", "Removed %s from %s");
+
+ provider.add("command.gtceu.medical_condition.give.failed", "Unable to apply this condition (invalid target)");
+ provider.add("command.gtceu.medical_condition.give.success.multiple", "Applied %s to %s targets");
+ provider.add("command.gtceu.medical_condition.give.success.single", "Applied %s to %s");
+
+ provider.add("command.gtceu.medical_condition.get", "%s has");
+ provider.add("command.gtceu.medical_condition.get.empty", "%s is perfectly healthy.");
+ provider.add("command.gtceu.medical_condition.get.element", "- %s for %s minutes %s seconds");
provider.add("command.gtceu.medical_condition.get.element.permanent",
- "Condition %s§r: %s minutes %s seconds (permanent)");
+ "- %s for %s minutes %s seconds (permanent)");
+
+ provider.add("command.gtceu.medical_condition.get.symptoms.empty", "%s has no symptoms.");
+ provider.add("command.gtceu.medical_condition.get.symptoms", "Currently %s has these symptoms:");
+ provider.add("command.gtceu.medical_condition.get.symptoms.element", "- %s");
+
provider.add("command.gtceu.dump_data.success", "Dumped %s resources from registry %s to %s");
provider.add("command.gtceu.place_vein.failure", "Failed to place vein %s at position %s");
provider.add("command.gtceu.place_vein.success", "Placed vein %s at position %s");
@@ -145,33 +164,53 @@ public static void init(RegistrateLangProvider provider) {
provider.add("command.gtceu.cape.use.success", "%s is now using cape %s");
provider.add("command.gtceu.cape.use.success.none", "%s is no longer using a cape");
- provider.add("gtceu.medical_condition.description", "§l§cHAZARDOUS §7Hold Shift to show details");
- provider.add("gtceu.medical_condition.description_shift", "§l§cHAZARDOUS:");
- provider.add("gtceu.medical_condition.chemical_burns", "§5Chemical burns");
- provider.add("gtceu.medical_condition.poison", "§2Poisonous");
- provider.add("gtceu.medical_condition.weak_poison", "§aWeakly poisonous");
- provider.add("gtceu.medical_condition.irritant", "§6Irritant");
- provider.add("gtceu.medical_condition.nausea", "§3Nauseating");
- provider.add("gtceu.medical_condition.carcinogen", "§eCarcinogenic");
- provider.add("gtceu.medical_condition.asbestosis", "§dAsbestosis");
- provider.add("gtceu.medical_condition.arsenicosis", "§bArsenicosis");
- provider.add("gtceu.medical_condition.silicosis", "§1Silicosis");
- provider.add("gtceu.medical_condition.berylliosis", "§5Berylliosis");
- provider.add("gtceu.medical_condition.methanol_poisoning", "§6Methanol Poisoning");
- provider.add("gtceu.medical_condition.carbon_monoxide_poisoning", "§7Carbon Monoxide Poisoning");
- provider.add("gtceu.medical_condition.none", "§2Not Dangerous");
- provider.add("gtceu.hazard_trigger.description", "Caused by:");
- provider.add("gtceu.hazard_trigger.protection.description", "Protects from:");
- provider.add("gtceu.hazard_trigger.inhalation", "Inhalation");
- provider.add("gtceu.hazard_trigger.any", "Any contact");
-
- provider.add("gtceu.hazard_trigger.skin_contact", "Skin contact");
- provider.add("gtceu.hazard_trigger.none", "Nothing");
- provider.add("gtceu.medical_condition.antidote.description", "§aAntidote §7Hold Shift to show details");
- provider.add("gtceu.medical_condition.antidote.description_shift", "§aCures these conditions:");
- provider.add("gtceu.medical_condition.antidote.description.effect_removed",
+ provider.add("tooltip.gtceu.medical_condition.description", "§l§cHAZARDOUS §7Hold Shift to show details");
+ provider.add("tooltip.gtceu.medical_condition.description_shift", "§l§cHAZARDOUS:");
+ provider.add("medical_condition.gtceu.chemical_burns", "§5Chemical burns");
+ provider.add("medical_condition.gtceu.poison", "§2Poisonous");
+ provider.add("medical_condition.gtceu.poison.affected", "§2Poisoning");
+ provider.add("medical_condition.gtceu.weak_poison", "§aWeakly poisonous");
+ provider.add("medical_condition.gtceu.weak_poison.affected", "§aMinor poisoning");
+ provider.add("medical_condition.gtceu.irritant", "§6Irritant");
+ provider.add("medical_condition.gtceu.irritant.affected", "§6Irritation");
+ provider.add("medical_condition.gtceu.nausea", "§3Nauseating");
+ provider.add("medical_condition.gtceu.nausea.affected", "§3Nausea");
+ provider.add("medical_condition.gtceu.carcinogen", "§eCarcinogenic");
+ provider.add("medical_condition.gtceu.carcinogen.affected", "§eCancer");
+ provider.add("medical_condition.gtceu.asbestosis", "§dAsbestosis");
+ provider.add("medical_condition.gtceu.arsenicosis", "§bArsenicosis");
+ provider.add("medical_condition.gtceu.methanol_poisoning", "§6Methanol Poisoning");
+ provider.add("medical_condition.gtceu.carbon_monoxide_poisoning", "§7Carbon Monoxide Poisoning");
+ provider.add("medical_condition.gtceu.none", "§2Not Dangerous");
+ provider.add("medical_condition.gtceu.none.affected", "§2Nothing?");
+
+ provider.add("symptom.gtceu.death", "Death");
+ provider.add("symptom.gtceu.random_damage", "Occasional damage");
+ provider.add("symptom.gtceu.health_debuff", "Lowered maximum health");
+ provider.add("symptom.gtceu.air_supply_debuff", "Lowered lung capacity");
+ provider.add("symptom.gtceu.mining_fatigue", "Fatigue");
+ provider.add("symptom.gtceu.weakness", "Weakness");
+ provider.add("symptom.gtceu.slowness", "Slowness");
+ provider.add("symptom.gtceu.blindness", "Blindness");
+ provider.add("symptom.gtceu.darkness", "Darkness");
+ provider.add("symptom.gtceu.nausea", "Nausea");
+ provider.add("symptom.gtceu.wither", "Necrosis");
+ provider.add("symptom.gtceu.weak_poisoning", "Weak poisoning");
+ provider.add("symptom.gtceu.poisoning", "Poisoning");
+ provider.add("symptom.gtceu.hunger", "Increased appetite");
+
+ provider.add("tooltip.gtceu.hazard_trigger", "Caused by:");
+ provider.add("tooltip.gtceu.hazard_trigger.protection", "Protects from:");
+ provider.add("tooltip.gtceu.hazard_trigger.inhalation", "Inhalation");
+ provider.add("tooltip.gtceu.hazard_trigger.any", "Any contact");
+ provider.add("tooltip.gtceu.hazard_trigger.skin_contact", "Skin contact");
+ provider.add("tooltip.gtceu.hazard_trigger.none", "Nothing");
+
+ provider.add("tooltip.gtceu.antidote.description", "§aAntidote §7Hold Shift to show details");
+ provider.add("tooltip.gtceu.antidote.description_shift", "§aCures these conditions:");
+ provider.add("tooltip.gtceu.antidote.description.effect_removed",
"Removes %s%% of current conditions' effects");
- provider.add("gtceu.medical_condition.antidote.description.effect_removed.all",
+ provider.add("tooltip.gtceu.antidote.description.effect_removed.all",
"Removes all of current conditions' effects");
provider.add("gtceu.multiblock.dimension", "§eDimensions: §r%sx%sx%s");
@@ -193,7 +232,7 @@ public static void init(RegistrateLangProvider provider) {
provider.add("item.gtceu.tool.behavior.crop_harvesting", "§aHarvester: §fHarvests Crops");
provider.add("item.gtceu.tool.behavior.plunger", "§9Plumber: §fDrains Fluids");
provider.add("item.gtceu.tool.behavior.block_rotation", "§2Mechanic: §fRotates Blocks");
- provider.add("item.gtceu.tool.behavior.dowse_campfire", "§1Firefighter: §fDowses Campfires");
+ provider.add("item.gtceu.tool.behavior.dowse_campfire", "§6Firefighter: §fDowses Campfires");
provider.add("item.gtceu.tool.behavior.damage_boost", "§4Damage Boost: §fExtra damage against %s");
provider.add("item.gtceu.tool.behavior.prospecting.ore", "Found ore: %s");
provider.add("item.gtceu.tool.behavior.prospecting.air", "Found an air pocket");
diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/ToolLang.java b/src/main/java/com/gregtechceu/gtceu/data/lang/ToolLang.java
index 6b0d8527c1d..38835fbc589 100644
--- a/src/main/java/com/gregtechceu/gtceu/data/lang/ToolLang.java
+++ b/src/main/java/com/gregtechceu/gtceu/data/lang/ToolLang.java
@@ -53,16 +53,16 @@ private static void initDeathMessages(RegistrateLangProvider provider) {
provider.add("death.attack.gtceu.medical_condition/poison",
"%s forgot that poisonous materials are, in fact, poisonous");
provider.add("death.attack.gtceu.medical_condition/silicosis",
- "%s didn't die of tuberculosis. it was silicosis.");
+ "%s didn't die of tuberculosis. It was silicosis");
provider.add("death.attack.gtceu.medical_condition/arsenicosis", "%s got arsenic poisoning");
provider.add("death.attack.gtceu.medical_condition/berylliosis", "%s mined emeralds a bit too greedily");
provider.add("death.attack.gtceu.medical_condition/carcinogen", "%s got leukemia");
provider.add("death.attack.gtceu.medical_condition/irritant", "%s got a §n§lREALLY§r bad rash");
provider.add("death.attack.gtceu.medical_condition/methanol_poisoning",
"%s tried to drink moonshine during the prohibition");
- provider.add("death.attack.gtceu.medical_condition/nausea", "%s died of nausea");
+ provider.add("death.attack.gtceu.medical_condition/nausea", "%s succumbed to nausea");
provider.add("death.attack.gtceu.medical_condition/none", "%s died of... nothing?");
- provider.add("death.attack.gtceu.medical_condition/weak_poison", "%s ate lead (or mercury!)");
+ provider.add("death.attack.gtceu.medical_condition/weak_poison", "%s ate lead");
provider.add("death.attack.gtceu.medical_condition/carbon_monoxide_poisoning", "%s left the stove on");
}
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 d829715d5de..e007aa4151b 100644
--- a/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java
+++ b/src/main/java/com/gregtechceu/gtceu/integration/kjs/GregTechKubeJSPlugin.java
@@ -473,7 +473,7 @@ public void registerTypeWrappers(ScriptType type, TypeWrappers typeWrappers) {
});
typeWrappers.registerSimple(MedicalCondition.class, o -> {
if (o instanceof MedicalCondition condition) return condition;
- if (o instanceof CharSequence str) return MedicalCondition.CONDITIONS.get(str.toString());
+ if (o instanceof CharSequence str) return GTRegistries.MEDICAL_CONDITIONS.get(GTCEu.id(str.toString()));
return null;
});
typeWrappers.registerSimple(IWorldGenLayer.RuleTestSupplier.class, o -> {
diff --git a/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java
index 493f7798fb9..caeaf139aed 100644
--- a/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java
+++ b/src/main/java/com/gregtechceu/gtceu/utils/FormattingUtil.java
@@ -15,6 +15,7 @@
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
+import java.util.HexFormat;
import java.util.Locale;
import java.util.stream.Collectors;
@@ -29,6 +30,7 @@ public class FormattingUtil {
public static final DecimalFormat DECIMAL_FORMAT_2F = new DecimalFormat("#,##0.##");
public static final DecimalFormat DECIMAL_FORMAT_SIC = new DecimalFormat("0E00");
public static final DecimalFormat DECIMAL_FORMAT_SIC_2F = new DecimalFormat("0.00E00");
+ public static final HexFormat HEX_FORMAT = HexFormat.of().withUpperCase();
private static final int SMALL_DOWN_NUMBER_BASE = '\u2080';
private static final int SMALL_UP_NUMBER_BASE = '\u2070';
diff --git a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
index 04a9f1fefae..f43ee33f385 100644
--- a/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
+++ b/src/main/java/com/gregtechceu/gtceu/utils/GTUtil.java
@@ -580,15 +580,13 @@ public static void appendHazardTooltips(Material material, List toolt
if (!ConfigHolder.INSTANCE.gameplay.hazardsEnabled || !material.hasProperty(HAZARD)) return;
if (GTUtil.isShiftDown()) {
- tooltipComponents.add(Component.translatable("gtceu.medical_condition.description_shift"));
- tooltipComponents.add(Component
- .translatable("gtceu.medical_condition." + material.getProperty(HAZARD).condition.name));
- tooltipComponents.add(Component.translatable("gtceu.hazard_trigger.description"));
- tooltipComponents.add(Component
- .translatable("gtceu.hazard_trigger." + material.getProperty(HAZARD).hazardTrigger.name()));
+ tooltipComponents.add(Component.translatable("tooltip.gtceu.medical_condition.description_shift"));
+ tooltipComponents.add(material.getProperty(HAZARD).condition.getTranslatableName());
+ tooltipComponents.add(Component.translatable("tooltip.gtceu.hazard_trigger"));
+ tooltipComponents.add(material.getProperty(HAZARD).hazardTrigger.getTranslatableName());
return;
}
- tooltipComponents.add(Component.translatable("gtceu.medical_condition.description"));
+ tooltipComponents.add(Component.translatable("tooltip.gtceu.medical_condition.description"));
}
public static CompoundTag saveItemStack(ItemStack itemStack, CompoundTag compoundTag) {
diff --git a/src/main/java/com/gregtechceu/gtceu/utils/fakeplayer/FakeServerGamePacketListenerImpl.java b/src/main/java/com/gregtechceu/gtceu/utils/fakeplayer/FakeServerGamePacketListenerImpl.java
new file mode 100644
index 00000000000..e828f23673e
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/utils/fakeplayer/FakeServerGamePacketListenerImpl.java
@@ -0,0 +1,207 @@
+package com.gregtechceu.gtceu.utils.fakeplayer;
+
+import net.minecraft.network.Connection;
+import net.minecraft.network.PacketSendListener;
+import net.minecraft.network.chat.ChatType;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.PlayerChatMessage;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.PacketFlow;
+import net.minecraft.network.protocol.game.*;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
+import net.minecraft.world.entity.RelativeMovement;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+@ParametersAreNonnullByDefault
+public class FakeServerGamePacketListenerImpl extends ServerGamePacketListenerImpl {
+
+ private static final Connection DUMMY_CONNECTION = new Connection(PacketFlow.CLIENTBOUND);
+
+ public FakeServerGamePacketListenerImpl(MinecraftServer server, ServerPlayer player) {
+ super(server, DUMMY_CONNECTION, player);
+ }
+
+ @Override
+ public void tick() {}
+
+ @Override
+ public void resetPosition() {}
+
+ @Override
+ public void disconnect(Component message) {}
+
+ @Override
+ public void handlePlayerInput(ServerboundPlayerInputPacket packet) {}
+
+ @Override
+ public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) {}
+
+ @Override
+ public void handleAcceptTeleportPacket(ServerboundAcceptTeleportationPacket packet) {}
+
+ @Override
+ public void handleRecipeBookSeenRecipePacket(ServerboundRecipeBookSeenRecipePacket packet) {}
+
+ @Override
+ public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) {}
+
+ @Override
+ public void handleSeenAdvancements(ServerboundSeenAdvancementsPacket packet) {}
+
+ @Override
+ public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {}
+
+ @Override
+ public void handleSetCommandBlock(ServerboundSetCommandBlockPacket packet) {}
+
+ @Override
+ public void handleSetCommandMinecart(ServerboundSetCommandMinecartPacket packet) {}
+
+ @Override
+ public void handlePickItem(ServerboundPickItemPacket packet) {}
+
+ @Override
+ public void handleRenameItem(ServerboundRenameItemPacket packet) {}
+
+ @Override
+ public void handleSetBeaconPacket(ServerboundSetBeaconPacket packet) {}
+
+ @Override
+ public void handleSetStructureBlock(ServerboundSetStructureBlockPacket packet) {}
+
+ @Override
+ public void handleSetJigsawBlock(ServerboundSetJigsawBlockPacket packet) {}
+
+ @Override
+ public void handleJigsawGenerate(ServerboundJigsawGeneratePacket packet) {}
+
+ @Override
+ public void handleSelectTrade(ServerboundSelectTradePacket packet) {}
+
+ @Override
+ public void handleEditBook(ServerboundEditBookPacket packet) {}
+
+ @Override
+ public void handleEntityTagQuery(ServerboundEntityTagQuery packet) {}
+
+ @Override
+ public void handleBlockEntityTagQuery(ServerboundBlockEntityTagQuery packet) {}
+
+ @Override
+ public void handleMovePlayer(ServerboundMovePlayerPacket packet) {}
+
+ @Override
+ public void teleport(double x, double y, double z, float yaw, float pitch) {}
+
+ @Override
+ public void handlePlayerAction(ServerboundPlayerActionPacket packet) {}
+
+ @Override
+ public void handleUseItemOn(ServerboundUseItemOnPacket packet) {}
+
+ @Override
+ public void handleUseItem(ServerboundUseItemPacket packet) {}
+
+ @Override
+ public void handleTeleportToEntityPacket(ServerboundTeleportToEntityPacket packet) {}
+
+ @Override
+ public void handleResourcePackResponse(ServerboundResourcePackPacket packet) {}
+
+ @Override
+ public void handlePaddleBoat(ServerboundPaddleBoatPacket packet) {}
+
+ @Override
+ public void onDisconnect(Component message) {}
+
+ @Override
+ public void send(Packet> packet) {}
+
+ @Override
+ public void send(Packet> packet, @Nullable PacketSendListener sendListener) {}
+
+ @Override
+ public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) {}
+
+ @Override
+ public void handleChat(ServerboundChatPacket packet) {}
+
+ @Override
+ public void handleAnimate(ServerboundSwingPacket packet) {}
+
+ @Override
+ public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) {}
+
+ @Override
+ public void handleInteract(ServerboundInteractPacket packet) {}
+
+ @Override
+ public void handleClientCommand(ServerboundClientCommandPacket packet) {}
+
+ @Override
+ public void handleContainerClose(ServerboundContainerClosePacket packet) {}
+
+ @Override
+ public void handleContainerClick(ServerboundContainerClickPacket packet) {}
+
+ @Override
+ public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {}
+
+ @Override
+ public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) {}
+
+ @Override
+ public void handleSetCreativeModeSlot(ServerboundSetCreativeModeSlotPacket packet) {}
+
+ @Override
+ public void handleSignUpdate(ServerboundSignUpdatePacket packet) {}
+
+ @Override
+ public void handleKeepAlive(ServerboundKeepAlivePacket packet) {}
+
+ @Override
+ public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) {}
+
+ @Override
+ public void handleClientInformation(ServerboundClientInformationPacket packet) {}
+
+ @Override
+ public void handleCustomPayload(ServerboundCustomPayloadPacket packet) {}
+
+ @Override
+ public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) {}
+
+ @Override
+ public void handleLockDifficulty(ServerboundLockDifficultyPacket packet) {}
+
+ @Override
+ public void teleport(double x, double y, double z, float yaw, float pitch, Set relativeSet) {}
+
+ @Override
+ public void ackBlockChangesUpTo(int sequence) {}
+
+ @Override
+ public void handleChatCommand(ServerboundChatCommandPacket packet) {}
+
+ @Override
+ public void handleChatAck(ServerboundChatAckPacket packet) {}
+
+ @Override
+ public void addPendingMessage(PlayerChatMessage message) {}
+
+ @Override
+ public void sendPlayerChatMessage(PlayerChatMessage message, ChatType.Bound boundChatType) {}
+
+ @Override
+ public void sendDisguisedChatMessage(Component content, ChatType.Bound boundChatType) {}
+
+ @Override
+ public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket packet) {}
+}
diff --git a/src/main/resources/assets/gtceu/lang/ja_jp.json b/src/main/resources/assets/gtceu/lang/ja_jp.json
index e734b1e3c55..f1d64562414 100644
--- a/src/main/resources/assets/gtceu/lang/ja_jp.json
+++ b/src/main/resources/assets/gtceu/lang/ja_jp.json
@@ -2457,12 +2457,12 @@
"gtceu.gui.toggle_view.disabled": "液体スロット切り替え",
"gtceu.gui.toggle_view.enabled": "アイテムスロット切り替え",
"gtceu.gui.waiting_list": "送信キュー:",
- "gtceu.hazard_trigger.any": "接続先",
- "gtceu.hazard_trigger.description": "原因:",
- "gtceu.hazard_trigger.inhalation": "吸入",
- "gtceu.hazard_trigger.none": "何もない",
- "gtceu.hazard_trigger.protection.description": "保護する:",
- "gtceu.hazard_trigger.skin_contact": "皮膚接触",
+ "tooltip.gtceu.hazard_trigger.any": "接続先",
+ "tooltip.gtceu.hazard_trigger": "原因:",
+ "tooltip.gtceu.hazard_trigger.inhalation": "吸入",
+ "tooltip.gtceu.hazard_trigger.none": "何もない",
+ "tooltip.gtceu.hazard_trigger.protection": "保護する:",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "皮膚接触",
"gtceu.implosion_compressor": "内破圧縮機",
"gtceu.io.both": "両方",
"gtceu.io.export": "搬出",
@@ -3208,25 +3208,23 @@
"gtceu.maintenance.configurable_time": "故障率: %fx",
"gtceu.maintenance.configurable_time.changed_description": "故障は通常の%f倍の頻度で発生します",
"gtceu.maintenance.configurable_time.unchanged_description": "故障は通常の頻度で発生します。設定を変更するとアップデートされます。",
- "gtceu.medical_condition.antidote.description": "§a解毒剤 §7Shiftを押して詳細を表示する",
- "gtceu.medical_condition.antidote.description.effect_removed": "現在の状態の効果を%s%%で取り除く",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "現在の状態の効果をすべて取り除く",
- "gtceu.medical_condition.antidote.description_shift": "§aこれらの状態を治す:",
- "gtceu.medical_condition.arsenicosis": "§bヒ素中毒",
- "gtceu.medical_condition.asbestosis": "§dアスベスト症",
- "gtceu.medical_condition.berylliosis": "§5ベリリウム症",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7一酸化炭素中毒",
- "gtceu.medical_condition.carcinogen": "§e発がん性",
- "gtceu.medical_condition.chemical_burns": "§5化学熱傷",
- "gtceu.medical_condition.description": "§l§c汚染§7 詳細を表示するにはshiftを押す",
- "gtceu.medical_condition.description_shift": "§l§c汚染:",
- "gtceu.medical_condition.irritant": "§6発疹",
- "gtceu.medical_condition.methanol_poisoning": "§6メタノール中毒",
- "gtceu.medical_condition.nausea": "§3吐き気",
- "gtceu.medical_condition.none": "§2危険ではない",
- "gtceu.medical_condition.poison": "§2有毒",
- "gtceu.medical_condition.silicosis": "§1珪肺",
- "gtceu.medical_condition.weak_poison": "§a弱毒",
+ "tooltip.gtceu.antidote.description": "§a解毒剤 §7Shiftを押して詳細を表示する",
+ "tooltip.gtceu.antidote.description.effect_removed": "現在の状態の効果を%s%%で取り除く",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "現在の状態の効果をすべて取り除く",
+ "tooltip.gtceu.antidote.description_shift": "§aこれらの状態を治す:",
+ "medical_condition.gtceu.arsenicosis": "§bヒ素中毒",
+ "medical_condition.gtceu.asbestosis": "§dアスベスト症",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7一酸化炭素中毒",
+ "medical_condition.gtceu.carcinogen": "§e発がん性",
+ "medical_condition.gtceu.chemical_burns": "§5化学熱傷",
+ "tooltip.gtceu.medical_condition.description": "§l§c汚染§7 詳細を表示するにはshiftを押す",
+ "tooltip.gtceu.medical_condition.description_shift": "§l§c汚染:",
+ "medical_condition.gtceu.irritant": "§6発疹",
+ "medical_condition.gtceu.methanol_poisoning": "§6メタノール中毒",
+ "medical_condition.gtceu.nausea": "§3吐き気",
+ "medical_condition.gtceu.none": "§2危険ではない",
+ "medical_condition.gtceu.poison": "§2有毒",
+ "medical_condition.gtceu.weak_poison": "§a弱毒",
"gtceu.minimap.ore_vein.depleted": "枯渇",
"gtceu.mixer": "ミキサー",
"gtceu.mode.both": "§d両方(液体とアイテム) §r",
diff --git a/src/main/resources/assets/gtceu/lang/ru_ru.json b/src/main/resources/assets/gtceu/lang/ru_ru.json
index 49a097fe4c1..d681ed7a117 100644
--- a/src/main/resources/assets/gtceu/lang/ru_ru.json
+++ b/src/main/resources/assets/gtceu/lang/ru_ru.json
@@ -5008,22 +5008,20 @@
"config.gtceu.option.meHatchEnergyUsage": "meHatchEnergyUsage",
"config.gtceu.option.orderedAssemblyLineFluids": "orderedAssemblyLineFluids",
"config.gtceu.option.orderedAssemblyLineItems": "orderedAssemblyLineItems",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "Убирает все последствия текущих заболеваний",
- "gtceu.medical_condition.antidote.description.effect_removed": "Убирает %s%% последствий текущих заболеваний",
- "gtceu.medical_condition.antidote.description_shift": "§aЛечит следующие заболевания:",
- "gtceu.medical_condition.antidote.description": "§aАнтидот §7Зажмите Shift, чтобы просмотреть подробную информацию",
- "gtceu.medical_condition.arsenicosis": "§bОтравление мышьяком",
- "gtceu.medical_condition.asbestosis": "§dАсбестоз",
- "gtceu.medical_condition.berylliosis": "§5Бериллиоз",
- "gtceu.medical_condition.carcinogen": "§eКанцерогенный",
- "gtceu.medical_condition.chemical_burns": "§5Химический ожог",
- "gtceu.medical_condition.description_shift": "§l§cОПАСНЫЙ:",
- "gtceu.medical_condition.methanol_poisoning": "§6Отравление метанолом",
- "gtceu.medical_condition.nausea": "§3Тошнотворный",
- "gtceu.medical_condition.none": "§2Не опасный",
- "gtceu.medical_condition.poison": "§2Ядовитый",
- "gtceu.medical_condition.silicosis": "§1Силикоз",
- "gtceu.medical_condition.weak_poison": "§aСлабо ядовитый",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "Убирает все последствия текущих заболеваний",
+ "tooltip.gtceu.antidote.description.effect_removed": "Убирает %s%% последствий текущих заболеваний",
+ "tooltip.gtceu.antidote.description_shift": "§aЛечит следующие заболевания:",
+ "tooltip.gtceu.antidote.description": "§aАнтидот §7Зажмите Shift, чтобы просмотреть подробную информацию",
+ "medical_condition.gtceu.arsenicosis": "§bОтравление мышьяком",
+ "medical_condition.gtceu.asbestosis": "§dАсбестоз",
+ "medical_condition.gtceu.carcinogen": "§eКанцерогенный",
+ "medical_condition.gtceu.chemical_burns": "§5Химический ожог",
+ "tooltip.gtceu.medical_condition.description_shift": "§l§cОПАСНЫЙ:",
+ "medical_condition.gtceu.methanol_poisoning": "§6Отравление метанолом",
+ "medical_condition.gtceu.nausea": "§3Тошнотворный",
+ "medical_condition.gtceu.none": "§2Не опасный",
+ "medical_condition.gtceu.poison": "§2Ядовитый",
+ "medical_condition.gtceu.weak_poison": "§aСлабо ядовитый",
"gtceu.recipe.total_computation": "Вычисление: %s CWU",
"gtceu.subtitle.assembler": "Сборщик собирает",
"gtceu.subtitle.bath": "Ванна шипит",
@@ -5072,12 +5070,12 @@
"config.gtceu.option.ae2": "ae2",
"block.gtceu.mv_air_scrubber": "§bУлучшенный очиститель воздуха §r",
"config.gtceu.option.energyConsumption": "energyConsumption",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7Отравление угарным газом",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7Отравление угарным газом",
"gtceu.subtitle.file": "Напильник скрежет",
"gtceu.subtitle.macerator": "Измельчитель измельчает",
"gtceu.subtitle.replicator": "Репликатор копирует",
"gtceu.top.item_auto_output": "Вывод предметов: %s",
- "gtceu.medical_condition.description": "§l§cОПАСНЫЙ §7Удерживайте Shift, чтобы просмотреть подробную информацию",
+ "tooltip.gtceu.medical_condition.description": "§l§cОПАСНЫЙ §7Удерживайте Shift, чтобы просмотреть подробную информацию",
"gtceu.subtitle.combustion": "Сгорание",
"gtceu.subtitle.computation": "Компьютер пикает",
"gtceu.subtitle.metal_pipe": "Очень_громкий_металичнский_труба.wav",
@@ -5123,14 +5121,14 @@
"gtceu.air_scrubber": "Очиститель воздуха",
"gtceu.duct_pipe.transfer_rate": "§bСкорость передачи воздуха: %s",
"gtceu.evaporation": "Выпаривание",
- "gtceu.hazard_trigger.any": "При любом контакте",
- "gtceu.hazard_trigger.description": "Проявляется при:",
- "gtceu.hazard_trigger.inhalation": "Вдыхание вредных веществ",
- "gtceu.hazard_trigger.none": "Ничем",
- "gtceu.hazard_trigger.protection.description": "Защищает от:",
- "gtceu.hazard_trigger.skin_contact": "Контакт с кожей",
+ "tooltip.gtceu.hazard_trigger.any": "При любом контакте",
+ "tooltip.gtceu.hazard_trigger": "Проявляется при:",
+ "tooltip.gtceu.hazard_trigger.inhalation": "Вдыхание вредных веществ",
+ "tooltip.gtceu.hazard_trigger.none": "Ничем",
+ "tooltip.gtceu.hazard_trigger.protection": "Защищает от:",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "Контакт с кожей",
"gtceu.jade.cleaned_this_second": "Убирает опасность: %s/с",
- "gtceu.medical_condition.irritant": "§6Раздражитель",
+ "medical_condition.gtceu.irritant": "§6Раздражитель",
"gtceu.subtitle.turbine": "Турбина воет",
"gtceu.subtitle.wirecutter": "Провод перекусился",
"gtceu.subtitle.wrench": "Ключ стрекочет",
diff --git a/src/main/resources/assets/gtceu/lang/uk_ua.json b/src/main/resources/assets/gtceu/lang/uk_ua.json
index cc680221e39..d9acf9579b9 100644
--- a/src/main/resources/assets/gtceu/lang/uk_ua.json
+++ b/src/main/resources/assets/gtceu/lang/uk_ua.json
@@ -2474,13 +2474,13 @@
"gtceu.gui.title_bar.page_switcher": "Сторінки",
"gtceu.gui.toggle_view.disabled": "Перемкнути вид (Рідини)",
"gtceu.gui.toggle_view.enabled": "Перемкнути вид (Предмети)",
- "gtceu.gui.waiting_list": "Черга на відправлення:",
- "gtceu.hazard_trigger.any": "При будь-якому контакті",
- "gtceu.hazard_trigger.description": "Спричиняється:",
- "gtceu.hazard_trigger.inhalation": "При вдиханні",
- "gtceu.hazard_trigger.none": "Ніяк",
- "gtceu.hazard_trigger.protection.description": "Захищає:",
- "gtceu.hazard_trigger.skin_contact": "При контакті зі шкірою",
+ "gtceu.gui.waiting_list": "Черга надсилання:",
+ "tooltip.gtceu.hazard_trigger": "Спричиняється:",
+ "tooltip.gtceu.hazard_trigger.protection": "Захищає:",
+ "tooltip.gtceu.hazard_trigger.any": "При будь-якому контакті",
+ "tooltip.gtceu.hazard_trigger.inhalation": "При вдиханні",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "При контакті зі шкірою",
+ "tooltip.gtceu.hazard_trigger.none": "Ніяк",
"gtceu.implosion_compressor": "Компресор надмірного тиску",
"gtceu.io.both": "Обидва",
"gtceu.io.export": "Експорт",
@@ -3227,25 +3227,23 @@
"gtceu.maintenance.configurable_time": "Час: %fx",
"gtceu.maintenance.configurable_time.changed_description": "Проблеми з обслуговуванням виникатимуть у %f разів частіше.",
"gtceu.maintenance.configurable_time.unchanged_description": "Проблеми з обслуговуванням виникатимуть зі звичайною швидкістю. Змініть конфігурацію для оновлення.",
- "gtceu.medical_condition.antidote.description": "§aПротиотрута§7 Утримуйте Shift для подробиць",
- "gtceu.medical_condition.antidote.description.effect_removed": "Знешкоджує %s%% наявних ефектів уражень",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "Знешкоджує усі ураження",
- "gtceu.medical_condition.antidote.description_shift": "§aВиліковує ці ураження:",
- "gtceu.medical_condition.arsenicosis": "§bОтруєння миш'яком",
- "gtceu.medical_condition.asbestosis": "§dАзбестоз",
- "gtceu.medical_condition.berylliosis": "§5Бериліоз",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7Отруєння монооксидом вуглецю",
- "gtceu.medical_condition.carcinogen": "§eРадіоактивне опромінення",
- "gtceu.medical_condition.chemical_burns": "§5Хімічні опіки",
- "gtceu.medical_condition.description": "§l§cНЕБЕЗПЕЧНО§7 Утримуйте Shift для подробиць",
- "gtceu.medical_condition.description_shift": "§l§cНЕБЕЗПЕКА:",
- "gtceu.medical_condition.irritant": "§6Подразення",
- "gtceu.medical_condition.methanol_poisoning": "§6Отруєння метанолом",
- "gtceu.medical_condition.nausea": "§3Нудота",
- "gtceu.medical_condition.none": "§2(Не²)Безпечно",
- "gtceu.medical_condition.poison": "§2Отрута",
- "gtceu.medical_condition.silicosis": "§1Силікоз",
- "gtceu.medical_condition.weak_poison": "§aСлабка отрута",
+ "tooltip.gtceu.antidote.description": "§aПротиотрута§7 Утримуйте Shift для подробиць",
+ "tooltip.gtceu.antidote.description.effect_removed": "Знешкоджує %s%% наявних ефектів уражень",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "Знешкоджує усі ураження",
+ "tooltip.gtceu.antidote.description_shift": "§aВиліковує ці ураження:",
+ "tooltip.gtceu.medical_condition.description": "§l§cНЕБЕЗПЕЧНО§7 Утримуйте Shift для подробиць",
+ "tooltip.gtceu.medical_condition.description_shift": "§l§cНЕБЕЗПЕКА:",
+ "medical_condition.gtceu.arsenicosis": "§bОтруєння миш'яком",
+ "medical_condition.gtceu.asbestosis": "§dАзбестоз",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7Отруєння монооксидом вуглецю",
+ "medical_condition.gtceu.carcinogen": "§eРадіоактивне опромінення",
+ "medical_condition.gtceu.chemical_burns": "§5Хімічні опіки",
+ "medical_condition.gtceu.irritant": "§6Подразення",
+ "medical_condition.gtceu.methanol_poisoning": "§6Отруєння метанолом",
+ "medical_condition.gtceu.nausea": "§3Нудота",
+ "medical_condition.gtceu.none": "§2(Не²)Безпечно",
+ "medical_condition.gtceu.poison": "§2Отрута",
+ "medical_condition.gtceu.weak_poison": "§aСлабка отрута",
"gtceu.minimap.ore_vein.depleted": "Виснажено",
"gtceu.mixer": "Змішувач",
"gtceu.mode.both": "§dСпільний (Рідини та предмети)§r",
@@ -5881,7 +5879,7 @@
"tile.gtceu.reinforced_foam.name": "Посилена піна",
"tile.gtceu.reinforced_stone.name": "Зміцнений камінь",
"tile.gtceu.seal.name": "Герметичний блок",
-
+
"comment": "застарілі рядки",
"behaviour.soft_hammer.idle_after_cycle": "Зупинити машину після завершення циклу роботи",
"block.gtceu.evaporation_plant": "Випарна вежа",
diff --git a/src/main/resources/assets/gtceu/lang/zh_cn.json b/src/main/resources/assets/gtceu/lang/zh_cn.json
index 057f5ffa80c..03f03315e53 100644
--- a/src/main/resources/assets/gtceu/lang/zh_cn.json
+++ b/src/main/resources/assets/gtceu/lang/zh_cn.json
@@ -2488,12 +2488,12 @@
"gtceu.gui.toggle_view.disabled": "切换视图(流体)",
"gtceu.gui.toggle_view.enabled": "切换视图(物品)",
"gtceu.gui.waiting_list": "发送队列:",
- "gtceu.hazard_trigger.any": "任何方式",
- "gtceu.hazard_trigger.description": "由此导致:",
- "gtceu.hazard_trigger.inhalation": "吸入",
- "gtceu.hazard_trigger.none": "无",
- "gtceu.hazard_trigger.protection.description": "免受:",
- "gtceu.hazard_trigger.skin_contact": "皮肤接触",
+ "tooltip.gtceu.hazard_trigger.any": "任何方式",
+ "tooltip.gtceu.hazard_trigger": "由此导致:",
+ "tooltip.gtceu.hazard_trigger.inhalation": "吸入",
+ "tooltip.gtceu.hazard_trigger.none": "无",
+ "tooltip.gtceu.hazard_trigger.protection": "免受:",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "皮肤接触",
"gtceu.implosion_compressor": "聚爆压缩机",
"gtceu.io.both": "同时",
"gtceu.io.export": "输出",
@@ -3249,25 +3249,23 @@
"gtceu.maintenance.configurable_time": "故障概率:%fx",
"gtceu.maintenance.configurable_time.changed_description": "故障的发生概率现为正常值的%f倍。",
"gtceu.maintenance.configurable_time.unchanged_description": "故障的发生概率为正常值。更改配置以更新。",
- "gtceu.medical_condition.antidote.description": "§a解毒剂 §7按住Shift以显示详情",
- "gtceu.medical_condition.antidote.description.effect_removed": "疾病效果持续时间降低%s%%",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "消除所有疾病效果",
- "gtceu.medical_condition.antidote.description_shift": "§a治愈以下疾病:",
- "gtceu.medical_condition.arsenicosis": "§b砷中毒",
- "gtceu.medical_condition.asbestosis": "§d石棉肺",
- "gtceu.medical_condition.berylliosis": "§5铍中毒",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7一氧化碳污染",
- "gtceu.medical_condition.carcinogen": "§e致癌",
- "gtceu.medical_condition.chemical_burns": "§5化学烧伤",
- "gtceu.medical_condition.description": "§c§l危险物质 §7按住Shift以显示详情",
- "gtceu.medical_condition.description_shift": "§c§l危险物质:",
- "gtceu.medical_condition.irritant": "§6刺激性",
- "gtceu.medical_condition.methanol_poisoning": "§6甲醇中毒",
- "gtceu.medical_condition.nausea": "§3恶心",
- "gtceu.medical_condition.none": "§2无害",
- "gtceu.medical_condition.poison": "§2中毒",
- "gtceu.medical_condition.silicosis": "§1矽肺病",
- "gtceu.medical_condition.weak_poison": "§a轻度中毒",
+ "tooltip.gtceu.antidote.description": "§a解毒剂 §7按住Shift以显示详情",
+ "tooltip.gtceu.antidote.description.effect_removed": "疾病效果持续时间降低%s%%",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "消除所有疾病效果",
+ "tooltip.gtceu.antidote.description_shift": "§a治愈以下疾病:",
+ "medical_condition.gtceu.arsenicosis": "§b砷中毒",
+ "medical_condition.gtceu.asbestosis": "§d石棉肺",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7一氧化碳污染",
+ "medical_condition.gtceu.carcinogen": "§e致癌",
+ "medical_condition.gtceu.chemical_burns": "§5化学烧伤",
+ "tooltip.gtceu.medical_condition.description": "§c§l危险物质 §7按住Shift以显示详情",
+ "tooltip.gtceu.medical_condition.description_shift": "§c§l危险物质:",
+ "medical_condition.gtceu.irritant": "§6刺激性",
+ "medical_condition.gtceu.methanol_poisoning": "§6甲醇中毒",
+ "medical_condition.gtceu.nausea": "§3恶心",
+ "medical_condition.gtceu.none": "§2无害",
+ "medical_condition.gtceu.poison": "§2中毒",
+ "medical_condition.gtceu.weak_poison": "§a轻度中毒",
"gtceu.minimap.ore_vein.depleted": "已枯竭",
"gtceu.mixer": "搅拌机",
"gtceu.mode.both": "§d全部(流体和物品)§r",
diff --git a/src/main/resources/assets/gtceu/lang/zh_tw.json b/src/main/resources/assets/gtceu/lang/zh_tw.json
index d295c7330e8..15f79b5205b 100644
--- a/src/main/resources/assets/gtceu/lang/zh_tw.json
+++ b/src/main/resources/assets/gtceu/lang/zh_tw.json
@@ -2382,12 +2382,12 @@
"gtceu.gui.toggle_view.disabled": "切換檢視(流體)",
"gtceu.gui.toggle_view.enabled": "切換檢視(物品)",
"gtceu.gui.waiting_list": "傳送佇列:",
- "gtceu.hazard_trigger.any": "任何方式",
- "gtceu.hazard_trigger.description": "肇因:",
- "gtceu.hazard_trigger.inhalation": "吸入",
- "gtceu.hazard_trigger.none": "無",
- "gtceu.hazard_trigger.protection.description": "免受:",
- "gtceu.hazard_trigger.skin_contact": "皮膚接觸",
+ "tooltip.gtceu.hazard_trigger.any": "任何方式",
+ "tooltip.gtceu.hazard_trigger": "肇因:",
+ "tooltip.gtceu.hazard_trigger.inhalation": "吸入",
+ "tooltip.gtceu.hazard_trigger.none": "無",
+ "tooltip.gtceu.hazard_trigger.protection": "免受:",
+ "tooltip.gtceu.hazard_trigger.skin_contact": "皮膚接觸",
"gtceu.implosion_compressor": "聚爆壓縮機",
"gtceu.io.both": "同時",
"gtceu.io.export": "輸出",
@@ -3128,25 +3128,23 @@
"gtceu.maintenance.configurable_time": "故障機率:%fx",
"gtceu.maintenance.configurable_time.changed_description": "故障的發生機率現為正常值的%f倍。",
"gtceu.maintenance.configurable_time.unchanged_description": "故障的發生機率為正常值。更改設定以更新。",
- "gtceu.medical_condition.antidote.description": "§a解毒劑 §7按住Shift以顯示詳情",
- "gtceu.medical_condition.antidote.description.effect_removed": "疾病效果持續時間降低%s%%",
- "gtceu.medical_condition.antidote.description.effect_removed.all": "消除所有疾病效果",
- "gtceu.medical_condition.antidote.description_shift": "§a治癒以下疾病:",
- "gtceu.medical_condition.arsenicosis": "§b砷中毒",
- "gtceu.medical_condition.asbestosis": "§d石棉肺",
- "gtceu.medical_condition.berylliosis": "§5鈹中毒",
- "gtceu.medical_condition.carbon_monoxide_poisoning": "§7一氧化碳汙染",
- "gtceu.medical_condition.carcinogen": "§e致癌",
- "gtceu.medical_condition.chemical_burns": "§5化學燒傷",
- "gtceu.medical_condition.description": "§c§l危險物質 §7按住Shift以顯示詳情",
- "gtceu.medical_condition.description_shift": "§c§l危險物質:",
- "gtceu.medical_condition.irritant": "§6刺激性",
- "gtceu.medical_condition.methanol_poisoning": "§6甲醇中毒",
- "gtceu.medical_condition.nausea": "§3噁心",
- "gtceu.medical_condition.none": "§2無害",
- "gtceu.medical_condition.poison": "§2中毒",
- "gtceu.medical_condition.silicosis": "§1矽肺病",
- "gtceu.medical_condition.weak_poison": "§a輕度中毒",
+ "tooltip.gtceu.antidote.description": "§a解毒劑 §7按住Shift以顯示詳情",
+ "tooltip.gtceu.antidote.description.effect_removed": "疾病效果持續時間降低%s%%",
+ "tooltip.gtceu.antidote.description.effect_removed.all": "消除所有疾病效果",
+ "tooltip.gtceu.antidote.description_shift": "§a治癒以下疾病:",
+ "medical_condition.gtceu.arsenicosis": "§b砷中毒",
+ "medical_condition.gtceu.asbestosis": "§d石棉肺",
+ "medical_condition.gtceu.carbon_monoxide_poisoning": "§7一氧化碳汙染",
+ "medical_condition.gtceu.carcinogen": "§e致癌",
+ "medical_condition.gtceu.chemical_burns": "§5化學燒傷",
+ "tooltip.gtceu.medical_condition.description": "§c§l危險物質 §7按住Shift以顯示詳情",
+ "tooltip.gtceu.medical_condition.description_shift": "§c§l危險物質:",
+ "medical_condition.gtceu.irritant": "§6刺激性",
+ "medical_condition.gtceu.methanol_poisoning": "§6甲醇中毒",
+ "medical_condition.gtceu.nausea": "§3噁心",
+ "medical_condition.gtceu.none": "§2無害",
+ "medical_condition.gtceu.poison": "§2中毒",
+ "medical_condition.gtceu.weak_poison": "§a輕度中毒",
"gtceu.minimap.ore_vein.depleted": "已枯竭",
"gtceu.mixer": "攪拌機",
"gtceu.mode.both": "§d全部(流體和物品)§r",
diff --git a/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTest.java b/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTest.java
new file mode 100644
index 00000000000..41cb339519f
--- /dev/null
+++ b/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTest.java
@@ -0,0 +1,340 @@
+package com.gregtechceu.gtceu.common.capability;
+
+import com.gregtechceu.gtceu.GTCEu;
+import com.gregtechceu.gtceu.api.data.chemical.ChemicalHelper;
+import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom;
+import com.gregtechceu.gtceu.api.data.tag.TagPrefix;
+import com.gregtechceu.gtceu.common.data.GTItems;
+import com.gregtechceu.gtceu.common.data.GTMaterials;
+import com.gregtechceu.gtceu.common.data.GTMedicalConditions;
+import com.gregtechceu.gtceu.gametest.util.TestUtils;
+
+import net.minecraft.gametest.framework.BeforeBatch;
+import net.minecraft.gametest.framework.GameTest;
+import net.minecraft.gametest.framework.GameTestHelper;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.util.Mth;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.effect.MobEffects;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.ai.attributes.Attributes;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
+import net.minecraftforge.gametest.GameTestHolder;
+import net.minecraftforge.gametest.PrefixGameTestTemplate;
+
+import lombok.experimental.ExtensionMethod;
+
+@SuppressWarnings("unused")
+@PrefixGameTestTemplate(false)
+@GameTestHolder(GTCEu.MOD_ID)
+@ExtensionMethod({ TestUtils.class, MedicalConditionTestHelpers.class })
+public class MedicalConditionTest {
+
+ @BeforeBatch(batch = "medical_conditions")
+ public static void prepare(ServerLevel level) {}
+
+ // spotless:off
+ // FIXME this is optional because the nausea potion effect doesnt want to stick
+ // and I haven't been able to figure out why
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 450, required = false)
+ public static void testMedicalConditionTicking(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // add a reasonable count of nausea (100 counts)
+ helper.addMedicalConditionCounts(player, GTMedicalConditions.NAUSEA, 450);
+
+ helper.startSequence()
+ // tick the medical condition tracker for 5 seconds
+ // this clears 20 counts of nausea
+ .thenExecuteFor(2 * 20, player::doTick)
+ // check if player has nausea effect
+ .thenExecute(() -> helper.assertTrue(player.hasEffect(MobEffects.CONFUSION),
+ "Player " + player + " should have nausea effect"))
+ // remove extra nausea
+ .thenExecute(() -> helper.getMedicalConditionTracker(player).heal(GTMedicalConditions.NAUSEA, 350))
+ // nausea condition lowers by 5 'counts' per second
+ // so the player should have it for another (90 / 5) = 18 seconds
+ // see comment on the next thing for explanation about why 15 instead of 18
+ .thenExecuteFor(15 * 20, () -> {
+ player.doTick();
+ helper.assertHasCondition(player, GTMedicalConditions.NAUSEA);
+ })
+ // I'm not actually sure how long this should be applying for, so...
+ // tick the player for 5 more seconds, just to be safe
+ .thenExecuteFor(5 * 20, player::doTick)
+ .thenExecute(() -> helper.assertFreeOfCondition(player, GTMedicalConditions.NAUSEA))
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 450)
+ public static void testItemHazardApplication(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // give player 1x Nt ingot (VERY radioactive, 10 'counts' per second)
+ player.addItem(ChemicalHelper.get(TagPrefix.ingot, GTMaterials.Neutronium));
+
+ helper.startSequence()
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player has 100 'counts' of cancer
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.CARCINOGEN, 100))
+ // remove Nt ingot from player
+ .thenExecute(() -> player.getInventory().clearContent())
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check that count hasn't changed
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.CARCINOGEN, 100))
+ // add more cancer to reach max slowness symptom
+ .thenExecute(() -> helper.setMedicalConditionCounts(player, GTMedicalConditions.CARCINOGEN, 18000))
+ // tick the medical condition tracker for 2 ticks, just to be safe
+ .thenExecuteFor(2, player::doTick)
+ // check that the slowness attribute modifier is properly applied.
+ .thenExecute(() -> {
+ double modifier = MedicalConditionTestHelpers.getAndAssertAttributeModifier(player, Attributes.MOVEMENT_SPEED, Symptom.SYMPTOM_SLOWNESS_UUID);
+ // this value is based on the slowness symptom's default stage count and multiplier (7 and 0.08 respectively)
+ helper.assertTrue(Mth.equal(modifier, -7 * 0.05f),
+ "Slowness symprom attribute modifier should have a value of " + (-7 * 0.05f) + " at 18000 counts. (is " + modifier + ")");
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 450)
+ public static void testHazardProtectionInhalation(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // equip face mask
+ player.setItemSlot(EquipmentSlot.HEAD, GTItems.FACE_MASK.asStack());
+ // give 16x asbestos dust
+ player.addItem(ChemicalHelper.get(TagPrefix.dust, GTMaterials.Asbestos, 16));
+
+ helper.startSequence()
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player did NOT get asbestosis
+ .thenExecute(() -> helper.assertFreeOfCondition(player, GTMedicalConditions.ASBESTOSIS))
+ // remove face mask
+ .thenExecute(() -> player.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY))
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player DID get asbestosis this time
+ .thenExecute(() -> {
+ if (!player.isAlive()) return; // we don't care if the player died here, that means the asbestos got them
+ helper.assertHasCondition(player, GTMedicalConditions.ASBESTOSIS);
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 450)
+ public static void testHazardProtectionSkinContact(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // equip rubber gloves
+ player.setItemSlot(EquipmentSlot.CHEST, GTItems.RUBBER_GLOVES.asStack());
+ // give a bucket of Fluorine
+ player.addItem(new ItemStack(GTMaterials.Fluorine.getBucket()));
+
+ helper.startSequence()
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player did NOT get chemical burns
+ .thenExecute(() -> helper.assertFreeOfCondition(player, GTMedicalConditions.CHEMICAL_BURNS))
+ // remove rubber gloves
+ .thenExecute(() -> player.setItemSlot(EquipmentSlot.CHEST, ItemStack.EMPTY))
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player DID get chemical burns this time
+ .thenExecute(() -> {
+ if (!player.isAlive()) return; // we don't care if the player died here, that means the chemical burns got them
+ helper.assertHasCondition(player, GTMedicalConditions.CHEMICAL_BURNS);
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 450)
+ public static void testHazardProtectionAnyContact(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // equip hazmat suit
+ player.setItemSlot(EquipmentSlot.HEAD, GTItems.HAZMAT_HELMET.asStack());
+ player.setItemSlot(EquipmentSlot.CHEST, GTItems.HAZMAT_CHESTPLATE.asStack());
+ player.setItemSlot(EquipmentSlot.LEGS, GTItems.HAZMAT_LEGGINGS.asStack());
+ player.setItemSlot(EquipmentSlot.FEET, GTItems.HAZMAT_BOOTS.asStack());
+ // give 16x Cadmium dust
+ player.addItem(ChemicalHelper.get(TagPrefix.dust, GTMaterials.Cadmium, 16));
+
+ helper.startSequence()
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player did NOT get poisoned
+ .thenExecute(() -> helper.assertFreeOfCondition(player, GTMedicalConditions.POISON))
+ // remove hazmat suit
+ .thenExecute(() -> {
+ player.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY);
+ player.setItemSlot(EquipmentSlot.CHEST, ItemStack.EMPTY);
+ player.setItemSlot(EquipmentSlot.LEGS, ItemStack.EMPTY);
+ player.setItemSlot(EquipmentSlot.FEET, ItemStack.EMPTY);
+ })
+ // tick the medical condition tracker for 10 seconds
+ .thenExecuteFor(10 * 20, player::doTick)
+ // check if player DID get poisoned this time
+ .thenExecute(() -> {
+ if (!player.isAlive()) return; // we don't care if the player died here, that means the poisoning got them
+ helper.assertHasCondition(player, GTMedicalConditions.POISON);
+ })
+ .thenSucceed();
+ }
+
+ // TODO add test for consumption hazard if that ever gets used for anything
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 350)
+ public static void testGeneralAntidoteWorksOnWeakPoison(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // give the player Regeneration 7 so they don't die
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 350, 6));
+ // add a low-ish count of weak poisoning
+ helper.addMedicalConditionCounts(player, GTMedicalConditions.WEAK_POISON, 100);
+ // give Player 16x Paracetamol
+ ItemStack pillStack = GTItems.PARACETAMOL_PILL.asStack(16);
+ player.setItemInHand(InteractionHand.MAIN_HAND, pillStack);
+
+ final long startTick = helper.getTick();
+
+ helper.startSequence()
+ // tick the medical condition tracker for 2 seconds
+ .thenExecuteFor(2 * 20, player::doTick)
+ // check that count hasn't changed
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.WEAK_POISON, 100))
+ // make player eat Paracetamol for 16 * 16 = 256 ticks
+ // (+2 for safety)
+ .thenExecuteFor(16 * 16 + 2, () -> {
+ player.doTick();
+ // constantly eat another item
+ var result = helper.useItem(player,
+ player.getItemInHand(InteractionHand.MAIN_HAND));
+ if (result.getResult().consumesAction()) {
+ player.setItemInHand(InteractionHand.MAIN_HAND, result.getObject());
+ }
+ })
+ .thenExecute(() -> {
+ // check if they were all consumed
+ helper.assertHeldItemCountIs(player, Items.AIR, 0, InteractionHand.MAIN_HAND);
+ // check that the poisoning is gone
+ helper.assertFreeOfCondition(player, GTMedicalConditions.WEAK_POISON);
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 350)
+ public static void testGeneralAntidoteDoesntWorkOnCancer(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // give the player Regeneration 7 so they don't die
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 350, 6));
+ // add a low-ish count of weak poisoning
+ helper.addMedicalConditionCounts(player, GTMedicalConditions.CARCINOGEN, 100);
+ // give Player 16x Paracetamol
+ ItemStack pillStack = GTItems.PARACETAMOL_PILL.asStack(16);
+ player.setItemInHand(InteractionHand.MAIN_HAND, pillStack);
+
+ final long startTick = helper.getTick();
+
+ helper.startSequence()
+ // tick the medical condition tracker for 2 seconds
+ .thenExecuteFor(2 * 20, player::doTick)
+ // check that count hasn't changed
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.CARCINOGEN, 100))
+ // make player eat Paracetamol for 16 * 16 = 256 ticks
+ // (+2 for safety)
+ .thenExecuteFor(16 * 16 + 2, () -> {
+ player.doTick();
+ // constantly eat another item
+ var result = helper.useItem(player,
+ player.getItemInHand(InteractionHand.MAIN_HAND));
+ if (result.getResult().consumesAction()) {
+ player.setItemInHand(InteractionHand.MAIN_HAND, result.getObject());
+ }
+ })
+ .thenExecute(() -> {
+ // check if they were all consumed
+ helper.assertHeldItemCountIs(player, Items.AIR, 0, InteractionHand.MAIN_HAND);
+ // check that count is STILL 100, as Paracetamol shouldn't be able to remove cancer.
+ helper.assertConditionCountEquals(player, GTMedicalConditions.CARCINOGEN, 100);
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 350)
+ public static void testRadAwayWorksOnCancer(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // give the player Regeneration 7 so they don't
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 350, 6));
+ // add a low count of cancer
+ helper.addMedicalConditionCounts(player, GTMedicalConditions.CARCINOGEN, 100);
+ // give Player 16x RadAway
+ ItemStack pillStack = GTItems.RAD_AWAY_PILL.asStack(16);
+ player.setItemInHand(InteractionHand.MAIN_HAND, pillStack);
+
+ final long startTick = helper.getTick();
+
+ helper.startSequence()
+ // tick the medical condition tracker for 2 seconds
+ .thenExecuteFor(2 * 20, player::doTick)
+ // check that count hasn't changed
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.CARCINOGEN, 100))
+ // make player eat RadAway for 16 * 16 = 256 ticks
+ // (+2 for safety)
+ .thenExecuteFor(16 * 16 + 2, () -> {
+ player.doTick();
+ // constantly eat another item
+ var result = helper.useItem(player,
+ player.getItemInHand(InteractionHand.MAIN_HAND));
+ if (result.getResult().consumesAction()) {
+ player.setItemInHand(InteractionHand.MAIN_HAND, result.getObject());
+ }
+ })
+ .thenExecute(() -> {
+ // check if they were all consumed
+ helper.assertHeldItemCountIs(player, Items.AIR, 0, InteractionHand.MAIN_HAND);
+ // check that the cancer is gone
+ helper.assertFreeOfCondition(player, GTMedicalConditions.CARCINOGEN);
+ })
+ .thenSucceed();
+ }
+
+ @GameTest(template = "empty", batch = "medical_conditions", timeoutTicks = 350)
+ public static void testRadAwayDoesntWorkOnWeakPoison(GameTestHelper helper) {
+ ServerPlayer player = helper.makeMockSurvivalServerPlayer();
+ // give the player Regeneration 7 so they don't
+ player.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 350, 6));
+ // add a low-ish count of weak poisoning
+ helper.addMedicalConditionCounts(player, GTMedicalConditions.WEAK_POISON, 100);
+ // give Player 16x RadAway
+ ItemStack pillStack = GTItems.RAD_AWAY_PILL.asStack(16);
+ player.setItemInHand(InteractionHand.MAIN_HAND, pillStack);
+
+ final long startTick = helper.getTick();
+
+ helper.startSequence()
+ // tick the medical condition tracker for 2 seconds
+ .thenExecuteFor(2 * 20, player::doTick)
+ // check that count hasn't changed
+ .thenExecute(() -> helper.assertConditionCountEquals(player, GTMedicalConditions.WEAK_POISON, 100))
+ // make player eat RadAway for 16 * 16 = 256 ticks
+ // (+2 for safety)
+ .thenExecuteFor(16 * 16 + 2, () -> {
+ player.doTick();
+ // constantly eat another item
+ var result = helper.useItem(player,
+ player.getItemInHand(InteractionHand.MAIN_HAND));
+ if (result.getResult().consumesAction()) {
+ player.setItemInHand(InteractionHand.MAIN_HAND, result.getObject());
+ }
+ })
+ .thenExecute(() -> {
+ // check if they were all consumed
+ helper.assertHeldItemCountIs(player, Items.AIR, 0, InteractionHand.MAIN_HAND);
+ // check that count is STILL 100, as RadAway shouldn't be able to remove weak poisoning.
+ helper.assertConditionCountEquals(player, GTMedicalConditions.WEAK_POISON, 100);
+ })
+ .thenSucceed();
+ }
+
+ // spotless:on
+}
diff --git a/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTestHelpers.java b/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTestHelpers.java
new file mode 100644
index 00000000000..35ac98256c3
--- /dev/null
+++ b/src/test/java/com/gregtechceu/gtceu/common/capability/MedicalConditionTestHelpers.java
@@ -0,0 +1,64 @@
+package com.gregtechceu.gtceu.common.capability;
+
+import com.gregtechceu.gtceu.api.capability.GTCapabilityHelper;
+import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
+import com.gregtechceu.gtceu.gametest.util.TestUtils;
+
+import net.minecraft.gametest.framework.GameTestHelper;
+import net.minecraft.util.Mth;
+import net.minecraft.world.entity.ai.attributes.Attribute;
+import net.minecraft.world.entity.player.Player;
+
+import lombok.experimental.ExtensionMethod;
+
+import java.util.UUID;
+
+@ExtensionMethod(TestUtils.class)
+public class MedicalConditionTestHelpers {
+
+ public static void addMedicalConditionCounts(GameTestHelper helper, Player player,
+ MedicalCondition condition, float counts) {
+ getMedicalConditionTracker(helper, player).progressCondition(condition, counts);
+ }
+
+ public static void setMedicalConditionCounts(GameTestHelper helper, Player player,
+ MedicalCondition condition, float counts) {
+ MedicalConditionTracker tracker = getMedicalConditionTracker(helper, player);
+ tracker.medicalConditions.put(condition, counts);
+ tracker.updateActiveSymptoms();
+ }
+
+ public static void clearMedicalCondition(GameTestHelper helper, Player player, MedicalCondition condition) {
+ getMedicalConditionTracker(helper, player).removeMedicalCondition(condition);
+ }
+
+ public static MedicalConditionTracker getMedicalConditionTracker(GameTestHelper helper, Player player) {
+ helper.assertEntityAlive(player);
+ MedicalConditionTracker tracker = GTCapabilityHelper.getMedicalConditionTracker(player);
+ helper.assertTrue(tracker != null,
+ "Player " + player + " doesn't have a medical condition tracker capability");
+ return tracker;
+ }
+
+ public static void assertHasCondition(GameTestHelper helper, Player player, MedicalCondition condition) {
+ helper.assertTrue(getMedicalConditionTracker(helper, player).medicalConditions.containsKey(condition),
+ "Player " + player + " should have medical condition " + condition.id);
+ }
+
+ public static void assertFreeOfCondition(GameTestHelper helper, Player player, MedicalCondition condition) {
+ helper.assertFalse(getMedicalConditionTracker(helper, player).medicalConditions.containsKey(condition),
+ "Player " + player + " should not have medical condition " + condition.id);
+ }
+
+ public static void assertConditionCountEquals(GameTestHelper helper, Player player,
+ MedicalCondition condition, float expectedCounts) {
+ float counts = getMedicalConditionTracker(helper, player).medicalConditions.getFloat(condition);
+ helper.assertTrue(Mth.equal(counts, expectedCounts),
+ "Player " + player + " should have " + expectedCounts + " 'counts' of medical condition " +
+ condition.id + ", has " + counts);
+ }
+
+ public static double getAndAssertAttributeModifier(Player player, Attribute attribute, UUID modifierId) {
+ return player.getAttributes().getModifierValue(attribute, modifierId);
+ }
+}
diff --git a/src/test/java/com/gregtechceu/gtceu/gametest/util/TestUtils.java b/src/test/java/com/gregtechceu/gtceu/gametest/util/TestUtils.java
index 6c2840a8c17..e49368fbfd3 100644
--- a/src/test/java/com/gregtechceu/gtceu/gametest/util/TestUtils.java
+++ b/src/test/java/com/gregtechceu/gtceu/gametest/util/TestUtils.java
@@ -16,12 +16,20 @@
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.common.item.behavior.CoverPlaceBehavior;
+import com.gregtechceu.gtceu.utils.fakeplayer.FakeServerGamePacketListenerImpl;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.gametest.framework.GameTestAssertPosException;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.network.chat.MutableComponent;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.InteractionResultHolder;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.RecipeType;
@@ -29,10 +37,12 @@
import net.minecraft.world.level.block.RedstoneLampBlock;
import net.minecraftforge.fluids.FluidStack;
+import com.mojang.authlib.GameProfile;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Objects;
+import java.util.UUID;
import static com.gregtechceu.gtceu.common.data.GTRecipeTypes.ELECTRIC;
@@ -313,4 +323,45 @@ public static void assertRedstoneEither(GameTestHelper helper, BlockPos pos, int
absolutePos, pos, helper.getTick());
}
}
+
+ public static ServerPlayer makeMockSurvivalServerPlayer(GameTestHelper helper) {
+ MinecraftServer server = helper.getLevel().getServer();
+ ServerPlayer player = new ServerPlayer(server, helper.getLevel(),
+ new GameProfile(UUID.randomUUID(), "test-mock-player")) {
+
+ public boolean isSpectator() {
+ return false;
+ }
+
+ public boolean isCreative() {
+ return false;
+ }
+ };
+ player.connection = new FakeServerGamePacketListenerImpl(server, player);
+ return player;
+ }
+
+ public static InteractionResultHolder useItem(GameTestHelper helper, Player player, ItemStack item) {
+ return useItem(helper, player, item, InteractionHand.MAIN_HAND);
+ }
+
+ public static InteractionResultHolder useItem(GameTestHelper helper, Player player, ItemStack item,
+ InteractionHand hand) {
+ return item.use(helper.getLevel(), player, hand);
+ }
+
+ public static void assertHeldItemCountIs(GameTestHelper helper, Player player,
+ @Nullable Item item, int count, InteractionHand hand) {
+ ItemStack stack = player.getItemInHand(hand);
+ if (item != null && item != Items.AIR) {
+ helper.assertTrue(stack.is(item), "Item stack " + stack + " in hand " + hand + " is not a " + item);
+ }
+ helper.assertTrue(stack.getCount() == count,
+ "Item stack " + stack + " in hand " + hand + " should have " + count + " items, has " +
+ stack.getCount());
+ }
+
+ public static void assertEntityAlive(GameTestHelper helper, Entity entity) {
+ helper.assertTrue(entity.isAlive(), "Entity " + entity + " should be alive");
+ }
}