aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/mixins
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-04-26 20:00:18 -0400
committerAaron <51387595+AzureAaron@users.noreply.github.com>2024-04-26 20:00:18 -0400
commitd24bac4d728d8ea9264e08934fb863771bcca5e2 (patch)
tree3157ed007409e99d70605157d47e9b0193a4d28a /src/main/java/de/hysky/skyblocker/mixins
parent74f40f7704cd935552a27d9ebc2ae6a3c76e3566 (diff)
downloadSkyblocker-d24bac4d728d8ea9264e08934fb863771bcca5e2.tar.gz
Skyblocker-d24bac4d728d8ea9264e08934fb863771bcca5e2.tar.bz2
Skyblocker-d24bac4d728d8ea9264e08934fb863771bcca5e2.zip
Pluralize the mixin and accessor packages
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/mixins')
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/AbstractInventoryScreenMixin.java19
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/BatEntityMixin.java21
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java106
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ClientPlayerEntityMixin.java82
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/CommandTreeS2CPacketMixin.java21
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ComponentHolderMixin.java39
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/DataTrackerMixin.java51
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/DrawContextMixin.java71
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/DyedColorComponentMixin.java34
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/FarmlandBlockMixin.java37
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/GenericContainerScreenHandlerMixin.java38
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java258
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/HandledScreenProviderMixin.java101
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/InGameHudMixin.java144
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/InGameOverlayRendererMixin.java22
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/InventoryScreenMixin.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java98
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/LeverBlockMixin.java29
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/LivingEntityRendererMixin.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/MinecraftClientMixin.java60
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/MouseMixin.java19
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/PlayerInventoryMixin.java21
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/PlayerListHudMixin.java57
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/PlayerSkinProviderMixin.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/PlayerSkinTextureMixin.java40
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/RenderFishMixin.java26
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/ScoreboardMixin.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/SocialInteractionsPlayerListWidgetMixin.java24
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/WindowMixin.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/WorldRendererMixin.java48
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/YggdrasilMinecraftSessionServiceMixin.java20
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/YggdrasilServicesKeyInfoMixin.java60
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/BeaconBlockEntityRendererInvoker.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/DrawContextInvoker.java21
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/EndermanEntityAccessor.java17
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/FrustumInvoker.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/HandledScreenAccessor.java26
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/MessageHandlerAccessor.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/PlayerListHudAccessor.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/RecipeBookWidgetAccessor.java15
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/ScreenAccessor.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/SkullBlockEntityAccessor.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/SlotAccessor.java17
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/accessors/WorldRendererAccessor.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/mixins/discordipc/ConnectionMixin.java20
46 files changed, 1871 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/mixins/AbstractInventoryScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixins/AbstractInventoryScreenMixin.java
new file mode 100644
index 00000000..53151826
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/AbstractInventoryScreenMixin.java
@@ -0,0 +1,19 @@
+package de.hysky.skyblocker.mixins;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen;
+
+@Mixin(AbstractInventoryScreen.class)
+public class AbstractInventoryScreenMixin {
+
+ @Inject(method = "drawStatusEffects", at = @At("HEAD"), cancellable = true)
+ private void skyblocker$dontDrawStatusEffects(CallbackInfo ci) {
+ if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.hideStatusEffectOverlay) ci.cancel();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/BatEntityMixin.java b/src/main/java/de/hysky/skyblocker/mixins/BatEntityMixin.java
new file mode 100644
index 00000000..7ee59be1
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/BatEntityMixin.java
@@ -0,0 +1,21 @@
+package de.hysky.skyblocker.mixins;
+
+import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager;
+import net.minecraft.entity.EntityType;
+import net.minecraft.entity.mob.AmbientEntity;
+import net.minecraft.entity.passive.BatEntity;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+
+@Mixin(BatEntity.class)
+public abstract class BatEntityMixin extends AmbientEntity {
+ protected BatEntityMixin(EntityType<? extends AmbientEntity> entityType, World world) {
+ super(entityType, world);
+ }
+
+ @Override
+ public void onRemoved() {
+ super.onRemoved();
+ DungeonManager.onBatRemoved(this);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java
new file mode 100644
index 00000000..0a5ebc64
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayNetworkHandlerMixin.java
@@ -0,0 +1,106 @@
+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.skyblock.FishingHelper;
+import de.hysky.skyblocker.skyblock.dungeon.DungeonScore;
+import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager;
+import de.hysky.skyblocker.skyblock.end.BeaconHighlighter;
+import de.hysky.skyblocker.skyblock.end.EnderNodes;
+import de.hysky.skyblocker.skyblock.end.TheEnd;
+import de.hysky.skyblocker.skyblock.waypoint.MythologicalRitual;
+import de.hysky.skyblocker.utils.SlayerUtils;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.block.Blocks;
+import net.minecraft.client.network.ClientPlayNetworkHandler;
+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.util.Identifier;
+import org.slf4j.Logger;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+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(ClientPlayNetworkHandler.class)
+public abstract class ClientPlayNetworkHandlerMixin {
+ @Shadow
+ private ClientWorld world;
+
+ @Inject(method = "onBlockUpdate", at = @At("RETURN"))
+ private void skyblocker$onBlockUpdate(BlockUpdateS2CPacket packet, CallbackInfo ci) {
+ if (Utils.isInTheEnd() && SlayerUtils.isInSlayer()) {
+ BeaconHighlighter.beaconPositions.remove(packet.getPos());
+ if (packet.getState().isOf(Blocks.BEACON)) {
+ BeaconHighlighter.beaconPositions.add(packet.getPos());
+ }
+ }
+ }
+
+ @Inject(method = "method_37472", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V"))
+ private void skyblocker$onItemDestroy(int entityId, CallbackInfo ci) {
+ if (world.getEntityById(entityId) instanceof ItemEntity itemEntity) {
+ DungeonManager.onItemPickup(itemEntity);
+ }
+ }
+
+ @ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V", ordinal = 0))
+ private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity) {
+ DungeonManager.onItemPickup(itemEntity);
+ return itemEntity;
+ }
+
+ @WrapWithCondition(method = "onEntityPassengersSet", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;)V", remap = false))
+ private boolean skyblocker$cancelEntityPassengersWarning(Logger instance, String msg) {
+ return !Utils.isOnHypixel();
+ }
+
+ @WrapWithCondition(method = "onPlayerList", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
+ private boolean skyblocker$cancelPlayerListWarning(Logger instance, String format, Object arg1, Object arg2) {
+ return !Utils.isOnHypixel();
+ }
+
+ @Inject(method = "onPlaySound", at = @At("RETURN"))
+ private void skyblocker$onPlaySound(PlaySoundS2CPacket packet, CallbackInfo ci) {
+ FishingHelper.onSound(packet);
+ }
+
+ @WrapWithCondition(method = "warnOnUnknownPayload", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false))
+ private boolean skyblocker$dropBadlionPacketWarnings(Logger instance, String message, Object identifier) {
+ return !(Utils.isOnHypixel() && ((Identifier) identifier).getNamespace().equals("badlion"));
+ }
+
+ @WrapWithCondition(method = { "onScoreboardScoreUpdate", "onScoreboardScoreReset" }, at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false))
+ private boolean skyblocker$cancelUnknownScoreboardObjectiveWarnings(Logger instance, String message, Object objectiveName) {
+ return !Utils.isOnHypixel();
+ }
+
+ @WrapWithCondition(method = "onTeam", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;[Ljava/lang/Object;)V", remap = false))
+ private boolean skyblocker$cancelTeamWarning(Logger instance, String format, Object... arg) {
+ return !Utils.isOnHypixel();
+ }
+
+ @Inject(method = "onParticle", at = @At("RETURN"))
+ private void skyblocker$onParticle(ParticleS2CPacket packet, CallbackInfo ci) {
+ MythologicalRitual.onParticle(packet);
+ EnderNodes.onParticle(packet);
+ }
+
+ @ModifyExpressionValue(method = "onEntityStatus", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/EntityStatusS2CPacket;getEntity(Lnet/minecraft/world/World;)Lnet/minecraft/entity/Entity;"))
+ private Entity skyblocker$onEntityDeath(Entity entity, @Local(argsOnly = true) EntityStatusS2CPacket packet) {
+ if (packet.getStatus() == EntityStatuses.PLAY_DEATH_SOUND_OR_ADD_PROJECTILE_HIT_PARTICLES) {
+ DungeonScore.handleEntityDeath(entity);
+ TheEnd.onEntityDeath(entity);
+ }
+ return entity;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/ClientPlayerEntityMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayerEntityMixin.java
new file mode 100644
index 00000000..d4c930d2
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/ClientPlayerEntityMixin.java
@@ -0,0 +1,82 @@
+package de.hysky.skyblocker.mixins;
+
+import com.mojang.authlib.GameProfile;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.auction.AuctionViewScreen;
+import de.hysky.skyblocker.skyblock.auction.EditBidPopup;
+import de.hysky.skyblocker.skyblock.dungeon.partyfinder.PartyFinderScreen;
+import de.hysky.skyblocker.skyblock.item.HotbarSlotLock;
+import de.hysky.skyblocker.skyblock.item.ItemProtection;
+import de.hysky.skyblocker.skyblock.rift.HealingMelonIndicator;
+import de.hysky.skyblocker.skyblock.searchoverlay.OverlayScreen;
+import de.hysky.skyblocker.skyblock.searchoverlay.SearchOverManager;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.block.entity.SignBlockEntity;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.AbstractClientPlayerEntity;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.world.ClientWorld;
+import net.minecraft.text.Text;
+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;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(ClientPlayerEntity.class)
+public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity {
+ @Shadow
+ @Final
+ protected MinecraftClient client;
+
+ public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {
+ super(world, profile);
+ }
+
+ @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
+ public void skyblocker$dropSelectedItem(CallbackInfoReturnable<Boolean> cir) {
+ if (Utils.isOnSkyblock() && (ItemProtection.isItemProtected(this.getInventory().getMainHandStack()) || HotbarSlotLock.isLocked(this.getInventory().selectedSlot))
+ && (!SkyblockerConfigManager.get().locations.dungeons.allowDroppingProtectedItems || !Utils.isInDungeons())) {
+ cir.setReturnValue(false);
+ }
+ }
+
+ @Inject(method = "updateHealth", at = @At("RETURN"))
+ public void skyblocker$updateHealth(CallbackInfo ci) {
+ HealingMelonIndicator.updateHealth();
+ }
+
+ @Inject(method = "openEditSignScreen", at = @At("HEAD"), cancellable = true)
+ public void skyblocker$redirectEditSignScreen(SignBlockEntity sign, boolean front, CallbackInfo callbackInfo) {
+ // Fancy Party Finder
+ if (!PartyFinderScreen.isInKuudraPartyFinder && client.currentScreen instanceof PartyFinderScreen partyFinderScreen && !partyFinderScreen.isAborted() && sign.getText(front).getMessage(3, false).getString().toLowerCase().contains("level")) {
+ partyFinderScreen.updateSign(sign, front);
+ callbackInfo.cancel();
+ return;
+ }
+
+ if (client.currentScreen instanceof AuctionViewScreen auctionViewScreen) {
+ this.client.setScreen(new EditBidPopup(auctionViewScreen, sign, front, auctionViewScreen.minBid));
+ callbackInfo.cancel();
+ }
+
+ // Search Overlay
+ if (client.currentScreen != null) {
+ if (SkyblockerConfigManager.get().general.searchOverlay.enableAuctionHouse && client.currentScreen.getTitle().getString().toLowerCase().contains("auction")) {
+ if (sign.getText(front).getMessage(3, false).getString().equalsIgnoreCase("enter query")) {
+ SearchOverManager.updateSign(sign, front, true);
+ client.setScreen(new OverlayScreen(Text.of("")));
+ callbackInfo.cancel();
+ }
+ } else if (SkyblockerConfigManager.get().general.searchOverlay.enableBazaar && client.currentScreen.getTitle().getString().toLowerCase().contains("bazaar")) {
+ if (sign.getText(front).getMessage(3, false).getString().equalsIgnoreCase("enter query")) {
+ SearchOverManager.updateSign(sign, front, false);
+ client.setScreen(new OverlayScreen(Text.of("")));
+ callbackInfo.cancel();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/hysky/skyblocker/mixins/CommandTreeS2CPacketMixin.java b/src/main/java/de/hysky/skyblocker/mixins/CommandTreeS2CPacketMixin.java
new file mode 100644
index 00000000..289923c8
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/CommandTreeS2CPacketMixin.java
@@ -0,0 +1,21 @@
+package de.hysky.skyblocker.mixins;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.mojang.brigadier.tree.CommandNode;
+import com.mojang.brigadier.tree.LiteralCommandNode;
+import de.hysky.skyblocker.skyblock.WarpAutocomplete;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.command.CommandSource;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(targets = "net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket$CommandTree")
+public class CommandTreeS2CPacketMixin {
+ @ModifyExpressionValue(method = "getNode", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/play/CommandTreeS2CPacket$CommandTree;getNode(I)Lcom/mojang/brigadier/tree/CommandNode;", ordinal = 1))
+ public CommandNode<? extends CommandSource> modifyCommandSuggestions(CommandNode<CommandSource> original) {
+ if (Utils.isOnHypixel() && WarpAutocomplete.commandNode != null && original instanceof LiteralCommandNode<?> literalCommandNode && literalCommandNode.getLiteral().equals("warp")) {
+ return WarpAutocomplete.commandNode;
+ }
+ return original;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/ComponentHolderMixin.java b/src/main/java/de/hysky/skyblocker/mixins/ComponentHolderMixin.java
new file mode 100644
index 00000000..8fa03cdc
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/ComponentHolderMixin.java
@@ -0,0 +1,39 @@
+package de.hysky.skyblocker.mixins;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.CustomArmorTrims;
+import de.hysky.skyblocker.utils.ItemUtils;
+import de.hysky.skyblocker.utils.Utils;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import net.minecraft.component.ComponentHolder;
+import net.minecraft.component.DataComponentType;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.trim.ArmorTrim;
+
+@Mixin(ComponentHolder.class)
+public interface ComponentHolderMixin {
+
+ @SuppressWarnings("unchecked")
+ @ModifyReturnValue(method = "get", at = @At("RETURN"))
+ private <T> T skyblocker$customArmorTrims(T original, DataComponentType<? extends T> dataComponentType) {
+ if (Utils.isOnSkyblock() && ((Object) this) instanceof ItemStack stack) {
+ if (dataComponentType == DataComponentTypes.TRIM) {
+ Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customTrims = SkyblockerConfigManager.get().general.customArmorTrims;
+ String itemUuid = ItemUtils.getItemUuid(stack);
+
+ if (customTrims.containsKey(itemUuid)) {
+ CustomArmorTrims.ArmorTrimId trimKey = customTrims.get(itemUuid);
+ return (T) CustomArmorTrims.TRIMS_CACHE.getOrDefault(trimKey, (ArmorTrim) original);
+ }
+ }
+ }
+
+ return original;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/DataTrackerMixin.java b/src/main/java/de/hysky/skyblocker/mixins/DataTrackerMixin.java
new file mode 100644
index 00000000..dfe6ac4c
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/DataTrackerMixin.java
@@ -0,0 +1,51 @@
+package de.hysky.skyblocker.mixins;
+
+import com.llamalad7.mixinextras.sugar.Local;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.mixins.accessors.EndermanEntityAccessor;
+import de.hysky.skyblocker.skyblock.entity.MobGlow;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.Blocks;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.data.DataTracked;
+import net.minecraft.entity.data.DataTracker;
+import net.minecraft.sound.SoundEvents;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
+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;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.util.Optional;
+
+@Mixin(DataTracker.class)
+public abstract class DataTrackerMixin {
+ @Shadow
+ @Final
+ private DataTracked trackedEntity;
+
+ @SuppressWarnings("ConstantValue")
+ @Inject(method = "writeUpdatedEntries", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/data/DataTracker;copyToFrom(Lnet/minecraft/entity/data/DataTracker$Entry;Lnet/minecraft/entity/data/DataTracker$SerializedEntry;)V"))
+ private <T> void skyblocker$onWriteUpdatedEntries(CallbackInfo ci, @Local DataTracker.Entry<T> entry, @Local DataTracker.SerializedEntry<T> serializedEntry) {
+ if (Utils.isInTheEnd() && SkyblockerConfigManager.get().slayer.endermanSlayer.enableYangGlyphsNotification && entry.getData() == EndermanEntityAccessor.getCARRIED_BLOCK() && entry.get() instanceof Optional<?> value && value.isPresent() && value.get() instanceof BlockState state && state.isOf(Blocks.BEACON) && ((Optional<?>) serializedEntry.value()).isEmpty()) {
+ MinecraftClient client = MinecraftClient.getInstance();
+ if (trackedEntity instanceof Entity entity && MobGlow.getArmorStands(entity).stream().anyMatch(armorStand -> armorStand.getName().getString().contains(client.getSession().getUsername()))) {
+ client.inGameHud.setTitleTicks(5, 20, 10);
+ client.inGameHud.setTitle(Text.literal("Yang Glyph!").formatted(Formatting.RED));
+ client.player.playSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 100f, 0.1f);
+ }
+ }
+ }
+
+ @SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference"})
+ @Inject(method = "copyToFrom", at = @At(value = "NEW", target = "Ljava/lang/IllegalStateException;"), cancellable = true)
+ public void skyblocker$ignoreInvalidDataExceptions(CallbackInfo ci) {
+ //These exceptions cause annoying small lag spikes for some reason
+ if (Utils.isOnHypixel()) ci.cancel();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixins/DrawContextMixin.java b/src/main/java/de/hysky/skyblocker/mixins/DrawContextMixin.java
new file mode 100644
index 00000000..7964b114
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/mixins/DrawContextMixin.java
@@ -0,0 +1,71 @@
+package de.hysky.skyblocker.mixins;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import com.llamalad7.mixinextras.sugar.ref.LocalRef;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.item.AttributeShards;
+import de.hysky.skyblocker.skyblock.item.ItemCooldowns;
+import de.hysky.skyblocker.utils.ItemUtils;
+import de.hysky.skyblocker.utils.Utils;
+import net.minecraft.client.font.TextRenderer;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NbtCompound;
+import net.minecraft.util.Formatting;
+import org.jetbrains.annotations.Nullable;
+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;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(DrawContext.class)
+public abstract class DrawContextMixin {
+ @Shadow
+ @Final
+ private MatrixStack matrices;
+
+ @Shadow
+ public abstract int drawText(TextRenderer textRenderer, @Nullable String text, int x, int y, int color, boolean shadow);
+
+ @Inject(method = "drawItemInSlot(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V", at = @At("HEAD"))
+ private void skyblocker$renderAttributeShardDisplay(CallbackInfo ci, @Local(argsOnly = true) TextRenderer textRenderer, @Local(argsOnly = true) ItemStack stack, @Local(argsOnly = true, ordinal = 0) int x, @Local(argsOnly = true, ordinal = 1) int y, @Local(argsOnly = true) LocalRef<String> countOverride) {
+ if (!SkyblockerConfigManager.get().general.itemInfoDisplay.attributeShardInfo) return;
+
+ if (Utils.isOnSkyblock()) {
+ NbtCompound customData = ItemUtils.getCustomData(stack);
+
+ if (ItemUtils.getItemId(stack).equals("ATTRIBUTE_SHARD")) {
+ NbtCompound attributesTag = customData.getCompound("attributes");
+ String[] attributes = attributesTag.getKeys().toArray(String[]::new);
+
+ if (attributes.length != 0) {
+ String attributeId = attributes[0];
+ int attributeLevel = attributesTag.getInt(attributeId);
+
+ //Set item count
+ countOverride.set(Integer.toString(attributeLevel));
+
+ //Draw the attribute name
+ this.matrices.push();
+ this.matrices.translate(0f, 0f, 200f);
+
+ String attributeInitials = AttributeShards.getShortName(attributeId);
+
+ this.drawText(textRenderer, attributeInitials, x, y, Formatting.AQUA.getColorValue(), true);
+
+ this.matrices.pop();
+ }
+ }
+ }
+ }
+
+ @ModifyExpressionValue(method = "drawItemInSlot(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/ItemCooldownManager;getCooldownProgress(Lnet/minecraft/item/Item;F)F"))
+ private float skyblocker$modifyItemCooldown(float cooldownProgress, @Local(argsOnly = true) ItemStack stack) {
+ return Utils.isOnSkyblock() && ItemCooldowns.isOnCooldown(stack) ? ItemCooldowns.getItemCooldownEntry(s