From 1d46e9679f067ca04e8291d6bb36ddba8e4bfe93 Mon Sep 17 00:00:00 2001 From: vorlie Date: Mon, 13 Jan 2025 16:37:42 +0100 Subject: [PATCH 1/4] Make particles client-side only, add mod menu, cloth config support and translation files. --- build.gradle | 7 ++ gradle.properties | 4 +- .../vorlie/lifedrain/LifeDrainClient.java | 62 +++++++++++++- .../vorlie/lifedrain/ModMenuIntegration.java | 85 +++++++++++++++++++ src/main/java/vorlie/lifedrain/LifeDrain.java | 24 +----- .../assets/lifedrain/lang/de_de.json | 10 +++ .../assets/lifedrain/lang/en_us.json | 10 +++ .../assets/lifedrain/lang/es_es.json | 10 +++ .../assets/lifedrain/lang/es_mx.json | 10 +++ .../assets/lifedrain/lang/fr_fr.json | 10 +++ .../assets/lifedrain/lang/ja_jp.json | 10 +++ .../assets/lifedrain/lang/ko_kr.json | 10 +++ .../assets/lifedrain/lang/pl_pl.json | 10 +++ .../assets/lifedrain/lang/ru_ru.json | 10 +++ .../assets/lifedrain/lang/zh_cn.json | 10 +++ src/main/resources/fabric.mod.json | 8 ++ 16 files changed, 267 insertions(+), 23 deletions(-) create mode 100644 src/client/java/vorlie/lifedrain/ModMenuIntegration.java create mode 100644 src/main/resources/assets/lifedrain/lang/de_de.json create mode 100644 src/main/resources/assets/lifedrain/lang/en_us.json create mode 100644 src/main/resources/assets/lifedrain/lang/es_es.json create mode 100644 src/main/resources/assets/lifedrain/lang/es_mx.json create mode 100644 src/main/resources/assets/lifedrain/lang/fr_fr.json create mode 100644 src/main/resources/assets/lifedrain/lang/ja_jp.json create mode 100644 src/main/resources/assets/lifedrain/lang/ko_kr.json create mode 100644 src/main/resources/assets/lifedrain/lang/pl_pl.json create mode 100644 src/main/resources/assets/lifedrain/lang/ru_ru.json create mode 100644 src/main/resources/assets/lifedrain/lang/zh_cn.json diff --git a/build.gradle b/build.gradle index 5b0c2c9..ec6b95f 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,8 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + maven { url "https://maven.shedaniel.me/" } + maven { url "https://maven.terraformersmc.com/releases/" } } loom { @@ -44,6 +46,11 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + modApi("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { + exclude(group: "net.fabricmc.fabric-api") + } + modApi "com.terraformersmc:modmenu:${project.mod_menu_version}" } processResources { diff --git a/gradle.properties b/gradle.properties index 5fa1fc1..d7aa752 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,4 +14,6 @@ maven_group=vorlie.lifedrain archives_base_name=lifedrain # Dependencies -fabric_version=0.102.0+1.21 \ No newline at end of file +fabric_version=0.102.0+1.21 +cloth_config_version=15.0.140 +mod_menu_version=11.0.3 \ No newline at end of file diff --git a/src/client/java/vorlie/lifedrain/LifeDrainClient.java b/src/client/java/vorlie/lifedrain/LifeDrainClient.java index b971d2c..95e22bd 100644 --- a/src/client/java/vorlie/lifedrain/LifeDrainClient.java +++ b/src/client/java/vorlie/lifedrain/LifeDrainClient.java @@ -2,9 +2,67 @@ import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; +import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.mob.HostileEntity; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.math.random.Random; + +import vorlie.lifedrain.config.ConfigManager; + public class LifeDrainClient implements ClientModInitializer { + private long lastLifestealTime = 0; // Time of the last lifesteal + private long COOLDOWN_TIME; // Cooldown time in milliseconds (1 second) + @Override public void onInitializeClient() { - // This entrypoint is suitable for setting up client-specific logic, such as rendering. + + COOLDOWN_TIME = ConfigManager.CONFIG.lifestealCooldown; + + // Initialization logic for client-specific features + AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { + if (world.isClient && entity instanceof HostileEntity) { + if (canActivateLifesteal()) { + handleLifesteal(player, (HostileEntity) entity); + } + } + return ActionResult.PASS; + }); + + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, success) -> { + ConfigManager.load(); + COOLDOWN_TIME = ConfigManager.CONFIG.lifestealCooldown; + }); + } + + private void handleLifesteal(PlayerEntity player, HostileEntity mob) { + if (player != null && mob != null && mob.isAlive()) { + if (player.getHealth() < player.getMaxHealth()) { + if (ConfigManager.CONFIG.enableParticles) { + ClientWorld world = MinecraftClient.getInstance().world; + if (world != null) { + Random random = player.getRandom(); + for (int i = 0; i < 10; i++) { + world.addParticle( + ParticleTypes.HEART, // The particle type (HEART in this case) + player.getX() + random.nextDouble() - 0.5, // X offset + player.getY() + random.nextDouble(), // Y offset + player.getZ() + random.nextDouble() - 0.5, // Z offset + 0, 0, 0); // Particle velocity (no movement) + } + } + } + } + lastLifestealTime = System.currentTimeMillis(); + } + } + + private boolean canActivateLifesteal() { + long currentTime = System.currentTimeMillis(); + return (currentTime - lastLifestealTime) >= COOLDOWN_TIME; } -} \ No newline at end of file +} diff --git a/src/client/java/vorlie/lifedrain/ModMenuIntegration.java b/src/client/java/vorlie/lifedrain/ModMenuIntegration.java new file mode 100644 index 0000000..9be5ae1 --- /dev/null +++ b/src/client/java/vorlie/lifedrain/ModMenuIntegration.java @@ -0,0 +1,85 @@ +package vorlie.lifedrain; + +import com.terraformersmc.modmenu.api.ConfigScreenFactory; +import com.terraformersmc.modmenu.api.ModMenuApi; + +import me.shedaniel.clothconfig2.api.ConfigBuilder; +import me.shedaniel.clothconfig2.api.ConfigCategory; +import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import net.minecraft.text.Text; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import vorlie.lifedrain.config.ConfigManager; + +@Environment(EnvType.CLIENT) // Ensure this only runs on the client side +public class ModMenuIntegration implements ModMenuApi { + private static final Logger LOGGER = LoggerFactory.getLogger("lifedrain"); + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + LOGGER.info("ModMenuIntegration loaded successfully."); + return parent -> { + ConfigBuilder builder = ConfigBuilder.create() + .setParentScreen(parent) + .setTitle(Text.translatable("config.lifedrain.title")); + + ConfigCategory general = builder.getOrCreateCategory(Text.translatable("config.lifedrain.general")); + ConfigEntryBuilder entryBuilder = builder.entryBuilder(); + + // Enable Particles + general.addEntry(entryBuilder + .startBooleanToggle(Text.translatable("config.lifedrain.enableParticles"), ConfigManager.CONFIG.enableParticles) + .setDefaultValue(true) + .setSaveConsumer(value -> ConfigManager.CONFIG.enableParticles = value) + .build()); + + // Lifesteal Cooldown + general.addEntry(entryBuilder + .startIntField(Text.translatable("config.lifedrain.lifestealCooldown"), ConfigManager.CONFIG.lifestealCooldown) + .setDefaultValue(1000) + .setMin(0) + .setSaveConsumer(value -> ConfigManager.CONFIG.lifestealCooldown = value) + .build()); + + // Base Heal (Easy) + general.addEntry(entryBuilder + .startFloatField(Text.translatable("config.lifedrain.baseHealEasy"), ConfigManager.CONFIG.baseHealEasy) + .setDefaultValue(2.0F) + .setMin(0.0F) + .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealEasy = value) + .build()); + + // Base Heal (Normal) + general.addEntry(entryBuilder + .startFloatField(Text.translatable("config.lifedrain.baseHealNormal"), ConfigManager.CONFIG.baseHealNormal) + .setDefaultValue(1.0F) + .setMin(0.0F) + .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealNormal = value) + .build()); + + // Base Heal (Hard) + general.addEntry(entryBuilder + .startFloatField(Text.translatable("config.lifedrain.baseHealHard"), ConfigManager.CONFIG.baseHealHard) + .setDefaultValue(0.5F) + .setMin(0.0F) + .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealHard = value) + .build()); + + // Bonus Heal Multiplier + general.addEntry(entryBuilder + .startFloatField(Text.translatable("config.lifedrain.bonusHealMultiplier"), ConfigManager.CONFIG.bonusHealMultiplier) + .setDefaultValue(0.2F) + .setMin(0.0F) + .setSaveConsumer(value -> ConfigManager.CONFIG.bonusHealMultiplier = value) + .build()); + + builder.setSavingRunnable(ConfigManager::save); + return builder.build(); + }; + } +} diff --git a/src/main/java/vorlie/lifedrain/LifeDrain.java b/src/main/java/vorlie/lifedrain/LifeDrain.java index e267a6a..7dd1f28 100644 --- a/src/main/java/vorlie/lifedrain/LifeDrain.java +++ b/src/main/java/vorlie/lifedrain/LifeDrain.java @@ -3,15 +3,11 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.player.AttackEntityCallback; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.ActionResult; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.random.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,10 +44,11 @@ public void onInitialize() { COOLDOWN_TIME = ConfigManager.CONFIG.lifestealCooldown; }); - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> { - ConfigCheckCommand.register(dispatcher); // Only two parameters are expected here + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> { + ConfigCheckCommand.register(dispatcher); // Register your custom command }); } + private void handleLifesteal(PlayerEntity player, HostileEntity mob) { if (player != null && mob != null && mob.isAlive()) { // Base healing amount from configuration @@ -70,19 +67,6 @@ private void handleLifesteal(PlayerEntity player, HostileEntity mob) { float totalHeal = baseHeal + bonusHeal; player.heal(totalHeal); - // Show particles if enabled - if (ConfigManager.CONFIG.enableParticles && player.getWorld() instanceof ServerWorld serverWorld) { - Random random = player.getRandom(); - for (int i = 0; i < 10; i++) { - serverWorld.spawnParticles( - ParticleTypes.HEART, - player.getX() + random.nextDouble() - 0.5, - player.getY() + random.nextDouble(), - player.getZ() + random.nextDouble() - 0.5, - 1, 0, 0, 0, 0); - } - } - LOGGER.info("Lifesteal: {} healed {} (Base: {}, Bonus: {}).", player.getName().getString(), totalHeal, baseHeal, bonusHeal); diff --git a/src/main/resources/assets/lifedrain/lang/de_de.json b/src/main/resources/assets/lifedrain/lang/de_de.json new file mode 100644 index 0000000..80585b2 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/de_de.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "LifeDrain Konfiguration", + "config.lifedrain.general": "Allgemein", + "config.lifedrain.enableParticles": "Partikel aktivieren", + "config.lifedrain.lifestealCooldown": "Lebensdiebstahl Abklingzeit (ms)", + "config.lifedrain.baseHealEasy": "Basisheilung (Einfach)", + "config.lifedrain.baseHealNormal": "Basisheilung (Normal)", + "config.lifedrain.baseHealHard": "Basisheilung (Schwierig)", + "config.lifedrain.bonusHealMultiplier": "Bonus Heilungs Multiplikator" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/en_us.json b/src/main/resources/assets/lifedrain/lang/en_us.json new file mode 100644 index 0000000..e3d42b0 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/en_us.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "LifeDrain Configuration", + "config.lifedrain.general": "General", + "config.lifedrain.enableParticles": "Enable Particles", + "config.lifedrain.lifestealCooldown": "Lifesteal Cooldown (ms)", + "config.lifedrain.baseHealEasy": "Base Heal (Easy)", + "config.lifedrain.baseHealNormal": "Base Heal (Normal)", + "config.lifedrain.baseHealHard": "Base Heal (Hard)", + "config.lifedrain.bonusHealMultiplier": "Bonus Heal Multiplier" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/es_es.json b/src/main/resources/assets/lifedrain/lang/es_es.json new file mode 100644 index 0000000..4ba03f6 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/es_es.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "Configuración de LifeDrain", + "config.lifedrain.general": "General", + "config.lifedrain.enableParticles": "Habilitar partículas", + "config.lifedrain.lifestealCooldown": "Tiempo de recarga de robar vida (ms)", + "config.lifedrain.baseHealEasy": "Curación base (Fácil)", + "config.lifedrain.baseHealNormal": "Curación base (Normal)", + "config.lifedrain.baseHealHard": "Curación base (Difícil)", + "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación adicional" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/es_mx.json b/src/main/resources/assets/lifedrain/lang/es_mx.json new file mode 100644 index 0000000..a26f8a6 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/es_mx.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "Configuración de LifeDrain", + "config.lifedrain.general": "General", + "config.lifedrain.enableParticles": "Activar partículas", + "config.lifedrain.lifestealCooldown": "Tiempo de recarga de robo de vida (ms)", + "config.lifedrain.baseHealEasy": "Curación base (Fácil)", + "config.lifedrain.baseHealNormal": "Curación base (Normal)", + "config.lifedrain.baseHealHard": "Curación base (Difícil)", + "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación extra" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/fr_fr.json b/src/main/resources/assets/lifedrain/lang/fr_fr.json new file mode 100644 index 0000000..861518f --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/fr_fr.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "Configuración de LifeDrain", + "config.lifedrain.general": "General", + "config.lifedrain.enableParticles": "Habilitar partículas", + "config.lifedrain.lifestealCooldown": "Temps de recharge du vol de vie (ms)", + "config.lifedrain.baseHealEasy": "Guérison de base (Facile)", + "config.lifedrain.baseHealNormal": "Guérison de base (Normal)", + "config.lifedrain.baseHealHard": "Guérison de base (Difficile)", + "config.lifedrain.bonusHealMultiplier": "Multiplicateur de guérison bonus" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ja_jp.json b/src/main/resources/assets/lifedrain/lang/ja_jp.json new file mode 100644 index 0000000..036d89e --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/ja_jp.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "LifeDrainの設定", + "config.lifedrain.general": "一般", + "config.lifedrain.enableParticles": "パーティクルを有効にする", + "config.lifedrain.lifestealCooldown": "ライフスティールクールダウン (ms)", + "config.lifedrain.baseHealEasy": "基本回復 (イージー)", + "config.lifedrain.baseHealNormal": "基本回復 (ノーマル)", + "config.lifedrain.baseHealHard": "基本回復 (ハード)", + "config.lifedrain.bonusHealMultiplier": "ボーナス回復乗数" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ko_kr.json b/src/main/resources/assets/lifedrain/lang/ko_kr.json new file mode 100644 index 0000000..d010d5f --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/ko_kr.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "LifeDrain 설정", + "config.lifedrain.general": "일반", + "config.lifedrain.enableParticles": "입자 효과 활성화", + "config.lifedrain.lifestealCooldown": "생명력 흡수 쿨타임 (ms)", + "config.lifedrain.baseHealEasy": "기본 치유 (쉬움)", + "config.lifedrain.baseHealNormal": "기본 치유 (일반)", + "config.lifedrain.baseHealHard": "기본 치유 (어려움)", + "config.lifedrain.bonusHealMultiplier": "보너스 치유 배율" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/pl_pl.json b/src/main/resources/assets/lifedrain/lang/pl_pl.json new file mode 100644 index 0000000..53766d4 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/pl_pl.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "Konfiguracja LifeDrain", + "config.lifedrain.general": "Ogólne", + "config.lifedrain.enableParticles": "Włącz cząsteczki", + "config.lifedrain.lifestealCooldown": "Czas odnowienia Lifesteal (ms)", + "config.lifedrain.baseHealEasy": "Podstawowe Leczenie (Łatwy)", + "config.lifedrain.baseHealNormal": "Podstawowe Leczenie (Normalny)", + "config.lifedrain.baseHealHard": "Podstawowe Leczenie (Trudny)", + "config.lifedrain.bonusHealMultiplier": "Mnożnik Leczenia Bonusowego" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ru_ru.json b/src/main/resources/assets/lifedrain/lang/ru_ru.json new file mode 100644 index 0000000..79b2c99 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/ru_ru.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "Настройки LifeDrain", + "config.lifedrain.general": "Общее", + "config.lifedrain.enableParticles": "Включить частицы", + "config.lifedrain.lifestealCooldown": "Время восстановления воровства жизни (мс)", + "config.lifedrain.baseHealEasy": "Основное исцеление (Легкий)", + "config.lifedrain.baseHealNormal": "Основное исцеление (Нормальный)", + "config.lifedrain.baseHealHard": "Основное исцеление (Трудный)", + "config.lifedrain.bonusHealMultiplier": "Множитель бонусного исцеления" +} \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/zh_cn.json b/src/main/resources/assets/lifedrain/lang/zh_cn.json new file mode 100644 index 0000000..d9f3cd4 --- /dev/null +++ b/src/main/resources/assets/lifedrain/lang/zh_cn.json @@ -0,0 +1,10 @@ +{ + "config.lifedrain.title": "LifeDrain 配置", + "config.lifedrain.general": "通用", + "config.lifedrain.enableParticles": "启用粒子效果", + "config.lifedrain.lifestealCooldown": "吸血冷却时间 (毫秒)", + "config.lifedrain.baseHealEasy": "基础治疗 (简单)", + "config.lifedrain.baseHealNormal": "基础治疗 (正常)", + "config.lifedrain.baseHealHard": "基础治疗 (困难)", + "config.lifedrain.bonusHealMultiplier": "额外治疗倍增" +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 3c15997..e3f974a 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -22,6 +22,9 @@ ], "fabric-datagen": [ "vorlie.lifedrain.LifeDrainDataGenerator" + ], + "modmenu": [ + "vorlie.lifedrain.ModMenuIntegration" ] }, "mixins": [ @@ -38,5 +41,10 @@ "fabric-api": ">=0.102.0+1.21" }, "suggests": { + "cloth-config": "15.0.140", + "modmenu": "11.0.3" + }, + "custom": { + "modmenu:api": true } } \ No newline at end of file From 9476a169f4dc1809e8788acda7bafef42c0aeb66 Mon Sep 17 00:00:00 2001 From: vorlie Date: Mon, 13 Jan 2025 17:04:29 +0100 Subject: [PATCH 2/4] Add tooltips --- .../java/vorlie/lifedrain/ModMenuIntegration.java | 10 +++++++++- src/main/java/vorlie/lifedrain/LifeDrain.java | 4 ++-- src/main/resources/assets/lifedrain/lang/de_de.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/en_us.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/es_es.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/es_mx.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/fr_fr.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/ja_jp.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/ko_kr.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/pl_pl.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/ru_ru.json | 8 +++++++- src/main/resources/assets/lifedrain/lang/zh_cn.json | 8 +++++++- 12 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/client/java/vorlie/lifedrain/ModMenuIntegration.java b/src/client/java/vorlie/lifedrain/ModMenuIntegration.java index 9be5ae1..17e120c 100644 --- a/src/client/java/vorlie/lifedrain/ModMenuIntegration.java +++ b/src/client/java/vorlie/lifedrain/ModMenuIntegration.java @@ -20,9 +20,11 @@ @Environment(EnvType.CLIENT) // Ensure this only runs on the client side public class ModMenuIntegration implements ModMenuApi { private static final Logger LOGGER = LoggerFactory.getLogger("lifedrain"); + @Override public ConfigScreenFactory getModConfigScreenFactory() { - LOGGER.info("ModMenuIntegration loaded successfully."); + LOGGER.info("Lifesteal: ModMenuIntegration loaded successfully."); + return parent -> { ConfigBuilder builder = ConfigBuilder.create() .setParentScreen(parent) @@ -36,6 +38,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .startBooleanToggle(Text.translatable("config.lifedrain.enableParticles"), ConfigManager.CONFIG.enableParticles) .setDefaultValue(true) .setSaveConsumer(value -> ConfigManager.CONFIG.enableParticles = value) + .setTooltip(Text.translatable("config.lifedrain.enableParticles.tooltip")) .build()); // Lifesteal Cooldown @@ -44,6 +47,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setDefaultValue(1000) .setMin(0) .setSaveConsumer(value -> ConfigManager.CONFIG.lifestealCooldown = value) + .setTooltip(Text.translatable("config.lifedrain.lifestealCooldown.tooltip")) .build()); // Base Heal (Easy) @@ -52,6 +56,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setDefaultValue(2.0F) .setMin(0.0F) .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealEasy = value) + .setTooltip(Text.translatable("config.lifedrain.baseHealEasy.tooltip")) .build()); // Base Heal (Normal) @@ -60,6 +65,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setDefaultValue(1.0F) .setMin(0.0F) .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealNormal = value) + .setTooltip(Text.translatable("config.lifedrain.baseHealNormal.tooltip")) .build()); // Base Heal (Hard) @@ -68,6 +74,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setDefaultValue(0.5F) .setMin(0.0F) .setSaveConsumer(value -> ConfigManager.CONFIG.baseHealHard = value) + .setTooltip(Text.translatable("config.lifedrain.baseHealHard.tooltip")) .build()); // Bonus Heal Multiplier @@ -76,6 +83,7 @@ public ConfigScreenFactory getModConfigScreenFactory() { .setDefaultValue(0.2F) .setMin(0.0F) .setSaveConsumer(value -> ConfigManager.CONFIG.bonusHealMultiplier = value) + .setTooltip(Text.translatable("config.lifedrain.bonusHealMultiplier.tooltip")) .build()); builder.setSavingRunnable(ConfigManager::save); diff --git a/src/main/java/vorlie/lifedrain/LifeDrain.java b/src/main/java/vorlie/lifedrain/LifeDrain.java index 7dd1f28..47a4d7e 100644 --- a/src/main/java/vorlie/lifedrain/LifeDrain.java +++ b/src/main/java/vorlie/lifedrain/LifeDrain.java @@ -23,7 +23,7 @@ public class LifeDrain implements ModInitializer { @Override public void onInitialize() { - LOGGER.info("LifeDrain mod initialized!"); + LOGGER.info("Lifesteal: LifeDrain mod initialized!"); ConfigManager.load(); // Load configuration COOLDOWN_TIME = ConfigManager.CONFIG.lifestealCooldown; @@ -40,7 +40,7 @@ public void onInitialize() { // Register the config reload event ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, success) -> { ConfigManager.load(); - LOGGER.info("LifeDrain config reloaded."); + LOGGER.info("Lifesteal: LifeDrain config reloaded."); COOLDOWN_TIME = ConfigManager.CONFIG.lifestealCooldown; }); diff --git a/src/main/resources/assets/lifedrain/lang/de_de.json b/src/main/resources/assets/lifedrain/lang/de_de.json index 80585b2..b133dc7 100644 --- a/src/main/resources/assets/lifedrain/lang/de_de.json +++ b/src/main/resources/assets/lifedrain/lang/de_de.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Basisheilung (Einfach)", "config.lifedrain.baseHealNormal": "Basisheilung (Normal)", "config.lifedrain.baseHealHard": "Basisheilung (Schwierig)", - "config.lifedrain.bonusHealMultiplier": "Bonus Heilungs Multiplikator" + "config.lifedrain.bonusHealMultiplier": "Bonus Heilungs Multiplikator", + "config.lifedrain.enableParticles.tooltip": "Diese Einstellung betrifft nur den Client. Der Server kann sie überschreiben. Im Einzelspieler-Modus funktionieren die Werte lokal.", + "config.lifedrain.lifestealCooldown.tooltip": "Der Cooldown-Wert des Servers wird verwendet, und die Client-Einstellungen werden ignoriert. Im Einzelspieler-Modus funktionieren die Werte lokal.", + "config.lifedrain.baseHealEasy.tooltip": "Der Server bestimmt die Grundheilungswerte. Im Einzelspieler-Modus funktionieren die Werte lokal.", + "config.lifedrain.baseHealNormal.tooltip": "Der Server bestimmt die Grundheilungswerte. Im Einzelspieler-Modus funktionieren die Werte lokal.", + "config.lifedrain.baseHealHard.tooltip": "Der Server bestimmt die Grundheilungswerte. Im Einzelspieler-Modus funktionieren die Werte lokal.", + "config.lifedrain.bonusHealMultiplier.tooltip": "Der Server bestimmt den Bonusheilungs-Multiplikator. Im Einzelspieler-Modus funktionieren die Werte lokal." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/en_us.json b/src/main/resources/assets/lifedrain/lang/en_us.json index e3d42b0..9912611 100644 --- a/src/main/resources/assets/lifedrain/lang/en_us.json +++ b/src/main/resources/assets/lifedrain/lang/en_us.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Base Heal (Easy)", "config.lifedrain.baseHealNormal": "Base Heal (Normal)", "config.lifedrain.baseHealHard": "Base Heal (Hard)", - "config.lifedrain.bonusHealMultiplier": "Bonus Heal Multiplier" + "config.lifedrain.bonusHealMultiplier": "Bonus Heal Multiplier", + "config.lifedrain.enableParticles.tooltip": "This setting only affects the client. The server may override it. In single-player, values will work locally.", + "config.lifedrain.lifestealCooldown.tooltip": "Server-side cooldown value is used, and client settings are ignored. In single-player, values will work locally.", + "config.lifedrain.baseHealEasy.tooltip": "Server determines the base healing values. In single-player, values will work locally.", + "config.lifedrain.baseHealNormal.tooltip": "Server determines the base healing values. In single-player, values will work locally.", + "config.lifedrain.baseHealHard.tooltip": "Server determines the base healing values. In single-player, values will work locally.", + "config.lifedrain.bonusHealMultiplier.tooltip": "Server determines the bonus healing multiplier. In single-player, values will work locally." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/es_es.json b/src/main/resources/assets/lifedrain/lang/es_es.json index 4ba03f6..de1ae22 100644 --- a/src/main/resources/assets/lifedrain/lang/es_es.json +++ b/src/main/resources/assets/lifedrain/lang/es_es.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Curación base (Fácil)", "config.lifedrain.baseHealNormal": "Curación base (Normal)", "config.lifedrain.baseHealHard": "Curación base (Difícil)", - "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación adicional" + "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación adicional", + "config.lifedrain.enableParticles.tooltip": "Esta opción solo afecta al cliente. El servidor puede sobrescribirla. En single-player, los valores funcionarán localmente.", + "config.lifedrain.lifestealCooldown.tooltip": "El valor de cooldown del servidor se usa, y los ajustes del cliente son ignorados. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealEasy.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealNormal.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealHard.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.bonusHealMultiplier.tooltip": "El servidor determina el multiplicador de curación adicional. En single-player, los valores funcionarán localmente." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/es_mx.json b/src/main/resources/assets/lifedrain/lang/es_mx.json index a26f8a6..0c94eed 100644 --- a/src/main/resources/assets/lifedrain/lang/es_mx.json +++ b/src/main/resources/assets/lifedrain/lang/es_mx.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Curación base (Fácil)", "config.lifedrain.baseHealNormal": "Curación base (Normal)", "config.lifedrain.baseHealHard": "Curación base (Difícil)", - "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación extra" + "config.lifedrain.bonusHealMultiplier": "Multiplicador de curación extra", + "config.lifedrain.enableParticles.tooltip": "Esta opción solo afecta al cliente. El servidor puede sobrescribirla. En single-player, los valores funcionarán localmente.", + "config.lifedrain.lifestealCooldown.tooltip": "El valor de cooldown del servidor se usa, y los ajustes del cliente son ignorados. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealEasy.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealNormal.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.baseHealHard.tooltip": "El servidor determina los valores base de curación. En single-player, los valores funcionarán localmente.", + "config.lifedrain.bonusHealMultiplier.tooltip": "El servidor determina el multiplicador de curación adicional. En single-player, los valores funcionarán localmente." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/fr_fr.json b/src/main/resources/assets/lifedrain/lang/fr_fr.json index 861518f..2ac98ea 100644 --- a/src/main/resources/assets/lifedrain/lang/fr_fr.json +++ b/src/main/resources/assets/lifedrain/lang/fr_fr.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Guérison de base (Facile)", "config.lifedrain.baseHealNormal": "Guérison de base (Normal)", "config.lifedrain.baseHealHard": "Guérison de base (Difficile)", - "config.lifedrain.bonusHealMultiplier": "Multiplicateur de guérison bonus" + "config.lifedrain.bonusHealMultiplier": "Multiplicateur de guérison bonus", + "config.lifedrain.enableParticles.tooltip": "Cette option n'affecte que le client. Le serveur peut la remplacer. En single-player, les valeurs fonctionneront localement.", + "config.lifedrain.lifestealCooldown.tooltip": "La valeur de cooldown du serveur est utilisée, les paramètres du client sont ignorés. En single-player, les valeurs fonctionneront localement.", + "config.lifedrain.baseHealEasy.tooltip": "Le serveur détermine les valeurs de guérison de base. En single-player, les valeurs fonctionneront localement.", + "config.lifedrain.baseHealNormal.tooltip": "Le serveur détermine les valeurs de guérison de base. En single-player, les valeurs fonctionneront localement.", + "config.lifedrain.baseHealHard.tooltip": "Le serveur détermine les valeurs de guérison de base. En single-player, les valeurs fonctionneront localement.", + "config.lifedrain.bonusHealMultiplier.tooltip": "Le serveur détermine le multiplicateur de guérison bonus. En single-player, les valeurs fonctionneront localement." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ja_jp.json b/src/main/resources/assets/lifedrain/lang/ja_jp.json index 036d89e..d32098b 100644 --- a/src/main/resources/assets/lifedrain/lang/ja_jp.json +++ b/src/main/resources/assets/lifedrain/lang/ja_jp.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "基本回復 (イージー)", "config.lifedrain.baseHealNormal": "基本回復 (ノーマル)", "config.lifedrain.baseHealHard": "基本回復 (ハード)", - "config.lifedrain.bonusHealMultiplier": "ボーナス回復乗数" + "config.lifedrain.bonusHealMultiplier": "ボーナス回復乗数", + "config.lifedrain.enableParticles.tooltip": "この設定はクライアントにのみ影響します。サーバーが上書きする可能性があります。シングルプレイヤーでは値がローカルで適用されます。", + "config.lifedrain.lifestealCooldown.tooltip": "サーバー側のクールダウン値が使用され、クライアント設定は無視されます。シングルプレイヤーでは値がローカルで適用されます。", + "config.lifedrain.baseHealEasy.tooltip": "サーバーが基本的な回復値を決定します。シングルプレイヤーでは値がローカルで適用されます。", + "config.lifedrain.baseHealNormal.tooltip": "サーバーが基本的な回復値を決定します。シングルプレイヤーでは値がローカルで適用されます。", + "config.lifedrain.baseHealHard.tooltip": "サーバーが基本的な回復値を決定します。シングルプレイヤーでは値がローカルで適用されます。", + "config.lifedrain.bonusHealMultiplier.tooltip": "サーバーがボーナス回復倍率を決定します。シングルプレイヤーでは値がローカルで適用されます。" } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ko_kr.json b/src/main/resources/assets/lifedrain/lang/ko_kr.json index d010d5f..255b20e 100644 --- a/src/main/resources/assets/lifedrain/lang/ko_kr.json +++ b/src/main/resources/assets/lifedrain/lang/ko_kr.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "기본 치유 (쉬움)", "config.lifedrain.baseHealNormal": "기본 치유 (일반)", "config.lifedrain.baseHealHard": "기본 치유 (어려움)", - "config.lifedrain.bonusHealMultiplier": "보너스 치유 배율" + "config.lifedrain.bonusHealMultiplier": "보너스 치유 배율", + "config.lifedrain.enableParticles.tooltip": "이 설정은 클라이언트에만 영향을 미칩니다. 서버에서 덮어쓸 수 있습니다. 싱글 플레이어에서 값은 로컬로 적용됩니다.", + "config.lifedrain.lifestealCooldown.tooltip": "서버 측 쿨다운 값이 사용되며, 클라이언트 설정은 무시됩니다. 싱글 플레이어에서 값은 로컬로 적용됩니다.", + "config.lifedrain.baseHealEasy.tooltip": "서버가 기본 치유 값을 결정합니다. 싱글 플레이어에서 값은 로컬로 적용됩니다.", + "config.lifedrain.baseHealNormal.tooltip": "서버가 기본 치유 값을 결정합니다. 싱글 플레이어에서 값은 로컬로 적용됩니다.", + "config.lifedrain.baseHealHard.tooltip": "서버가 기본 치유 값을 결정합니다. 싱글 플레이어에서 값은 로컬로 적용됩니다.", + "config.lifedrain.bonusHealMultiplier.tooltip": "서버가 보너스 치유 배율을 결정합니다. 싱글 플레이어에서 값은 로컬로 적용됩니다." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/pl_pl.json b/src/main/resources/assets/lifedrain/lang/pl_pl.json index 53766d4..2f1002c 100644 --- a/src/main/resources/assets/lifedrain/lang/pl_pl.json +++ b/src/main/resources/assets/lifedrain/lang/pl_pl.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Podstawowe Leczenie (Łatwy)", "config.lifedrain.baseHealNormal": "Podstawowe Leczenie (Normalny)", "config.lifedrain.baseHealHard": "Podstawowe Leczenie (Trudny)", - "config.lifedrain.bonusHealMultiplier": "Mnożnik Leczenia Bonusowego" + "config.lifedrain.bonusHealMultiplier": "Mnożnik Leczenia Bonusowego", + "config.lifedrain.enableParticles.tooltip": "To ustawienie wpływa tylko na klienta. Serwer może je nadpisać. W trybie single-player wartości będą działały lokalnie.", + "config.lifedrain.lifestealCooldown.tooltip": "Wartość cooldownu serwera jest używana, a ustawienia klienta są ignorowane. W trybie single-player wartości będą działały lokalnie.", + "config.lifedrain.baseHealEasy.tooltip": "Serwer ustala podstawowe wartości leczenia. W trybie single-player wartości będą działały lokalnie.", + "config.lifedrain.baseHealNormal.tooltip": "Serwer ustala podstawowe wartości leczenia. W trybie single-player wartości będą działały lokalnie.", + "config.lifedrain.baseHealHard.tooltip": "Serwer ustala podstawowe wartości leczenia. W trybie single-player wartości będą działały lokalnie.", + "config.lifedrain.bonusHealMultiplier.tooltip": "Serwer ustala mnożnik bonusowego leczenia. W trybie single-player wartości będą działały lokalnie." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/ru_ru.json b/src/main/resources/assets/lifedrain/lang/ru_ru.json index 79b2c99..9ec19f0 100644 --- a/src/main/resources/assets/lifedrain/lang/ru_ru.json +++ b/src/main/resources/assets/lifedrain/lang/ru_ru.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "Основное исцеление (Легкий)", "config.lifedrain.baseHealNormal": "Основное исцеление (Нормальный)", "config.lifedrain.baseHealHard": "Основное исцеление (Трудный)", - "config.lifedrain.bonusHealMultiplier": "Множитель бонусного исцеления" + "config.lifedrain.bonusHealMultiplier": "Множитель бонусного исцеления", + "config.lifedrain.enableParticles.tooltip": "Эта настройка влияет только на клиент. Сервер может её переопределить. В синглплеере значения будут работать локально.", + "config.lifedrain.lifestealCooldown.tooltip": "Значение времени восстановления на сервере используется, а настройки клиента игнорируются. В синглплеере значения будут работать локально.", + "config.lifedrain.baseHealEasy.tooltip": "Сервер определяет основные значения исцеления. В синглплеере значения будут работать локально.", + "config.lifedrain.baseHealNormal.tooltip": "Сервер определяет основные значения исцеления. В синглплеере значения будут работать локально.", + "config.lifedrain.baseHealHard.tooltip": "Сервер определяет основные значения исцеления. В синглплеере значения будут работать локально.", + "config.lifedrain.bonusHealMultiplier.tooltip": "Сервер определяет множитель дополнительного исцеления. В синглплеере значения будут работать локально." } \ No newline at end of file diff --git a/src/main/resources/assets/lifedrain/lang/zh_cn.json b/src/main/resources/assets/lifedrain/lang/zh_cn.json index d9f3cd4..c93a795 100644 --- a/src/main/resources/assets/lifedrain/lang/zh_cn.json +++ b/src/main/resources/assets/lifedrain/lang/zh_cn.json @@ -6,5 +6,11 @@ "config.lifedrain.baseHealEasy": "基础治疗 (简单)", "config.lifedrain.baseHealNormal": "基础治疗 (正常)", "config.lifedrain.baseHealHard": "基础治疗 (困难)", - "config.lifedrain.bonusHealMultiplier": "额外治疗倍增" + "config.lifedrain.bonusHealMultiplier": "额外治疗倍增", + "config.lifedrain.enableParticles.tooltip": "此设置仅影响客户端。服务器可能会覆盖它。在单人游戏中,值将本地生效。", + "config.lifedrain.lifestealCooldown.tooltip": "服务器的冷却时间值会被使用,客户端设置将被忽略。在单人游戏中,值将本地生效。", + "config.lifedrain.baseHealEasy.tooltip": "服务器决定基础治疗值。在单人游戏中,值将本地生效。", + "config.lifedrain.baseHealNormal.tooltip": "服务器决定基础治疗值。在单人游戏中,值将本地生效。", + "config.lifedrain.baseHealHard.tooltip": "服务器决定基础治疗值。在单人游戏中,值将本地生效。", + "config.lifedrain.bonusHealMultiplier.tooltip": "服务器决定额外治疗倍数。在单人游戏中,值将本地生效。" } \ No newline at end of file From e9ce891e96c510f5ae6ba93213d80db8c21e9e72 Mon Sep 17 00:00:00 2001 From: vorlie Date: Mon, 13 Jan 2025 17:05:51 +0100 Subject: [PATCH 3/4] Update mod version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d7aa752..70078c7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.21+build.9 loader_version=0.16.10 # Mod Properties -mod_version=1.0.3 +mod_version=1.0.4 maven_group=vorlie.lifedrain archives_base_name=lifedrain From e1ad0ca7d460a75ebb47ae9dde70b0cfcd12835c Mon Sep 17 00:00:00 2001 From: vorlie Date: Mon, 13 Jan 2025 17:13:37 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a4c3cb1..dbaf52f 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,53 @@ +# **LifeDrain** + **LifeDrain** adds a simple but powerful mechanic to Minecraft: stealing life from hostile mobs. Every time you attack, you’ll heal yourself based on the damage dealt, making combat a way to stay alive rather than just survive. 🩸 **Features:** -- Healing mechanics: +- **Healing mechanics:** - Base healing scales with the difficulty level: - Easy: 2.0 HP - Normal: 1.0 HP - Hard: 0.5 HP - Bonus healing based on the damage dealt: 20% of the damage dealt. - Lifesteal cooldown is set to 1000 milliseconds (1 second) by default. +- **Client-Side Features:** + - **Particle Effects:** Enable or disable particle effects when healing is triggered. Particles are client-side, meaning they will only be visible on your screen. + - **Client-Side Configuration Options:** Through **Cloth Config** and **Mod Menu**, you can customize particle effects, cooldown settings, and other features directly from the in-game settings menu. - Applies only to hostile mobs, ensuring lifesteal is balanced and works as intended in combat. ⚙️ **Configuration:** - Customize healing values for different difficulty levels: - Base healing for Easy, Normal, and Hard modes. - Bonus healing multiplier based on the damage dealt. -- Enable or disable particle effects when healing is triggered. -- Adjust the cooldown for lifesteal activation (time between consecutive lifesteal uses). -- Configuration is saved to `PATH-TO-MINECRAFT-INSTANCE/config/lifedrain.json` and can be modified directly. +- **Client-Side Customization:** + - Enable or disable particle effects when healing is triggered (client-side only). + - Adjust the cooldown for lifesteal activation (time between consecutive lifesteal uses). + - Configuration options are accessible through **Cloth Config** and **Mod Menu**. +- All settings are saved to `lifedrain.json` and can be modified directly. - The config file is automatically updated to add missing values if they are not found. - Use the `/check_config` command to automatically check and update the config file if necessary. +**Translations Available:** +The mod is fully translated into the following languages: +- **English** +- **Polish** +- **Spanish (Mexico)** +- **Spanish** +- **Chinese (Simplified)** +- **Korean** +- **Russian** +- **German** +- **Japanese** +- **French** + This mod is lightweight and perfect for anyone who enjoys combat-focused gameplay or just wants a little extra survivability. **Note:** Although the mod can be loaded in Minecraft `1.21.X`, it is not recommended. Attacking a hostile mob in versions other than `1.21` will cause your game to crash. **Requirements:** -- Fabric Loader 0.16.10+ -- Fabric API 0.102.0+1.21+ +- Fabric Loader 0.16.10 +- Fabric API 0.102.0 (for Minecraft 1.21) - Minecraft 1.21 -- Java 21+ +- Java 21 +- **Cloth Config 15.0.140** (Client-side, optional) +- **Mod Menu 11.0.3** (Client-side, optional)