diff --git a/build.gradle b/build.gradle index 20e6ea3..8f53f5c 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'maven-publish' } -version = project.mod_version +version = "${project.mod_version}-${project.minecraft_version}" group = project.maven_group base { @@ -14,7 +14,6 @@ loom { accessWidenerPath = file("src/main/resources/widgets.accesswidener") } - repositories { // Add repositories to retrieve artifacts from in here. // You should only use this when depending on other mods because @@ -86,21 +85,3 @@ jar { rename { "${it}_${project.archivesBaseName}" } } } - -// configure the maven publication -publishing { - publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } -} diff --git a/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java b/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java index c7b825f..408c140 100644 --- a/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java +++ b/src/main/java/de/shiewk/widgets/client/WidgetsModClient.java @@ -10,6 +10,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; @@ -69,5 +70,9 @@ public class WidgetsModClient implements ClientModInitializer { WidgetManager.register(new BiomeWidget(Identifier.of(WidgetsMod.MOD_ID, "biome"))); WidgetManager.register(new SpeedWidget(Identifier.of(WidgetsMod.MOD_ID, "speed"))); WidgetManager.register(new ArmorHudWidget(Identifier.of(WidgetsMod.MOD_ID, "armor"))); + + ComboWidget comboWidget = new ComboWidget(Identifier.of(WidgetsMod.MOD_ID, "combo")); + WidgetManager.register(comboWidget); + AttackEntityCallback.EVENT.register(comboWidget); } } diff --git a/src/main/java/de/shiewk/widgets/mixin/MixinClientPlayNetworkHandler.java b/src/main/java/de/shiewk/widgets/mixin/MixinClientPlayNetworkHandler.java index 9e013c6..e501617 100644 --- a/src/main/java/de/shiewk/widgets/mixin/MixinClientPlayNetworkHandler.java +++ b/src/main/java/de/shiewk/widgets/mixin/MixinClientPlayNetworkHandler.java @@ -1,8 +1,12 @@ package de.shiewk.widgets.mixin; +import de.shiewk.widgets.widgets.ComboWidget; import de.shiewk.widgets.widgets.TPSWidget; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.packet.s2c.play.DamageTiltS2CPacket; +import net.minecraft.network.packet.s2c.play.EntityDamageS2CPacket; import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -18,4 +22,22 @@ public class MixinClientPlayNetworkHandler { // server sends this packet every 20 ticks TPSWidget.worldTimeUpdated(System.nanoTime()); } + + @Inject(at = @At("HEAD"), method = "onDamageTilt") + public void onDamageTilt(DamageTiltS2CPacket packet, CallbackInfo ci){ + if (MinecraftClient.getInstance().isOnThread()) return; + int entityId = packet.id(); + ClientPlayerEntity player = MinecraftClient.getInstance().player; + int playerId = player == null ? Integer.MIN_VALUE : player.getId(); + ComboWidget.entityTakeDamage(playerId, entityId); + } + + @Inject(at = @At("HEAD"), method = "onEntityDamage") + public void onEntityDamage(EntityDamageS2CPacket packet, CallbackInfo ci){ + if (MinecraftClient.getInstance().isOnThread()) return; + int entityId = packet.entityId(); + ClientPlayerEntity player = MinecraftClient.getInstance().player; + int playerId = player == null ? Integer.MIN_VALUE : player.getId(); + ComboWidget.entityTakeDamage(playerId, entityId); + } } diff --git a/src/main/java/de/shiewk/widgets/widgets/ComboWidget.java b/src/main/java/de/shiewk/widgets/widgets/ComboWidget.java new file mode 100644 index 0000000..e071417 --- /dev/null +++ b/src/main/java/de/shiewk/widgets/widgets/ComboWidget.java @@ -0,0 +1,113 @@ +package de.shiewk.widgets.widgets; + +import de.shiewk.widgets.WidgetSettings; +import de.shiewk.widgets.widgets.settings.IntSliderWidgetSetting; +import de.shiewk.widgets.widgets.settings.ToggleWidgetSetting; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static net.minecraft.text.Text.literal; +import static net.minecraft.text.Text.translatable; + +public class ComboWidget extends BasicTextWidget implements AttackEntityCallback { + + public ComboWidget(Identifier id) { + super(id, List.of( + new ToggleWidgetSetting("show_label", translatable("widgets.widgets.common.showLabel"), true), + new IntSliderWidgetSetting("display_threshold", translatable("widgets.widgets.combo.displayThreshold"), 0, 0, 5) + )); + if (INSTANCE != null) throw new IllegalStateException("Instance already initialized"); + INSTANCE = this; + } + + private static ComboWidget INSTANCE; + + private boolean showLabel = true; + private int targetEntityId = 0; + private boolean hitPlanned = false; + private int combo = 0; + private int ticksSinceUpdate = 0; + private int displayThreshold = 0; + + @Override + public ActionResult interact(PlayerEntity playerEntity, World world, Hand hand, Entity entity, @Nullable EntityHitResult entityHitResult) { + clientHitEntity(entity.getId()); + return ActionResult.PASS; + } + + private void clientHitEntity(int targetEntityId) { + int oldTarget = this.targetEntityId; + if (oldTarget != targetEntityId){ + resetCombo(); + } + this.targetEntityId = targetEntityId; + hitPlanned = true; + } + + public static void entityTakeDamage(int clientEntityId, int damagedEntityId){ + INSTANCE.entityTakeDamage0(clientEntityId, damagedEntityId); + } + + private void entityTakeDamage0(int clientEntityId, int damagedEntityId) { + if (damagedEntityId == clientEntityId){ + resetCombo(); + } else if (damagedEntityId == this.targetEntityId && this.hitPlanned){ + hitPlanned = false; + combo++; + ticksSinceUpdate = 0; + updateComboText(); + } + } + + @Override + public void tickWidget() { + if (ticksSinceUpdate > 40){ + resetCombo(); + hitPlanned = false; + } + ticksSinceUpdate++; + } + + private void resetCombo() { + combo = 0; + ticksSinceUpdate = 0; + updateComboText(); + } + + private void updateComboText() { + shouldRender = combo >= displayThreshold; + if (showLabel){ + formatAndSetRenderText(translatable("widgets.widgets.combo.combo", combo)); + } else { + formatAndSetRenderText(literal(""+combo)); + } + } + + @Override + public Text getName() { + return translatable("widgets.widgets.combo"); + } + + @Override + public Text getDescription() { + return translatable("widgets.widgets.combo.description"); + } + + @Override + public void onSettingsChanged(WidgetSettings settings) { + super.onSettingsChanged(settings); + this.displayThreshold = ((IntSliderWidgetSetting) settings.optionById("display_threshold")).getValue(); + this.showLabel = ((ToggleWidgetSetting) settings.optionById("show_label")).getValue(); + updateComboText(); + } +} diff --git a/src/main/java/de/shiewk/widgets/widgets/TPSWidget.java b/src/main/java/de/shiewk/widgets/widgets/TPSWidget.java index 955b316..a8e684f 100644 --- a/src/main/java/de/shiewk/widgets/widgets/TPSWidget.java +++ b/src/main/java/de/shiewk/widgets/widgets/TPSWidget.java @@ -22,6 +22,7 @@ public class TPSWidget extends BasicTextWidget { getSettings().optionById("textcolor").setShowCondition(() -> !this.dynamicColor && !this.rainbow); getSettings().optionById("rainbow").setShowCondition(() -> !this.dynamicColor); getSettings().optionById("rainbow_speed").setShowCondition(() -> !this.dynamicColor && this.rainbow); + if (INSTANCE != null) throw new IllegalStateException("Instance already initialized"); INSTANCE = this; } diff --git a/src/main/java/de/shiewk/widgets/widgets/settings/IntSliderWidgetSetting.java b/src/main/java/de/shiewk/widgets/widgets/settings/IntSliderWidgetSetting.java index c7ebb92..82e2a00 100644 --- a/src/main/java/de/shiewk/widgets/widgets/settings/IntSliderWidgetSetting.java +++ b/src/main/java/de/shiewk/widgets/widgets/settings/IntSliderWidgetSetting.java @@ -8,6 +8,7 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; public class IntSliderWidgetSetting extends WidgetSettingOption { @@ -26,10 +27,10 @@ public class IntSliderWidgetSetting extends WidgetSettingOption { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (maxValue > value && keyCode == 262) { // right arrow key + if (maxValue > value && keyCode == GLFW.GLFW_KEY_RIGHT) { value++; return true; - } else if (minValue < value && keyCode == 263){ // left arrow key + } else if (minValue < value && keyCode == GLFW.GLFW_KEY_LEFT){ value--; return true; } diff --git a/src/main/resources/assets/widgets/lang/de_de.json b/src/main/resources/assets/widgets/lang/de_de.json index 7d9e8b3..868e6b4 100644 --- a/src/main/resources/assets/widgets/lang/de_de.json +++ b/src/main/resources/assets/widgets/lang/de_de.json @@ -116,5 +116,9 @@ "widgets.widgets.tps": "TPS", "widgets.widgets.tps.description": "Zeigt die TPS im Einzelspielermodus an oder schätzt die TPS im Mehrspielermodus", "widgets.widgets.tps.dynamicColor": "Farbe dynamisch anzeigen", - "widgets.widgets.tps.tps": "%s TPS" + "widgets.widgets.tps.tps": "%s TPS", + "widgets.widgets.combo": "Combo", + "widgets.widgets.combo.description": "Zeigt deine momentane Combo an", + "widgets.widgets.combo.combo": "Combo: %s", + "widgets.widgets.combo.displayThreshold": "Minimum sichtbar" } \ No newline at end of file diff --git a/src/main/resources/assets/widgets/lang/en_us.json b/src/main/resources/assets/widgets/lang/en_us.json index 1941c0f..7a9eb93 100644 --- a/src/main/resources/assets/widgets/lang/en_us.json +++ b/src/main/resources/assets/widgets/lang/en_us.json @@ -116,5 +116,9 @@ "widgets.widgets.tps": "TPS", "widgets.widgets.tps.description": "Shows the current TPS when in singleplayer or estimates server TPS when in multiplayer", "widgets.widgets.tps.dynamicColor": "Dynamic Color", - "widgets.widgets.tps.tps": "%s TPS" + "widgets.widgets.tps.tps": "%s TPS", + "widgets.widgets.combo": "Combo", + "widgets.widgets.combo.description": "Shows your current Combo", + "widgets.widgets.combo.combo": "Combo: %s", + "widgets.widgets.combo.displayThreshold": "Display Threshold" } \ No newline at end of file