Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,21 +1,64 @@
package de.hysky.skyblocker.mixins;

import de.hysky.skyblocker.skyblock.item.ItemStackUpdateDurability;
import de.hysky.skyblocker.skyblock.InventorySearch;
import de.hysky.skyblocker.skyblock.ItemPickupWidget;
import net.minecraft.core.NonNullList;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
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.List;

@Mixin(AbstractContainerMenu.class)
public class AbstractContainerMenuMixin {
public abstract class AbstractContainerMenuMixin {
@Shadow
@Final
public NonNullList<Slot> slots;

@Shadow
private ItemStack carried;

/// When the server creates or updates the entire menu
@Inject(method = "initializeContents", at = @At("TAIL"))
private void skyblocker$initializeContents(int stateId, List<ItemStack> list, ItemStack itemStack, CallbackInfo ci) {
for (int j = 0; j < list.size(); j++) {
((ItemStackUpdateDurability) (Object) this.slots.get(j).getItem()).skyblocker$getAndCacheDurability();
if (InventorySearch.isSearching()) {
InventorySearch.refreshSlot(j);
}
}
((ItemStackUpdateDurability) (Object) this.carried).skyblocker$getAndCacheDurability();
}

/// When the player clicks
@Inject(method = "doClick", at = @At("TAIL"))
private void skyblocker$doClick(int i, int j, ClickType clickType, Player player, CallbackInfo ci) {
// I'm way too lazy to figure how to only update the slots that were moved, soo...
for (int k = 0; k < this.slots.size(); k++) {
((ItemStackUpdateDurability) (Object) this.slots.get(k).getItem()).skyblocker$getAndCacheDurability();
if (InventorySearch.isSearching()) {
InventorySearch.refreshSlot(k);
}
}
((ItemStackUpdateDurability) (Object) this.carried).skyblocker$getAndCacheDurability();
}

/// When the server updates a single item
@Inject(method = "setItem", at = @At("HEAD"))
private void onSetStackInSlot(int slot, int revision, ItemStack stack, CallbackInfo ci) {
if (InventorySearch.isSearching()) {
InventorySearch.refreshSlot(slot);
}
ItemPickupWidget.getInstance().onItemPickup(slot, stack);
((ItemStackUpdateDurability) (Object) stack).skyblocker$getAndCacheDurability();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don’t you need this to be called on component update as well? We already have a mixin for that somewhere as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to the code for cancelComponentUpdateAnimation? That occurs in renderer code: ItemInHandRendererMixin.
There is also DataComponentHolderMixin, but that method doesn't seem to have a relevant update function.
Also, I don't believe the server even has a way to partially update an inventory stack's components: the only relevant packet seems to be ClientboundContainerSetSlotPacket, which always goes through setItem.

Copy link
Contributor Author

@InspectorBoat InspectorBoat Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I also did verify that the durability bar correctly updates while mining.)

}
}
19 changes: 4 additions & 15 deletions src/main/java/de/hysky/skyblocker/mixins/ItemStackMixin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.item.ItemStackUpdateDurability;
import de.hysky.skyblocker.injected.SkyblockerStack;
import de.hysky.skyblocker.skyblock.item.PetInfo;
import de.hysky.skyblocker.skyblock.item.SkyblockItemRarity;
Expand Down Expand Up @@ -35,7 +36,7 @@
import net.minecraft.world.item.enchantment.ItemEnchantments;

@Mixin(ItemStack.class)
public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerStack {
public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerStack, ItemStackUpdateDurability {
@Unique
private float durabilityBarFill = -1;

Expand Down Expand Up @@ -88,14 +89,6 @@ public abstract class ItemStackMixin implements DataComponentHolder, SkyblockerS
}
}

/**
* Updates the durability of this item stack every tick when in the inventory.
*/
@Inject(method = "inventoryTick", at = @At("TAIL"))
private void skyblocker$updateDamage(CallbackInfo ci) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do need it to update every tick for #1961

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for ticking cooldowns?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

skyblocker$getAndCacheDurability();
}

@ModifyReturnValue(method = "isBarVisible", at = @At("RETURN"))
private boolean modifyItemBarVisible(boolean original) {
return original || durabilityBarFill >= 0f;
Expand All @@ -111,11 +104,6 @@ private int modifyItemBarColor(int original) {
return durabilityBarFill >= 0 ? OkLabColor.interpolate(CommonColors.RED, CommonColors.GREEN, durabilityBarFill) : original;
}

@Inject(method = "<init>(Lnet/minecraft/world/level/ItemLike;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At("TAIL"))
private void onInit(CallbackInfo ci) {
skyblocker$getAndCacheDurability();
}

@Inject(method = "set*", at = @At("TAIL"))
private <T> void skyblocker$resetFields(DataComponentType<T> type, @Nullable T value, CallbackInfoReturnable<T> cir) {
if (type == DataComponents.CUSTOM_DATA) {
Expand All @@ -137,7 +125,8 @@ private void onInit(CallbackInfo ci) {
}

@Unique
private void skyblocker$getAndCacheDurability() {
@Override
public void skyblocker$getAndCacheDurability() {
if (!skyblocker$shouldProcess()) {
durabilityBarFill = -1;
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package de.hysky.skyblocker.skyblock.item;

public interface ItemStackUpdateDurability {
void skyblocker$getAndCacheDurability();
}