1
mirror of https://github.com/Shiewk/Widgets.git synced 2026-04-28 11:34:17 +02:00

Add combo widget (#3)

This commit is contained in:
Shy
2025-08-21 14:30:55 +02:00
parent 378ec01796
commit 4fe29d81ac
8 changed files with 155 additions and 24 deletions
+1 -20
View File
@@ -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.
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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;
}
@@ -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;
}
@@ -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"
}
@@ -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"
}