diff options
author | Yasin <a.piri@hotmail.de> | 2023-10-09 12:58:02 +0200 |
---|---|---|
committer | Yasin <a.piri@hotmail.de> | 2023-10-09 12:58:02 +0200 |
commit | bd3f0329d0e391bd84b5f9e3ff207d9dd9815853 (patch) | |
tree | 2fd1d1ef625f57acc2e4916c967d8d2393844798 /src/main/java/de/hysky/skyblocker/mixin | |
parent | 2315b90da8117f28f66348927afdb621ee4fc815 (diff) | |
download | Skyblocker-bd3f0329d0e391bd84b5f9e3ff207d9dd9815853.tar.gz Skyblocker-bd3f0329d0e391bd84b5f9e3ff207d9dd9815853.tar.bz2 Skyblocker-bd3f0329d0e391bd84b5f9e3ff207d9dd9815853.zip |
new pr because fixing merge conflict would take too long
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/mixin')
32 files changed, 1159 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/mixin/AbstractInventoryScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/AbstractInventoryScreenMixin.java new file mode 100644 index 00000000..d0d4b9f7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/AbstractInventoryScreenMixin.java @@ -0,0 +1,19 @@ +package de.hysky.skyblocker.mixin; + +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/mixin/ArmorTrimMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java new file mode 100644 index 00000000..02d75409 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ArmorTrimMixin.java @@ -0,0 +1,37 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.CustomArmorTrims; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.item.ItemStack; +import net.minecraft.item.trim.ArmorTrim; +import net.minecraft.nbt.NbtCompound; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Optional; + +@Mixin(ArmorTrim.class) +public class ArmorTrimMixin { + + @ModifyReturnValue(method = "getTrim", at = @At("RETURN")) + private static Optional<ArmorTrim> skyblocker$customArmorTrims(@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional<ArmorTrim> original, @Local ItemStack stack) { + NbtCompound nbt = stack.getNbt(); + + if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { + Object2ObjectOpenHashMap<String, CustomArmorTrims.ArmorTrimId> customTrims = SkyblockerConfigManager.get().general.customArmorTrims; + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null; + + if (customTrims.containsKey(itemUuid)) { + CustomArmorTrims.ArmorTrimId trimKey = customTrims.get(itemUuid); + return CustomArmorTrims.TRIMS_CACHE.getOrDefault(trimKey, original); + } + } + + return original; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/BatEntityMixin.java b/src/main/java/de/hysky/skyblocker/mixin/BatEntityMixin.java new file mode 100644 index 00000000..dc2fa673 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/BatEntityMixin.java @@ -0,0 +1,21 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonSecrets; +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(); + DungeonSecrets.onBatRemoved(this); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 00000000..fff534b2 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,48 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.WrapWithCondition; +import com.llamalad7.mixinextras.sugar.Local; +import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonSecrets; +import dev.cbyrne.betterinject.annotations.Inject; +import de.hysky.skyblocker.skyblock.FishingHelper; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class ClientPlayNetworkHandlerMixin { + + @Inject(method = "onPlaySound", at = @At("RETURN")) + private void skyblocker$onPlaySound(PlaySoundS2CPacket packet) { + FishingHelper.onSound(packet); + } + + @SuppressWarnings("resource") + @ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "STORE", ordinal = 0)) + private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity, @Local LivingEntity collector) { + DungeonSecrets.onItemPickup(itemEntity, collector, collector == MinecraftClient.getInstance().player); + 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;)V", remap = false)) + private boolean skyblocker$cancelPlayerListWarning(Logger instance, String format, Object arg) { + 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(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java new file mode 100644 index 00000000..37ae92e8 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java @@ -0,0 +1,35 @@ +package de.hysky.skyblocker.mixin; + +import com.mojang.authlib.GameProfile; + +import dev.cbyrne.betterinject.annotations.Inject; +import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.ItemProtection; +import de.hysky.skyblocker.skyblock.rift.HealingMelonIndicator; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerEntity.class) +public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { + 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()) { + if (ItemProtection.isItemProtected(this.getInventory().getMainHandStack())) cir.setReturnValue(false); + HotbarSlotLock.handleDropSelectedItem(this.getInventory().selectedSlot, cir); + } + } + + @Inject(method = "updateHealth", at = @At("RETURN")) + public void skyblocker$updateHealth() { + HealingMelonIndicator.updateHealth(); + } +}
\ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java new file mode 100644 index 00000000..fab9a1ea --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.events.ClientPlayerBlockBreakEvent; +import net.minecraft.block.BlockState; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +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.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ClientPlayerInteractionManager.class) +public class ClientPlayerInteractionManagerMixin { + @Shadow + @Final + private MinecraftClient client; + + @Inject(method = "breakBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;onBroken(Lnet/minecraft/world/WorldAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V"), locals = LocalCapture.CAPTURE_FAILHARD) + private void skyblocker$onBlockBroken(BlockPos pos, CallbackInfoReturnable<Boolean> cir, World world, BlockState blockState) { + ClientPlayerBlockBreakEvent.AFTER.invoker().afterBlockBreak(world, this.client.player, pos, blockState); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/DrawContextMixin.java b/src/main/java/de/hysky/skyblocker/mixin/DrawContextMixin.java new file mode 100644 index 00000000..41b8e985 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/DrawContextMixin.java @@ -0,0 +1,72 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import dev.cbyrne.betterinject.annotations.Arg; +import dev.cbyrne.betterinject.annotations.Inject; +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.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; + +@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(@Arg TextRenderer textRenderer, @Arg ItemStack stack, @Arg(ordinal = 0) int x, @Arg(ordinal = 1) int y, @Local(argsOnly = true) LocalRef<String> countOverride) { + if (!SkyblockerConfigManager.get().general.itemInfoDisplay.attributeShardInfo) return; + + NbtCompound nbt = stack.getNbt(); + + if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + + if (extraAttributes.getString("id").equals("ATTRIBUTE_SHARD")) { + NbtCompound attributesTag = extraAttributes.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 ItemStack stack) { + return Utils.isOnSkyblock() && ItemCooldowns.isOnCooldown(stack) ? ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent() : cooldownProgress; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java b/src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java new file mode 100644 index 00000000..51ab3852 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/DyeableItemMixin.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.item.DyeableItem; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(DyeableItem.class) +public interface DyeableItemMixin { + @ModifyReturnValue(method = "getColor", at = @At("RETURN")) + private int skyblocker$customDyeColor(int originalColor, ItemStack stack) { + NbtCompound nbt = stack.getNbt(); + + if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null; + + return SkyblockerConfigManager.get().general.customDyeColors.getOrDefault(itemUuid, originalColor); + } + + return originalColor; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/FarmlandBlockMixin.java b/src/main/java/de/hysky/skyblocker/mixin/FarmlandBlockMixin.java new file mode 100644 index 00000000..dfa886c4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/FarmlandBlockMixin.java @@ -0,0 +1,38 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.FarmlandBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +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; + +@Mixin(FarmlandBlock.class) +public abstract class FarmlandBlockMixin extends Block { + @Shadow + @Final + protected static VoxelShape SHAPE; + + protected FarmlandBlockMixin(Settings settings) { + super(settings); + } + + @ModifyReturnValue(method = "getOutlineShape", at = @At("RETURN")) + private VoxelShape skyblocker$replaceOutlineShape(VoxelShape original) { + return Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.hitbox.oldFarmlandHitbox ? VoxelShapes.fullCube() : original; + } + + @SuppressWarnings("deprecation") + @Override + public VoxelShape getCullingShape(BlockState state, BlockView world, BlockPos pos) { + return SHAPE; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/GenericContainerScreenHandlerMixin.java b/src/main/java/de/hysky/skyblocker/mixin/GenericContainerScreenHandlerMixin.java new file mode 100644 index 00000000..9929c5d4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/GenericContainerScreenHandlerMixin.java @@ -0,0 +1,30 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.SkyblockerMod; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.ScreenHandlerType; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.List; + +@Mixin(GenericContainerScreenHandler.class) +public abstract class GenericContainerScreenHandlerMixin extends ScreenHandler { + protected GenericContainerScreenHandlerMixin(@Nullable ScreenHandlerType<?> type, int syncId) { + super(type, syncId); + } + + @Override + public void setStackInSlot(int slot, int revision, ItemStack stack) { + SkyblockerMod.getInstance().containerSolverManager.markDirty(); + super.setStackInSlot(slot, revision, stack); + } + + @Override + public void updateSlotStacks(int revision, List<ItemStack> stacks, ItemStack cursorStack) { + SkyblockerMod.getInstance().containerSolverManager.markDirty(); + super.updateSlotStacks(revision, stacks, cursorStack); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java new file mode 100644 index 00000000..689974c8 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/HandledScreenMixin.java @@ -0,0 +1,193 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.experiment.ChronomatronSolver; +import de.hysky.skyblocker.skyblock.experiment.ExperimentSolver; +import de.hysky.skyblocker.skyblock.experiment.SuperpairsSolver; +import de.hysky.skyblocker.skyblock.experiment.UltrasequencerSolver; +import de.hysky.skyblocker.skyblock.item.BackpackPreview; +import de.hysky.skyblocker.skyblock.item.CompactorDeletorPreview; +import de.hysky.skyblocker.skyblock.item.ItemProtection; +import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.skyblock.item.WikiLookup; +import de.hysky.skyblocker.skyblock.itemlist.ItemRegistry; +import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.gui.ContainerSolver; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.item.TooltipContext; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Text; +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.Unique; +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.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Map; +import java.util.regex.Matcher; + +@Mixin(HandledScreen.class) +public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen { + /** + * This is the slot id returned for when a click is outside of the screen's bounds + */ + @Unique + private static final int OUT_OF_BOUNDS_SLOT = -999; + + @Shadow + @Nullable + protected Slot focusedSlot; + + @Shadow + @Final + protected T handler; + + protected HandledScreenMixin(Text title) { + super(title); + } + + @Inject(at = @At("HEAD"), method = "keyPressed") + public void skyblocker$keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) { + if (this.client != null && this.focusedSlot != null && keyCode != 256 && !this.client.options.inventoryKey.matchesKey(keyCode, scanCode) && WikiLookup.wikiLookup.matchesKey(keyCode, scanCode)) { + WikiLookup.openWiki(this.focusedSlot); + } + } + + @SuppressWarnings("DataFlowIssue") + // makes intellij be quiet about this.focusedSlot maybe being null. It's already null checked in mixined method. + @Inject(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V"), cancellable = true) + public void skyblocker$drawMouseOverTooltip(DrawContext context, int x, int y, CallbackInfo ci) { + if (!Utils.isOnSkyblock()) return; + + // Hide Empty Tooltips + if (SkyblockerConfigManager.get().general.hideEmptyTooltips && focusedSlot.getStack().getName().getString().equals(" ")) { + ci.cancel(); + } + + // Backpack Preview + boolean shiftDown = SkyblockerConfigManager.get().general.backpackPreviewWithoutShift ^ Screen.hasShiftDown(); + if (shiftDown && getTitle().getString().equals("Storage") && focusedSlot.inventory != client.player.getInventory() && BackpackPreview.renderPreview(context, focusedSlot.getIndex(), x, y)) { + ci.cancel(); + } + + // Compactor Preview + if (SkyblockerConfigManager.get().general.compactorDeletorPreview) { + ItemStack stack = focusedSlot.getStack(); + Matcher matcher = CompactorDeletorPreview.NAME.matcher(ItemRegistry.getInternalName(stack)); + if (matcher.matches() && CompactorDeletorPreview.drawPreview(context, stack, matcher.group("type"), matcher.group("size"), x, y)) { + ci.cancel(); + } + } + } + + @Redirect(method = "drawMouseoverTooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;getStack()Lnet/minecraft/item/ItemStack;", ordinal = 0)) + private ItemStack skyblocker$experimentSolvers$replaceTooltipDisplayStack(Slot slot) { + return skyblocker$experimentSolvers$getStack(slot, null); + } + + @ModifyVariable(method = "drawSlot", at = @At(value = "LOAD", ordinal = 4), ordinal = 0) + private ItemStack skyblocker$experimentSolvers$replaceDisplayStack(ItemStack stack, DrawContext context, Slot slot) { + return skyblocker$experimentSolvers$getStack(slot, stack); + } + + + @Unique + private ItemStack skyblocker$experimentSolvers$getStack(Slot slot, ItemStack stack) { + ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); + if ((currentSolver instanceof SuperpairsSolver || currentSolver instanceof UltrasequencerSolver) && ((ExperimentSolver) currentSolver).getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) { + ItemStack itemStack = ((ExperimentSolver) currentSolver).getSlots().get(slot.getIndex()); + return itemStack == null ? slot.getStack() : itemStack; + } + return (stack != null) ? stack : slot.getStack(); + } + + @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;clickSlot(IIILnet/minecraft/screen/slot/SlotActionType;Lnet/minecraft/entity/player/PlayerEntity;)V")) + private void skyblocker$experimentSolvers$onSlotClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { + if (slot != null) { + ContainerSolver currentSolver = SkyblockerMod.getInstance().containerSolverManager.getCurrentSolver(); + if (currentSolver instanceof ExperimentSolver experimentSolver && experimentSolver.getState() == ExperimentSolver.State.SHOW && slot.inventory instanceof SimpleInventory) { + if (experimentSolver instanceof ChronomatronSolver chronomatronSolver) { + Item item = chronomatronSolver.getChronomatronSlots().get(chronomatronSolver.getChronomatronCurrentOrdinal()); + if ((slot.getStack().isOf(item) || ChronomatronSolver.TERRACOTTA_TO_GLASS.get(slot.getStack().getItem()) == item) && chronomatronSolver.incrementChronomatronCurrentOrdinal() >= chronomatronSolver.getChronomatronSlots().size()) { + chronomatronSolver.setState(ExperimentSolver.State.END); + } + } else if (experimentSolver instanceof SuperpairsSolver superpairsSolver) { + superpairsSolver.setSuperpairsPrevClickedSlot(slot.getIndex()); + superpairsSolver.setSuperpairsCurrentSlot(ItemStack.EMPTY); + } else if (experimentSolver instanceof UltrasequencerSolver ultrasequencerSolver && slot.getIndex() == ultrasequencerSolver.getUltrasequencerNextSlot()) { + int count = ultrasequencerSolver.getSlots().get(ultrasequencerSolver.getUltrasequencerNextSlot()).getCount() + 1; + ultrasequencerSolver.getSlots().entrySet().stream().filter(entry -> entry.getValue().getCount() == count).findAny().map(Map.Entry::getKey).ifPresentOrElse(ultrasequencerSolver::setUltrasequencerNextSlot, () -> ultrasequencerSolver.setState(ExperimentSolver.State.END)); + } + } + } + } + + /** + * The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks) + * For example, using the drop key bind while hovering over an item will invoke this method to drop the players item + */ + @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) + private void skyblocker$onSlotInteract(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { + if (Utils.isOnSkyblock()) { + // When you try and drop the item by picking it up then clicking outside of the screen + if (slotId == OUT_OF_BOUNDS_SLOT) { + ItemStack cursorStack = this.handler.getCursorStack(); + + if (ItemProtection.isItemProtected(cursorStack)) ci.cancel(); + } + + if (slot != null) { + // When you click your drop key while hovering over an item + if (actionType == SlotActionType.THROW) { + ItemStack stack = slot.getStack(); + + if (ItemProtection.isItemProtected(stack)) ci.cancel(); + } + + //Prevent salvaging + if (this.getTitle().getString().equals("Salvage Items")) { + ItemStack stack = slot.getStack(); + + if (ItemProtection.isItemProtected(stack)) ci.cancel(); + } + + //Prevent selling to NPC shops + if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) { + ItemStack sellItem = this.handler.slots.get(49).getStack(); + + if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) { + ItemStack stack = slot.getStack(); + + if (ItemProtection.isItemProtected(stack)) ci.cancel(); + } + } + } + } + } + + //TODO make this a util method somewhere else, eventually + private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) { + return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString)); + } + + @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) + private void skyblocker$drawItemRarityBackground(DrawContext context, Slot slot, CallbackInfo ci) { + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(slot.getStack(), context, slot.x, slot.y); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java new file mode 100644 index 00000000..1b6d62d4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java @@ -0,0 +1,93 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.FancyStatusBars; +import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.ItemCooldowns; +import de.hysky.skyblocker.skyblock.dungeon.DungeonMap; +import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; +import de.hysky.skyblocker.utils.Utils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Environment(EnvType.CLIENT) +@Mixin(InGameHud.class) +public abstract class InGameHudMixin { + @Unique + private static final Identifier SLOT_LOCK = new Identifier(SkyblockerMod.NAMESPACE, "textures/gui/slot_lock.png"); + @Unique + private final FancyStatusBars statusBars = new FancyStatusBars(); + + @Shadow + private int scaledHeight; + @Shadow + private int scaledWidth; + + @Shadow + @Final + private MinecraftClient client; + + @Inject(method = "renderHotbar", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHotbarItem(Lnet/minecraft/client/gui/DrawContext;IIFLnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/item/ItemStack;I)V", ordinal = 0)) + public void skyblocker$renderHotbarItemLockOrRarityBg(float tickDelta, DrawContext context, CallbackInfo ci, @Local(ordinal = 4, name = "m") int index, @Local(ordinal = 5, name = "n") int x, @Local(ordinal = 6, name = "o") int y, @Local PlayerEntity player) { + if (Utils.isOnSkyblock()) { + if (SkyblockerConfigManager.get().general.itemInfoDisplay.itemRarityBackgrounds) ItemRarityBackgrounds.tryDraw(player.getInventory().main.get(index), context, x, y); + if (HotbarSlotLock.isLocked(index)) context.drawTexture(SLOT_LOCK, x, y, 0, 0, 16, 16); + } + } + + @Inject(method = "renderExperienceBar", at = @At("HEAD"), cancellable = true) + private void skyblocker$renderExperienceBar(CallbackInfo ci) { + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.bars.enableBars && !Utils.isInTheRift()) + ci.cancel(); + } + + @Inject(method = "renderStatusBars", at = @At("HEAD"), cancellable = true) + private void skyblocker$renderStatusBars(DrawContext context, CallbackInfo ci) { + if (!Utils.isOnSkyblock()) + return; + if (statusBars.render(context, scaledWidth, scaledHeight)) + ci.cancel(); + + if (Utils.isInDungeons() && SkyblockerConfigManager.get().locations.dungeons.enableMap) + DungeonMap.render(context.getMatrices()); + } + + @Inject(method = "renderMountHealth", at = @At("HEAD"), cancellable = true) + private void skyblocker$renderMountHealth(CallbackInfo ci) { + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.bars.enableBars && !Utils.isInTheRift()) + ci.cancel(); + } + + @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"), cancellable = true) + private void skyblocker$dontRenderStatusEffects(CallbackInfo ci) { + if (Utils.isOnSkyblock() && SkyblockerConfigManager.get().general.hideStatusEffectOverlay) ci.cancel(); + } + + @ModifyExpressionValue(method = "renderCrosshair", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getAttackCooldownProgress(F)F")) + private float skyblocker$modifyAttackIndicatorCooldown(float cooldownProgress) { + if (Utils.isOnSkyblock() && client.player != null) { + ItemStack stack = client.player.getMainHandStack(); + if (ItemCooldowns.isOnCooldown(stack)) { + return ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent(); + } + } + + return cooldownProgress; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/InventoryScreenMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InventoryScreenMixin.java new file mode 100644 index 00000000..8e6b9230 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/InventoryScreenMixin.java @@ -0,0 +1,18 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.itemlist.ItemListWidget; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(InventoryScreen.class) +public abstract class InventoryScreenMixin { + @ModifyExpressionValue(method = "<init>", at = @At(value = "NEW", target = "net/minecraft/client/gui/screen/recipebook/RecipeBookWidget")) + private RecipeBookWidget skyblocker$replaceRecipeBook(RecipeBookWidget original) { + return SkyblockerConfigManager.get().general.itemList.enableItemList && Utils.isOnSkyblock() ? new ItemListWidget() : original; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/ItemMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ItemMixin.java new file mode 100644 index 00000000..98bea52b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ItemMixin.java @@ -0,0 +1,22 @@ +package de.hysky.skyblocker.mixin; + +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +@Mixin(Item.class) +public abstract class ItemMixin { + @WrapOperation( + method = {"getItemBarColor", "getItemBarStep"}, + at = @At(value = "FIELD", target = "Lnet/minecraft/item/Item;maxDamage:I", opcode = Opcodes.GETFIELD) + ) + private int skyblocker$handlePickoDrillBar(Item item, Operation<Integer> original, ItemStack stack) { + return stack.getMaxDamage(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/ItemStackMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ItemStackMixin.java new file mode 100644 index 00000000..c7f5fac9 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ItemStackMixin.java @@ -0,0 +1,61 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.utils.ItemUtils; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.Text; + +@Mixin(ItemStack.class) +public abstract class ItemStackMixin { + @Shadow + @Nullable + private NbtCompound nbt; + + @ModifyReturnValue(method = "getName", at = @At("RETURN")) + private Text skyblocker$customItemNames(Text original) { + if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null; + + return SkyblockerConfigManager.get().general.customItemNames.getOrDefault(itemUuid, original); + } + + return original; + } + + @ModifyReturnValue(method = "getDamage", at = @At("RETURN")) + private int skyblocker$handleDamage(int original) { + ItemUtils.Durability dur = ItemUtils.getDurability((ItemStack) (Object) this); + if (dur != null) { + return dur.max() - dur.current(); + } + return original; + } + + @ModifyReturnValue(method = "getMaxDamage", at = @At("RETURN")) + private int skyblocker$handleMaxDamage(int original) { + ItemUtils.Durability dur = ItemUtils.getDurability((ItemStack) (Object) this); + if (dur != null) { + return dur.max(); + } + return original; + } + + @ModifyReturnValue(method = "isDamageable", at = @At("RETURN")) + private boolean skyblocker$handleDamageable(boolean original) { + ItemUtils.Durability dur = ItemUtils.getDurability((ItemStack) (Object) this); + if (dur != null) { + return true; + } + return original; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/LeverBlockMixin.java b/src/main/java/de/hysky/skyblocker/mixin/LeverBlockMixin.java new file mode 100644 index 00000000..97c0a7c0 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/LeverBlockMixin.java @@ -0,0 +1,29 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.skyblock.dungeon.OldLever; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.block.BlockState; +import net.minecraft.block.LeverBlock; +import net.minecraft.block.WallMountedBlock; +import net.minecraft.util.shape.VoxelShape; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import dev.cbyrne.betterinject.annotations.Arg; +import dev.cbyrne.betterinject.annotations.Inject; + +@Mixin(LeverBlock.class) +public abstract class LeverBlockMixin extends WallMountedBlock { + protected LeverBlockMixin(Settings settings) { + super(settings); + } + + @Inject(method = "getOutlineShape", at = @At("HEAD"), cancellable = true) + public void skyblocker$onGetOutlineShape(@Arg BlockState state, CallbackInfoReturnable<VoxelShape> cir) { + if (Utils.isOnSkyblock()) { + VoxelShape shape = OldLever.getShape(state.get(FACE), state.get(FACING)); + if (shape != null) cir.setReturnValue(shape); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java new file mode 100644 index 00000000..066490d5 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java @@ -0,0 +1,25 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import dev.cbyrne.betterinject.annotations.Inject; + +@Mixin(MinecraftClient.class) +public abstract class MinecraftClientMixin { + @Shadow + @Nullable + public ClientPlayerEntity player; + + @Inject(method = "handleInputEvents", at = @At("HEAD")) + public void skyblocker$handleInputEvents() { + if (Utils.isOnSkyblock()) { + HotbarSlotLock.handleInputEvents(player); + } + } +}
\ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/mixin/PlayerListHudMixin.java b/src/main/java/de/hysky/skyblocker/mixin/PlayerListHudMixin.java new file mode 100644 index 00000000..7330b1c1 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/PlayerListHudMixin.java @@ -0,0 +1,57 @@ +package de.hysky.skyblocker.mixin; + +import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.tabhud.TabHud; +import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListMgr; +import de.hysky.skyblocker.utils.Utils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.text.Text; +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.callback.CallbackInfo; + +import dev.cbyrne.betterinject.annotations.Arg; +import dev.cbyrne.betterinject.annotations.Inject; + +@Environment(EnvType.CLIENT) +@Mixin(PlayerListHud.class) +public class PlayerListHudMixin { + @Shadow + private Text footer; + + @Inject(at = @At("HEAD"), method = "render(Lnet/minecraft/client/gui/DrawContext;ILnet/minecraft/scoreboard/Scoreboard;Lnet/minecraft/scoreboard/ScoreboardObjective;)V", cancellable = true) + public void skyblocker$renderTabHud(@Arg DrawContext context, @Arg int w, CallbackInfo info) { + if (!Utils.isOnSkyblock() || !SkyblockerConfigManager.get().general.tabHud.tabHudEnabled || TabHud.defaultTgl.isPressed()) { + return; + } + + ClientPlayNetworkHandler nwH = MinecraftClient.getInstance().getNetworkHandler(); + if (nwH == null) { + return; + } + + int h = MinecraftClient.getInstance().getWindow().getScaledHeight(); + float scale = SkyblockerConfigManager.get().general.tabHud.tabHudScale / 100f; + w = (int) (w / scale); + h = (int) (h / scale); + + PlayerListMgr.updateFooter(footer); + + try { + ScreenMaster.render(context, w,h); + // Screen screen = Screen.getCorrect(w, h, footer); + // screen.render(context); + info.cancel(); + } catch (Exception e) { + TabHud.LOGGER.error("[Skyblocker] Encountered unknown exception while drawing default hud", e); + } + } + +}
\ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinProviderMixin.java b/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinProviderMixin.java new file mode 100644 index 00000000..978835d2 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/PlayerSkinProviderMixin.java @@ -0,0 +1,29 @@ +package de.hysky.skyblocker.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftSessionService; + +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.texture.PlayerSkinProvider.Textures; + +@Mixin(targets = "net.minecraft.client.texture.PlayerSkinProvider$1") +public class PlayerSkinProviderMixin { + + @ModifyReturnValue(method = "method_52867", at = @At("RETURN")) + private static Textures skyblocker$fixTexturesThatHadAnInvalidSignature(Textures texture, @Local MinecraftSessionService sessionService, @Local GameProfile profile) { + if (Utils.isOnHypixel() && texture == Textures.MISSING) { + try { + return Textures.fromMap(sessionService.getTextures(profile, false), false); + } catch (Throwable t) { + return Textures.MISSING; + } + } + + return texture; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/ScoreboardMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ScoreboardMixin.java new file mode 100644 index 00000000..2cfb658a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/ScoreboardMixin.java @@ -0,0 +1,16 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.WrapWithCondition; +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.scoreboard.Scoreboard; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Scoreboard.class) +public abstract class ScoreboardMixin { + @WrapWithCondition(method = "addTeam", 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(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/SocialInteractionsPlayerListWidgetMixin.java b/src/main/java/de/hysky/skyblocker/mixin/SocialInteractionsPlayerListWidgetMixin.java new file mode 100644 index 00000000..3a60bfbb --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/SocialInteractionsPlayerListWidgetMixin.java @@ -0,0 +1,24 @@ +package de.hysky.skyblocker.mixin; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.gui.screen.multiplayer.SocialInteractionsPlayerListEntry; +import net.minecraft.client.gui.screen.multiplayer.SocialInteractionsPlayerListWidget; + +@Mixin(SocialInteractionsPlayerListWidget.class) +public class SocialInteractionsPlayerListWidgetMixin { + + @WrapOperation(method = "setPlayers", at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", remap = false)) + private Object skyblocker$hideInvalidPlayers(Map<Object, Object> map, Object uuid, Object entry, Operation<Object> operation) { + if (Utils.isOnSkyblock() && !((SocialInteractionsPlayerListEntry) entry).getName().matches("[A-Za-z0-9_]+")) return null; + + return operation.call(map, uuid, entry); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java new file mode 100644 index 00000000..e723c998 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java @@ -0,0 +1,33 @@ +package de.hysky.skyblocker.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef; + +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.dungeon.StarredMobGlow; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.entity.Entity; + +@Mixin(WorldRenderer.class) +public class WorldRendererMixin { + + @ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;hasOutline(Lnet/minecraft/entity/Entity;)Z")) + private boolean skyblocker$shouldStarredMobGlow(boolean original, @Local Entity entity, @Share("isGlowingStarredMob") LocalBooleanRef isGlowingStarredMob) { + boolean isAStarredMobThatShouldGlow = SkyblockerConfigManager.get().locations.dungeons.starredMobGlow && StarredMobGlow.shouldMobGlow(entity); + + isGlowingStarredMob.set(isAStarredMobThatShouldGlow); + + return original || isAStarredMobThatShouldGlow; + } + + @ModifyVariable(method = "render", at = @At("STORE"), ordinal = 0) + private int skyblocker$modifyGlowColor(int color, @Local Entity entity, @Share("isGlowingStarredMob") LocalBooleanRef isGlowingStarredMob) { + return isGlowingStarredMob.get() ? StarredMobGlow.getGlowColor(entity) : color; + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/YggdrasilMinecraftSessionServiceMixin.java b/src/main/java/de/hysky/skyblocker/mixin/YggdrasilMinecraftSessionServiceMixin.java new file mode 100644 index 00000000..8da87be0 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/YggdrasilMinecraftSessionServiceMixin.java @@ -0,0 +1,20 @@ +package de.hysky.skyblocker.mixin; + +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; + +import de.hysky.skyblocker.utils.Utils; + +@Mixin(value = YggdrasilMinecraftSessionService.class, remap = false) +public class YggdrasilMinecraftSessionServiceMixin { + + @WrapOperation(method = "getSecurePropertyValue", remap = false, at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) + private void skyblocker$dontLogMissingSignaturesOrTamperedProperties(Logger logger, String message, Object property, Operation<Void> operation) { + if (!Utils.isOnHypixel()) operation.call(logger, message, property); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java b/src/main/java/de/hysky/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java new file mode 100644 index 00000000..d38e40cc --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/YggdrasilServicesKeyInfoMixin.java @@ -0,0 +1,59 @@ +package de.hysky.skyblocker.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.authlib.yggdrasil.YggdrasilServicesKeyInfo; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import de.hysky.skyblocker.utils.Utils; +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.Unique; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Base64; +import java.util.Map; + +@Mixin(value = YggdrasilServicesKeyInfo.class, remap = false) +public class YggdrasilServicesKeyInfoMixin { + @Shadow + @Final + private static Logger LOGGER; + @Unique + private static final Map<String, String> REPLACEMENT_MAP = Map.of(); + @Unique + private static final IntList ERRONEUS_SIGNATURE_HASHES = new IntArrayList(); + + @WrapOperation(method = "validateProperty", at = @At(value = "INVOKE", target = "Ljava/util/Base64$Decoder;decode(Ljava/lang/String;)[B", remap = false), remap = false) + private byte[] skyblocker$replaceKnownWrongBase64(Base64.Decoder decoder, String signature, Operation<byte[]> decode) { + try { + return decode.call(decoder, signature); + } catch (IllegalArgumentException e) { + try { + return decode.call(decoder, signature.replaceAll("[^A-Za-z0-9+/=]", "")); + } catch (IllegalArgumentException e2) { + if (Utils.isOnSkyblock()) { + if (REPLACEMENT_MAP.containsKey(signature)) { + return decode.call(decoder, REPLACEMENT_MAP.get(signature)); + } + int signatureHashCode = signature.hashCode(); + if (!ERRONEUS_SIGNATURE_HASHES.contains(signatureHashCode)) { + ERRONEUS_SIGNATURE_HASHES.add(signatureHashCode); + LOGGER.warn("[Skyblocker Base64 Fixer] Failed to decode base64 string No.{}: {}", ERRONEUS_SIGNATURE_HASHES.size() - 1, signature); + } else { + LOGGER.warn("[Skyblocker Base64 Fixer] Failed to decode the base64 string No.{} again", ERRONEUS_SIGNATURE_HASHES.indexOf(signatureHashCode)); + } + } + } + throw e; + } + } + + @WrapOperation(method = "validateProperty", remap = false, at = @At(value = "INVOKE", target = "org/slf4j/Logger.error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false)) + private void skyblocker$dontLogFailedSignatureValidation(Logger logger, String message, Object property, Object exception, Operation<Void> operation) { + if (!Utils.isOnHypixel()) operation.call(logger, message, property, exception); + } +}
\ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java new file mode 100644 index 00000000..0b607fce --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/BeaconBlockEntityRendererInvoker.java @@ -0,0 +1,16 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BeaconBlockEntityRenderer; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(BeaconBlockEntityRenderer.class) +public interface BeaconBlockEntityRendererInvoker { + @SuppressWarnings("unused") + @Invoker("renderBeam") + static void renderBeam(MatrixStack matrices, VertexConsumerProvider vertexConsumers, float tickDelta, long worldTime, int yOffset, int maxY, float[] color) { + throw new IllegalStateException("Mixin invoker failed to apply."); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/DrawContextInvoker.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/DrawContextInvoker.java new file mode 100644 index 00000000..8dcccf34 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/DrawContextInvoker.java @@ -0,0 +1,17 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.gui.tooltip.TooltipPositioner; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(DrawContext.class) +public interface DrawContextInvoker { + + @Invoker + void invokeDrawTooltip(TextRenderer textRenderer, List<TooltipComponent> components, int x, int y, TooltipPositioner positioner); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/FrustumInvoker.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/FrustumInvoker.java new file mode 100644 index 00000000..3a9e688b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/FrustumInvoker.java @@ -0,0 +1,15 @@ +package de.hysky.skyblocker.mixin.accessor; + +import de.hysky.skyblocker.utils.render.FrustumUtils; +import net.minecraft.client.render.Frustum; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +/** + * Use {@link FrustumUtils#isVisible(double, double, double, double, double, double) FrustumUtils#isVisible} which is shorter. For the purpose of avoiding object allocations! + */ +@Mixin(Frustum.class) +public interface FrustumInvoker { + @Invoker + boolean invokeIsVisible(double minX, double minY, double minZ, double maxX, double maxY, double maxZ); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/HandledScreenAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/HandledScreenAccessor.java new file mode 100644 index 00000000..d82422cb --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/HandledScreenAccessor.java @@ -0,0 +1,20 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(HandledScreen.class) +public interface HandledScreenAccessor { + @Accessor("x") + int getX(); + + @Accessor("y") + int getY(); + + @Accessor + int getBackgroundWidth(); + + @Accessor + int getBackgroundHeight(); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java new file mode 100644 index 00000000..d82c568f --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/PlayerListHudAccessor.java @@ -0,0 +1,17 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Comparator; + +@Mixin(PlayerListHud.class) +public interface PlayerListHudAccessor { + + @Accessor("ENTRY_ORDERING") + static Comparator<PlayerListEntry> getOrdering() { + throw new AssertionError(); + } +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java new file mode 100644 index 00000000..aecdf9b7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/RecipeBookWidgetAccessor.java @@ -0,0 +1,14 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.client.gui.widget.TextFieldWidget; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(RecipeBookWidget.class) +public interface RecipeBookWidgetAccessor { + @Accessor + String getSearchText(); + @Accessor + TextFieldWidget getSearchField(); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/ScreenAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/ScreenAccessor.java new file mode 100644 index 00000000..c0196e5f --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/ScreenAccessor.java @@ -0,0 +1,14 @@ +package de.hysky.skyblocker.mixin.accessor; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Screen.class) +public interface ScreenAccessor { + @Accessor + @Mutable + void setTitle(Text title); +} diff --git a/src/main/java/de/hysky/skyblocker/mixin/accessor/WorldRendererAccessor.java b/src/main/java/de/hysky/skyblocker/mixin/accessor/WorldRendererAccessor.java new file mode 100644 index 00000000..f1b3158d --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixin/accessor/WorldRendererAccessor.java @@ -0,0 +1,13 @@ +package de.hysky.skyblocker.mixin.accessor; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.render.Frustum; +import net.minecraft.client.render.WorldRenderer; + +@Mixin(WorldRenderer.class) +public interface WorldRendererAccessor { + @Accessor + Frustum getFrustum(); +}
\ No newline at end of file |