mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 03:26:44 +01:00
Handle stack limits when equipping items to trinket slots
This commit is contained in:
parent
ac874945cd
commit
e02589d07b
6 changed files with 161 additions and 5 deletions
|
@ -0,0 +1,58 @@
|
|||
package com.minelittlepony.unicopia.mixin.trinkets;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import dev.emi.trinkets.TrinketSlot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
|
||||
// fixed shift-clicking (handles other 10%)
|
||||
@Mixin(ScreenHandler.class)
|
||||
abstract class MixinScreenHandler {
|
||||
@Nullable
|
||||
private Slot currentSlot;
|
||||
|
||||
@Redirect(method = "insertItem",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/collection/DefaultedList;get(I)Ljava/lang/Object;"
|
||||
)
|
||||
)
|
||||
// manual capture of the current slot since @Redirect doesn't support local captures
|
||||
private Object onGetSlot(DefaultedList<Slot> sender, int index) {
|
||||
currentSlot = sender.get(index);
|
||||
return currentSlot;
|
||||
}
|
||||
|
||||
@Redirect(method = "insertItem",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/screen/slot/Slot;getMaxItemCount()I"
|
||||
)
|
||||
)
|
||||
// redirect slot.getMaxItemCount() to stack aware version
|
||||
protected int onGetMaxItemCount(Slot sender, ItemStack stack) {
|
||||
return canApply(sender) ? sender.getMaxItemCount(stack) : sender.getMaxItemCount();
|
||||
}
|
||||
|
||||
@Redirect(method = "insertItem",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/item/ItemStack;isEmpty()Z",
|
||||
ordinal = 1
|
||||
)
|
||||
)
|
||||
// redirect "if (!itemStack.isEmpty() && ItemStack.canCombine(stack, itemStack))" -> "if (!canNotInsert(itemStack, slot) && ItemStack.canCombine(stack, itemStack))"
|
||||
protected boolean canNotInsert(ItemStack sender) {
|
||||
return sender.isEmpty() || (canApply(currentSlot) && (currentSlot.getStack().getCount() + sender.getCount()) <= currentSlot.getMaxItemCount(sender));
|
||||
}
|
||||
|
||||
private static boolean canApply(Slot slot) {
|
||||
return slot instanceof TrinketSlot;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.minelittlepony.unicopia.mixin.trinkets;
|
||||
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
|
||||
import com.minelittlepony.unicopia.trinkets.TrinketsDelegateImpl;
|
||||
import dev.emi.trinkets.api.*;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
@Mixin(TrinketItem.class)
|
||||
abstract class MixinTrinketItem {
|
||||
// overwrite with a max-count aware version (fixes inserting)
|
||||
@Overwrite
|
||||
public static boolean equipItem(PlayerEntity user, ItemStack stack) {
|
||||
return TrinketsDelegateImpl.INSTANCE.getInventories(user)
|
||||
.filter(inv -> TrinketsDelegateImpl.tryInsert(inv, stack, user))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.minelittlepony.unicopia.mixin.trinkets;
|
||||
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
|
||||
import com.minelittlepony.unicopia.trinkets.TrinketsDelegateImpl;
|
||||
import dev.emi.trinkets.*;
|
||||
import dev.emi.trinkets.api.*;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
@Mixin(SurvivalTrinketSlot.class)
|
||||
abstract class MixinTrinketSurvivalSlot extends Slot implements TrinketSlot {
|
||||
@Shadow(remap = false)
|
||||
private @Final int slotOffset;
|
||||
@Shadow(remap = false)
|
||||
private @Final TrinketInventory trinketInventory;
|
||||
|
||||
MixinTrinketSurvivalSlot() { super(null, 0, 0, 0); }
|
||||
|
||||
@Override
|
||||
public int getMaxItemCount(ItemStack stack) {
|
||||
return TrinketsDelegateImpl.getMaxCount(stack, new SlotReference(trinketInventory, slotOffset), super.getMaxItemCount(stack));
|
||||
}
|
||||
}
|
||||
|
||||
@Mixin(CreativeTrinketSlot.class)
|
||||
abstract class MixinTrinketCreativeSlot extends Slot implements TrinketSlot {
|
||||
@Shadow(remap = false)
|
||||
private @Final SurvivalTrinketSlot original;
|
||||
|
||||
MixinTrinketCreativeSlot() { super(null, 0, 0, 0); }
|
||||
|
||||
@Override
|
||||
public int getMaxItemCount(ItemStack stack) {
|
||||
return original.getMaxItemCount(stack);
|
||||
}
|
||||
}
|
|
@ -9,14 +9,15 @@ import com.minelittlepony.unicopia.util.InventoryUtil;
|
|||
import dev.emi.trinkets.TrinketSlot;
|
||||
import dev.emi.trinkets.api.*;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.event.GameEvent;
|
||||
|
||||
class TrinketsDelegateImpl implements TrinketsDelegate {
|
||||
static final TrinketsDelegateImpl INSTANCE = new TrinketsDelegateImpl();
|
||||
public class TrinketsDelegateImpl implements TrinketsDelegate {
|
||||
public static final TrinketsDelegateImpl INSTANCE = new TrinketsDelegateImpl();
|
||||
// who tf designed this api?
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +72,7 @@ class TrinketsDelegateImpl implements TrinketsDelegate {
|
|||
);
|
||||
}
|
||||
|
||||
private Stream<TrinketInventory> getInventories(LivingEntity entity) {
|
||||
public Stream<TrinketInventory> getInventories(LivingEntity entity) {
|
||||
return TrinketsApi.getTrinketComponent(entity)
|
||||
.stream()
|
||||
.map(component -> component.getInventory())
|
||||
|
@ -82,4 +83,40 @@ class TrinketsDelegateImpl implements TrinketsDelegate {
|
|||
private static Identifier getSlotId(SlotType slotType) {
|
||||
return new Identifier(slotType.getGroup(), slotType.getName());
|
||||
}
|
||||
|
||||
public static int getMaxCount(ItemStack stack, SlotReference ref, int normal) {
|
||||
Trinket trinket = TrinketsApi.getTrinket(stack.getItem());
|
||||
if (trinket instanceof UnicopiaTrinket ut) {
|
||||
return Math.min(
|
||||
normal,
|
||||
Math.min(
|
||||
stack.getMaxCount(),
|
||||
ut.getMaxCount(stack, ref)
|
||||
));
|
||||
}
|
||||
return normal;
|
||||
}
|
||||
|
||||
public static boolean tryInsert(TrinketInventory inv, ItemStack stack, PlayerEntity user) {
|
||||
int i = InventoryUtil.getOpenSlot(inv);
|
||||
if (i == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SlotReference ref = new SlotReference(inv, i);
|
||||
if (!TrinketSlot.canInsert(stack, ref, user)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Trinket trinket = TrinketsApi.getTrinket(stack.getItem());
|
||||
|
||||
SoundEvent soundEvent = stack.getEquipSound();
|
||||
inv.setStack(i, stack.split(trinket instanceof UnicopiaTrinket ut ? ut.getMaxCount(stack, ref) : stack.getMaxCount()));
|
||||
if (!stack.isEmpty() && soundEvent != null) {
|
||||
user.emitGameEvent(GameEvent.EQUIP);
|
||||
user.playSound(soundEvent, 1, 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public class UnicopiaTrinket implements Trinket {
|
|||
}
|
||||
|
||||
// @Override
|
||||
public int getMaxCount(ItemStack stack, SlotReference slot, LivingEntity entity) {
|
||||
public int getMaxCount(ItemStack stack, SlotReference slot) {
|
||||
// https://github.com/emilyploszaj/trinkets/issues/215
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,11 @@
|
|||
"MixinShulkerEntity",
|
||||
"MixinTargetPredicate",
|
||||
"MixinWorld",
|
||||
"MixinWorldChunk"
|
||||
"MixinWorldChunk",
|
||||
"trinkets.MixinTrinketSurvivalSlot",
|
||||
"trinkets.MixinTrinketCreativeSlot",
|
||||
"trinkets.MixinTrinketItem",
|
||||
"trinkets.MixinScreenHandler"
|
||||
],
|
||||
"client": [
|
||||
"client.MixinAnimalModel",
|
||||
|
|
Loading…
Reference in a new issue