diff options
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker')
9 files changed, 249 insertions, 27 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index b28ad3d4..1d6f1eed 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -4,6 +4,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.*; +import me.xmrvizzy.skyblocker.skyblock.cooldown.ItemCooldowns; import me.xmrvizzy.skyblocker.skyblock.dungeon.*; import me.xmrvizzy.skyblocker.skyblock.dungeon.secrets.DungeonSecrets; import me.xmrvizzy.skyblocker.skyblock.dwarven.DwarvenHud; @@ -78,6 +79,7 @@ public class SkyblockerMod implements ClientModInitializer { Relics.init(); BackpackPreview.init(); QuickNav.init(); + ItemCooldowns.init(); DwarvenHud.init(); ChatMessageListener.init(); Shortcuts.init(); diff --git a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java index 5848ed15..092bc587 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/me/xmrvizzy/skyblocker/config/SkyblockerConfig.java @@ -187,6 +187,10 @@ public class SkyblockerConfig implements ConfigData { @ConfigEntry.Gui.CollapsibleObject() public FairySouls fairySouls = new FairySouls(); + @ConfigEntry.Category("itemCooldown") + @ConfigEntry.Gui.CollapsibleObject() + public ItemCooldown itemCooldown = new ItemCooldown(); + @ConfigEntry.Category("shortcuts") @ConfigEntry.Gui.CollapsibleObject() public Shortcuts shortcuts = new Shortcuts(); @@ -320,6 +324,10 @@ public class SkyblockerConfig implements ConfigData { public boolean highlightOnlyNearbySouls = false; } + public static class ItemCooldown { + public boolean enableItemCooldowns = true; + } + public static class Shortcuts { @ConfigEntry.Gui.Tooltip() public boolean enableShortcuts = true; diff --git a/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java b/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java new file mode 100644 index 00000000..9d9463f7 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/events/ClientPlayerBlockBreakEvent.java @@ -0,0 +1,21 @@ +package me.xmrvizzy.skyblocker.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; + +// Fabric API currently doesn't have an event for this +public class ClientPlayerBlockBreakEvent { + public static final Event<AfterBlockBreak> AFTER = EventFactory.createArrayBacked(AfterBlockBreak.class, + (listeners) -> (pos, player) -> { + for (AfterBlockBreak listener : listeners) { + listener.afterBlockBreak(pos, player); + } + }); + + @FunctionalInterface + public interface AfterBlockBreak { + void afterBlockBreak(BlockPos pos, PlayerEntity player); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java new file mode 100644 index 00000000..4b343317 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/ClientPlayerInteractionManagerMixin.java @@ -0,0 +1,24 @@ +package me.xmrvizzy.skyblocker.mixin; + +import me.xmrvizzy.skyblocker.events.ClientPlayerBlockBreakEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.util.math.BlockPos; +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; + +@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")) + private void skyblocker$blockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir) { + ClientPlayerBlockBreakEvent.AFTER.invoker().afterBlockBreak(pos, this.client.player); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java index cfe979d0..8cde4973 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/DrawContextMixin.java @@ -1,12 +1,13 @@ package me.xmrvizzy.skyblocker.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; import com.llamalad7.mixinextras.sugar.ref.LocalRef; import com.mojang.blaze3d.systems.RenderSystem; - import dev.cbyrne.betterinject.annotations.Arg; import dev.cbyrne.betterinject.annotations.Inject; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.skyblock.cooldown.ItemCooldowns; import me.xmrvizzy.skyblocker.skyblock.item.AttributeShards; import me.xmrvizzy.skyblocker.utils.ItemUtils; import me.xmrvizzy.skyblocker.utils.Utils; @@ -18,7 +19,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Formatting; import net.minecraft.util.math.ColorHelper; - import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -73,7 +73,8 @@ public abstract class DrawContextMixin { max = Integer.parseInt(split[1]) * 1000; } break; - } else if (line.contains("uses.")) { + } + else if (line.contains("uses.")) { if (clearFormatting != null) { int startIndex = clearFormatting.lastIndexOf("after") + 6; int endIndex = clearFormatting.indexOf("uses", startIndex); @@ -99,35 +100,45 @@ public abstract class DrawContextMixin { @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 (!SkyblockerConfig.get().general.itemInfoDisplay.attributeShardInfo) return; + if (!SkyblockerConfig.get().general.itemInfoDisplay.attributeShardInfo) return; + + NbtCompound nbt = stack.getNbt(); + + if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); - NbtCompound nbt = stack.getNbt(); + if (extraAttributes.getString("id").equals("ATTRIBUTE_SHARD")) { + NbtCompound attributesTag = extraAttributes.getCompound("attributes"); + String[] attributes = attributesTag.getKeys().toArray(String[]::new); - if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) { - NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + if (attributes.length != 0) { + String attributeId = attributes[0]; + int attributeLevel = attributesTag.getInt(attributeId); - if (extraAttributes.getString("id").equals("ATTRIBUTE_SHARD")) { - NbtCompound attributesTag = extraAttributes.getCompound("attributes"); - String[] attributes = attributesTag.getKeys().toArray(String[]::new); + //Set item count + countOverride.set(Integer.toString(attributeLevel)); - if (attributes.length != 0) { - String attributeId = attributes[0]; - int attributeLevel = attributesTag.getInt(attributeId); + //Draw the attribute name + this.matrices.push(); + this.matrices.translate(0f, 0f, 200f); - //Set item count - countOverride.set(Integer.toString(attributeLevel)); + String attributeInitials = AttributeShards.getShortName(attributeId); - //Draw the attribute name - this.matrices.push(); - this.matrices.translate(0f, 0f, 200f); + this.drawText(textRenderer, attributeInitials, x, y, Formatting.AQUA.getColorValue(), true); - String attributeInitials = AttributeShards.getShortName(attributeId); + this.matrices.pop(); + } + } + } + } - this.drawText(textRenderer, attributeInitials, x, y, Formatting.AQUA.getColorValue(), true); + @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) { + if (Utils.isOnSkyblock() && ItemCooldowns.isItemOnCooldown(stack)) { + return ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent(); + } - this.matrices.pop(); - } - } - } + return cooldownProgress; } -}
\ No newline at end of file +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java index 752b102a..19f928d8 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java +++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/InGameHudMixin.java @@ -1,17 +1,22 @@ package me.xmrvizzy.skyblocker.mixin; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; import me.xmrvizzy.skyblocker.SkyblockerMod; import me.xmrvizzy.skyblocker.config.SkyblockerConfig; import me.xmrvizzy.skyblocker.skyblock.FancyStatusBars; import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock; +import me.xmrvizzy.skyblocker.skyblock.cooldown.ItemCooldowns; import me.xmrvizzy.skyblocker.skyblock.dungeon.DungeonMap; import me.xmrvizzy.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.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; @@ -32,6 +37,10 @@ public abstract class InGameHudMixin { @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$renderHotbarItemLock(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) { if (Utils.isOnSkyblock() && HotbarSlotLock.isLocked(index)) { @@ -61,9 +70,21 @@ public abstract class InGameHudMixin { if (Utils.isOnSkyblock() && SkyblockerConfig.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() && SkyblockerConfig.get().general.hideStatusEffectOverlay) ci.cancel(); } -}
\ No newline at end of file + + @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()) { + ItemStack stack = this.client.player.getMainHandStack(); + if (ItemCooldowns.isItemOnCooldown(stack)) { + return ItemCooldowns.getItemCooldownEntry(stack).getRemainingCooldownPercent(); + } + } + + return cooldownProgress; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldownEntry.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldownEntry.java new file mode 100644 index 00000000..0b21c75f --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldownEntry.java @@ -0,0 +1,24 @@ +package me.xmrvizzy.skyblocker.skyblock.cooldown; + +public class ItemCooldownEntry { + private final int cooldown; + private final long startTime; + + public ItemCooldownEntry(int cooldown) { + this.cooldown = cooldown; + this.startTime = System.currentTimeMillis(); + } + + public boolean isOnCooldown() { + return (this.startTime + this.cooldown) > System.currentTimeMillis(); + } + + public long getRemainingCooldown() { + long time = (this.startTime + this.cooldown) - System.currentTimeMillis(); + return time <= 0 ? 0 : time; + } + + public float getRemainingCooldownPercent() { + return this.isOnCooldown() ? ((float) this.getRemainingCooldown()) / ((float) cooldown) : 0.0f; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldowns.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldowns.java new file mode 100644 index 00000000..6663b368 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/cooldown/ItemCooldowns.java @@ -0,0 +1,96 @@ +package me.xmrvizzy.skyblocker.skyblock.cooldown; + +import com.google.common.collect.ImmutableList; +import me.xmrvizzy.skyblocker.config.SkyblockerConfig; +import me.xmrvizzy.skyblocker.events.ClientPlayerBlockBreakEvent; +import me.xmrvizzy.skyblocker.utils.ItemUtils; +import net.fabricmc.fabric.api.event.player.UseItemCallback; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class ItemCooldowns { + private static final String JUNGLE_AXE_ID = "JUNGLE_AXE"; + private static final String TREECAPITATOR_ID = "TREECAPITATOR_AXE"; + private static final String GRAPPLING_HOOK_ID = "GRAPPLING_HOOK"; + private static final ImmutableList<String> BAT_ARMOR_IDS = ImmutableList.of("BAT_PERSON_HELMET", "BAT_PERSON_CHESTPLATE", "BAT_PERSON_LEGGINGS", "BAT_PERSON_BOOTS"); + + private static final Map<String, ItemCooldownEntry> itemCooldowns = new HashMap<>(); + private static SkyblockerConfig.ItemCooldown config; + + public static void init() { + ClientPlayerBlockBreakEvent.AFTER.register(ItemCooldowns::afterBlockBreak); + UseItemCallback.EVENT.register(ItemCooldowns::onItemInteract); + config = SkyblockerConfig.get().general.itemCooldown; + } + + public static void afterBlockBreak(BlockPos pos, PlayerEntity player) { + if (!config.enableItemCooldowns) return; + + String usedItemId = ItemUtils.getItemId(player.getMainHandStack()); + if (usedItemId == null) return; + + if (usedItemId.equals(JUNGLE_AXE_ID)) { + if (!isItemOnCooldown(JUNGLE_AXE_ID)) { + itemCooldowns.put(JUNGLE_AXE_ID, new ItemCooldownEntry(2000)); + } + } + else if (usedItemId.equals(TREECAPITATOR_ID)) { + if (!isItemOnCooldown(TREECAPITATOR_ID)) { + itemCooldowns.put(TREECAPITATOR_ID, new ItemCooldownEntry(2000)); + } + } + } + + private static TypedActionResult<ItemStack> onItemInteract(PlayerEntity player, World world, Hand hand) { + if (!config.enableItemCooldowns) return TypedActionResult.pass(ItemStack.EMPTY); + + String usedItemId = ItemUtils.getItemId(player.getMainHandStack()); + if (usedItemId != null && usedItemId.equals(GRAPPLING_HOOK_ID) && player.fishHook != null) { + if (!isItemOnCooldown(GRAPPLING_HOOK_ID) && !isPlayerWearingBatArmor(player)) { + itemCooldowns.put(GRAPPLING_HOOK_ID, new ItemCooldownEntry(2000)); + } + } + + return TypedActionResult.pass(ItemStack.EMPTY); + } + + public static boolean isItemOnCooldown(ItemStack itemStack) { + return isItemOnCooldown(ItemUtils.getItemId(itemStack)); + } + + private static boolean isItemOnCooldown(String itemId) { + if (itemCooldowns.containsKey(itemId)) { + ItemCooldownEntry cooldownEntry = itemCooldowns.get(itemId); + if (cooldownEntry.isOnCooldown()) { + return true; + } + else { + itemCooldowns.remove(cooldownEntry); + return false; + } + } + + return false; + } + + public static ItemCooldownEntry getItemCooldownEntry(ItemStack itemStack) { + return itemCooldowns.get(ItemUtils.getItemId(itemStack)); + } + + private static boolean isPlayerWearingBatArmor(PlayerEntity player) { + for (ItemStack stack : player.getArmorItems()) { + String itemId = ItemUtils.getItemId(stack); + if (!BAT_ARMOR_IDS.contains(itemId)) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java index 5c12b777..9953edae 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/ItemUtils.java @@ -4,6 +4,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.client.MinecraftClient; import net.minecraft.client.item.TooltipContext; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.StringNbtReader; import net.minecraft.text.Text; @@ -40,4 +41,18 @@ public class ItemUtils { throw new RuntimeException(e); } } + + public static String getItemId(ItemStack itemStack) { + if (itemStack == null) return null; + + NbtCompound nbt = itemStack.getNbt(); + if (nbt != null && nbt.contains("ExtraAttributes")) { + NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes"); + if (extraAttributes.contains("id")) { + return extraAttributes.getString("id"); + } + } + + return null; + } } |