diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker')
5 files changed, 172 insertions, 5 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index e6cd3c54..369a9a90 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -8,12 +8,15 @@ import de.hysky.skyblocker.config.configs.UIAndVisualsConfig; import de.hysky.skyblocker.utils.waypoint.Waypoint; import dev.isxander.yacl3.api.ConfigCategory; import dev.isxander.yacl3.api.*; +import dev.isxander.yacl3.api.controller.ColorControllerBuilder; import dev.isxander.yacl3.api.controller.FloatFieldControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import java.awt.*; + public class UIAndVisualsCategory { public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig config) { return ConfigCategory.createBuilder() @@ -377,6 +380,49 @@ public class UIAndVisualsCategory { .build()) .build()) + //Compact Damage Numbers + .group(OptionGroup.createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage")) + .collapsed(true) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.enabled")) + .binding(defaults.uiAndVisuals.compactDamage.enabled, + () -> config.uiAndVisuals.compactDamage.enabled, + newValue -> config.uiAndVisuals.compactDamage.enabled = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Integer>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.precision")) + .description(OptionDescription.of(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.precision.@Tooltip"))) + .binding(defaults.uiAndVisuals.compactDamage.precision, + () -> config.uiAndVisuals.compactDamage.precision, + newValue -> config.uiAndVisuals.compactDamage.precision = newValue) + .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(1,3).step(1)) + .build()) + .option(Option.<Color>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.normalDamageColor")) + .binding(defaults.uiAndVisuals.compactDamage.normalDamageColor, + () -> config.uiAndVisuals.compactDamage.normalDamageColor, + newValue -> config.uiAndVisuals.compactDamage.normalDamageColor = newValue) + .controller(ColorControllerBuilder::create) + .build()) + .option(Option.<Color>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientStart")) + .binding(defaults.uiAndVisuals.compactDamage.critDamageGradientStart, + () -> config.uiAndVisuals.compactDamage.critDamageGradientStart, + newValue -> config.uiAndVisuals.compactDamage.critDamageGradientStart = newValue) + .controller(ColorControllerBuilder::create) + .build()) + .option(Option.<Color>createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientEnd")) + .binding(defaults.uiAndVisuals.compactDamage.critDamageGradientEnd, + () -> config.uiAndVisuals.compactDamage.critDamageGradientEnd, + newValue -> config.uiAndVisuals.compactDamage.critDamageGradientEnd = newValue) + .controller(ColorControllerBuilder::create) + .build()) + .build() + ) + .build(); } } diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 03d300f4..e016988b 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -4,6 +4,7 @@ import de.hysky.skyblocker.utils.waypoint.Waypoint; import dev.isxander.yacl3.config.v2.api.SerialEntry; import net.minecraft.util.Formatting; +import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -59,6 +60,9 @@ public class UIAndVisualsConfig { @SerialEntry public FlameOverlay flameOverlay = new FlameOverlay(); + @SerialEntry + public CompactDamage compactDamage = new CompactDamage(); + public static class ChestValue { @SerialEntry public boolean enableChestValue = true; @@ -258,4 +262,20 @@ public class UIAndVisualsConfig { public int flameOpacity = 100; } + public static class CompactDamage { + @SerialEntry + public boolean enabled = true; + + @SerialEntry + public int precision = 1; + + @SerialEntry + public Color normalDamageColor = new Color(0xFFFFFF); + + @SerialEntry + public Color critDamageGradientStart = new Color(0xFFFF55); + + @SerialEntry + public Color critDamageGradientEnd = new Color(0xFF5555); + } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java index 0a5ebc64..2c2c1376 100644 --- a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java @@ -3,6 +3,8 @@ package de.hysky.skyblocker.mixins; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.llamalad7.mixinextras.sugar.Local; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.CompactDamage; import de.hysky.skyblocker.skyblock.FishingHelper; import de.hysky.skyblocker.skyblock.dungeon.DungeonScore; import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager; @@ -18,12 +20,11 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityStatuses; import net.minecraft.entity.ItemEntity; -import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket; -import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket; -import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; -import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; +import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.network.packet.s2c.play.*; import net.minecraft.util.Identifier; import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -36,6 +37,10 @@ public abstract class ClientPlayNetworkHandlerMixin { @Shadow private ClientWorld world; + @Shadow + @Final + private static Logger LOGGER; + @Inject(method = "onBlockUpdate", at = @At("RETURN")) private void skyblocker$onBlockUpdate(BlockUpdateS2CPacket packet, CallbackInfo ci) { if (Utils.isInTheEnd() && SlayerUtils.isInSlayer()) { @@ -103,4 +108,14 @@ public abstract class ClientPlayNetworkHandlerMixin { } return entity; } + + @Inject(method = "onEntityTrackerUpdate", at = @At("TAIL")) + private void skyblocker$onEntityTrackerUpdate(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci, @Local Entity entity) { + if (!SkyblockerConfigManager.get().uiAndVisuals.compactDamage.enabled || !(entity instanceof ArmorStandEntity armorStandEntity)) return; + try { //Prevent packet handling fails if something goes wrong so that entity trackers still update, just without compact damage numbers + CompactDamage.compactDamage(armorStandEntity); + } catch (Exception e) { + LOGGER.error("[Skyblocker Compact Damage] Failed to compact damage number", e); + } + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java new file mode 100644 index 00000000..cff4997b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/CompactDamage.java @@ -0,0 +1,86 @@ +package de.hysky.skyblocker.skyblock; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.CustomArmorAnimatedDyes; +import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; +import org.apache.commons.lang3.math.NumberUtils; + +import java.util.List; +import java.util.regex.Pattern; + + +public class CompactDamage { + private static final Pattern DAMAGE_PATTERN = Pattern.compile("(?:✧|✯)?[\\d,]+(?:✧|✯?)❤?"); + private CompactDamage() { + } + + public static void compactDamage(ArmorStandEntity entity) { + if (!entity.isInvisible() || !entity.hasCustomName() || !entity.isCustomNameVisible()) return; + Text customName = entity.getCustomName(); + String customNameStringified = customName.getString(); + if (!DAMAGE_PATTERN.matcher(customNameStringified).matches()) return; + List<Text> siblings = customName.getSiblings(); + if (siblings.isEmpty()) return; + + MutableText prettierCustomName; + if (siblings.size() == 1) { //Non-crit damage + Text text = siblings.getFirst(); + String dmg = text.getString().replace(",", ""); + if (!NumberUtils.isParsable(dmg)) return; //Sanity check + String prettifiedDmg = prettifyDamageNumber(Long.parseLong(dmg)); + int color; + if (text.getStyle().getColor() != null) { + if (text.getStyle().getColor() == TextColor.fromFormatting(Formatting.GRAY)) { + color = SkyblockerConfigManager.get().uiAndVisuals.compactDamage.normalDamageColor.getRGB() & 0x00FFFFFF; + } else color = text.getStyle().getColor().getRgb(); + } else color = SkyblockerConfigManager.get().uiAndVisuals.compactDamage.normalDamageColor.getRGB() & 0x00FFFFFF; + prettierCustomName = Text.literal("").append(Text.literal(prettifiedDmg).setStyle(customName.getStyle()).withColor(color)); + } else { //Crit damage + boolean wasDoubled = customNameStringified.contains("❤"); //Ring of love ability adds a heart to the end of the damage string + int entriesToRemove = wasDoubled ? 2 : 1; + + String dmg = siblings.subList(1, siblings.size() - entriesToRemove) //First and last sibling are the crit symbols and maybe heart + .stream() + .map(Text::getString) + .reduce("", String::concat) //Concatenate all the siblings to get the dmg number + .replace(",", ""); + + if (!NumberUtils.isParsable(dmg)) return; //Sanity check + String dmgSymbol = customNameStringified.charAt(0) != '✯' ? "✧" : "✯"; //Mega Crit ability from the Overload enchantment + String prettifiedDmg = dmgSymbol + prettifyDamageNumber(Long.parseLong(dmg)) + dmgSymbol; + prettierCustomName = Text.literal(""); + int length = prettifiedDmg.length(); + for (int i = 0; i < length; i++) { + prettierCustomName.append(Text.literal(prettifiedDmg.substring(i, i + 1)).withColor( + CustomArmorAnimatedDyes.interpolate( + SkyblockerConfigManager.get().uiAndVisuals.compactDamage.critDamageGradientStart.getRGB() & 0x00FFFFFF, + SkyblockerConfigManager.get().uiAndVisuals.compactDamage.critDamageGradientEnd.getRGB() & 0x00FFFFFF, + i / (length - 1.0) + ) + )); + } + + if (wasDoubled) prettierCustomName.append(Text.literal("❤").formatted(Formatting.LIGHT_PURPLE)); + + prettierCustomName.setStyle(customName.getStyle()); + } + + entity.setCustomName(prettierCustomName); + } + + private static String prettifyDamageNumber(long damage) { + if (damage < 1_000) return String.valueOf(damage); + if (damage < 1_000_000) return format(damage / 1_000.0) + "k"; + if (damage < 1_000_000_000) return format(damage / 1_000_000.0) + "M"; + if (damage < 1_000_000_000_000L) return format(damage / 1_000_000_000.0) + "B"; + return format(damage / 1_000_000_000_000.0) + "T"; //This will probably never be reached + } + + private static String format(double number) { + return ("%." + SkyblockerConfigManager.get().uiAndVisuals.compactDamage.precision + "f").formatted(number); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java index 4440cd84..76e7f02c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java @@ -109,7 +109,7 @@ public class CustomArmorAnimatedDyes { } //Credit to https://codepen.io/OliverBalfour/post/programmatically-making-gradients - private static int interpolate(int firstColor, int secondColor, double percentage) { + public static int interpolate(int firstColor, int secondColor, double percentage) { int r1 = MathHelper.square((firstColor >> 16) & 0xFF); int g1 = MathHelper.square((firstColor >> 8) & 0xFF); int b1 = MathHelper.square(firstColor & 0xFF); |