diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java index 874428fe7..a7a3dd947 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/CastingEnvironment.java @@ -19,6 +19,7 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; @@ -360,11 +361,88 @@ public InteractionHand getOtherHand() { */ protected abstract List getUsableStacks(StackDiscoveryMode mode); + protected List getUsableStacksForPlayer(StackDiscoveryMode mode, @Nullable InteractionHand castingHand, ServerPlayer caster) { + return switch (mode) { + case QUERY -> { + var out = new ArrayList(); + + if (castingHand == null) { + var mainhand = caster.getItemInHand(InteractionHand.MAIN_HAND); + if (!mainhand.isEmpty()) { + out.add(mainhand); + } + + var offhand = caster.getItemInHand(InteractionHand.OFF_HAND); + if (!offhand.isEmpty()) { + out.add(offhand); + } + } else { + var offhand = caster.getItemInHand(HexUtils.otherHand(castingHand)); + if (!offhand.isEmpty()) { + out.add(offhand); + } + } + + // If we're casting from the main hand, try to pick from the slot one to the right of the selected slot + // Otherwise, scan the hotbar left to right + var anchorSlot = castingHand != InteractionHand.OFF_HAND + ? (caster.getInventory().selected + 1) % 9 + : 0; + + + for (int delta = 0; delta < 9; delta++) { + var slot = (anchorSlot + delta) % 9; + out.add(caster.getInventory().getItem(slot)); + } + + yield out; + } + case EXTRACTION -> { + // https://wiki.vg/Inventory is WRONG + // slots 0-8 are the hotbar + // for what purpose i cannot imagine + // http://redditpublic.com/images/b/b2/Items_slot_number.png looks right + // and offhand is 150 Inventory.java:464 + var out = new ArrayList(); + + // First, the inventory backwards + // We use inv.items here to get the main inventory, but not offhand or armor + Inventory inv = caster.getInventory(); + for (int i = inv.items.size() - 1; i >= 0; i--) { + if (i != inv.selected) { + out.add(inv.items.get(i)); + } + } + + // then the offhand, then the selected hand + out.addAll(inv.offhand); + out.add(inv.getSelected()); + + yield out; + } + }; + } + /** * Get the primary/secondary item stacks this env can use (i.e. main hand and offhand for the player). */ protected abstract List getPrimaryStacks(); + protected List getPrimaryStacksForPlayer(InteractionHand castingHand, ServerPlayer caster) { + var primaryItem = caster.getItemInHand(castingHand); + + if (primaryItem.isEmpty()) + primaryItem = ItemStack.EMPTY.copy(); + + var secondaryItem = caster.getItemInHand(HexUtils.otherHand(castingHand)); + + if (secondaryItem.isEmpty()) + secondaryItem = ItemStack.EMPTY.copy(); + + return List.of(new HeldItemInfo(secondaryItem, HexUtils.otherHand(castingHand)), new HeldItemInfo(primaryItem, + castingHand)); + } + /** * Return the slot from which to take blocks and items. */ @@ -463,6 +541,38 @@ public boolean withdrawItem(Predicate stackOk, int count, boolean act */ public abstract boolean replaceItem(Predicate stackOk, ItemStack replaceWith, @Nullable InteractionHand hand); + + public boolean replaceItemForPlayer(Predicate stackOk, ItemStack replaceWith, @Nullable InteractionHand hand, ServerPlayer caster) { + if (caster == null) + return false; + + if (hand != null && stackOk.test(caster.getItemInHand(hand))) { + caster.setItemInHand(hand, replaceWith); + return true; + } + + Inventory inv = caster.getInventory(); + for (int i = inv.items.size() - 1; i >= 0; i--) { + if (i != inv.selected) { + if (stackOk.test(inv.items.get(i))) { + inv.setItem(i, replaceWith); + return true; + } + } + } + + if (stackOk.test(caster.getItemInHand(getOtherHand()))) { + caster.setItemInHand(getOtherHand(), replaceWith); + return true; + } + if (stackOk.test(caster.getItemInHand(getCastingHand()))) { + caster.setItemInHand(getCastingHand(), replaceWith); + return true; + } + + return false; + } + /** * The order/mode stacks should be discovered in */ diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java index a5cfdaa62..111bf3213 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/CircleCastEnv.java @@ -166,18 +166,27 @@ public InteractionHand getCastingHand() { } @Override + // TODO: Could do something like get items in inventories adjacent to the circle? protected List getUsableStacks(StackDiscoveryMode mode) { - return new ArrayList<>(); // TODO: Could do something like get items in inventories adjacent to the circle? + if (this.getCaster() != null) + return getUsableStacksForPlayer(mode, null, this.getCaster()); + return new ArrayList<>(); } @Override + // TODO: Adjacent inv! protected List getPrimaryStacks() { - return List.of(); // TODO: Adjacent inv! + if (this.getCaster() != null) + return getPrimaryStacksForPlayer(InteractionHand.OFF_HAND, this.getCaster()); + return List.of(); } @Override + // TODO: Adjacent inv! public boolean replaceItem(Predicate stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { - return false; // TODO: Adjacent inv! + if (this.getCaster() != null) + return replaceItemForPlayer(stackOk, replaceWith, hand, this.getCaster()); + return false; } @Override diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java index 52b7ee979..a6cfa1976 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/eval/env/PlayerBasedCastEnv.java @@ -70,106 +70,17 @@ public void postExecution(CastResult result) { @Override protected List getUsableStacks(StackDiscoveryMode mode) { - return switch (mode) { - case QUERY -> { - var out = new ArrayList(); - - var offhand = this.caster.getItemInHand(HexUtils.otherHand(this.castingHand)); - if (!offhand.isEmpty()) { - out.add(offhand); - } - - // If we're casting from the main hand, try to pick from the slot one to the right of the selected slot - // Otherwise, scan the hotbar left to right - var anchorSlot = this.castingHand == InteractionHand.MAIN_HAND - ? (this.caster.getInventory().selected + 1) % 9 - : 0; - - - for (int delta = 0; delta < 9; delta++) { - var slot = (anchorSlot + delta) % 9; - out.add(this.caster.getInventory().getItem(slot)); - } - - yield out; - } - case EXTRACTION -> { - // https://wiki.vg/Inventory is WRONG - // slots 0-8 are the hotbar - // for what purpose i cannot imagine - // http://redditpublic.com/images/b/b2/Items_slot_number.png looks right - // and offhand is 150 Inventory.java:464 - var out = new ArrayList(); - - // First, the inventory backwards - // We use inv.items here to get the main inventory, but not offhand or armor - Inventory inv = this.caster.getInventory(); - for (int i = inv.items.size() - 1; i >= 0; i--) { - if (i != inv.selected) { - out.add(inv.items.get(i)); - } - } - - // then the offhand, then the selected hand - out.addAll(inv.offhand); - out.add(inv.getSelected()); - - yield out; - } - }; + return getUsableStacksForPlayer(mode, castingHand, caster); } @Override protected List getPrimaryStacks() { - var primaryItem = this.caster.getItemInHand(this.castingHand); - - if (primaryItem.isEmpty()) - primaryItem = ItemStack.EMPTY.copy(); - - return List.of(new HeldItemInfo(getAlternateItem(), this.getOtherHand()), new HeldItemInfo(primaryItem, - this.castingHand)); - } - - ItemStack getAlternateItem() { - var otherHand = HexUtils.otherHand(this.castingHand); - var stack = this.caster.getItemInHand(otherHand); - if (stack.isEmpty()) { - return ItemStack.EMPTY.copy(); - } else { - return stack; - } + return getPrimaryStacksForPlayer(this.castingHand, this.caster); } @Override public boolean replaceItem(Predicate stackOk, ItemStack replaceWith, @Nullable InteractionHand hand) { - if (caster == null) - return false; - - if (hand != null && stackOk.test(caster.getItemInHand(hand))) { - caster.setItemInHand(hand, replaceWith); - return true; - } - - Inventory inv = this.caster.getInventory(); - for (int i = inv.items.size() - 1; i >= 0; i--) { - if (i != inv.selected) { - if (stackOk.test(inv.items.get(i))) { - inv.setItem(i, replaceWith); - return true; - } - } - } - - if (stackOk.test(caster.getItemInHand(getOtherHand()))) { - caster.setItemInHand(getOtherHand(), replaceWith); - return true; - } - if (stackOk.test(caster.getItemInHand(getCastingHand()))) { - caster.setItemInHand(getCastingHand(), replaceWith); - return true; - } - - return false; + return replaceItemForPlayer(stackOk, replaceWith, hand, this.caster); } @Override