Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow spell circles to access player inventory #734

Merged
merged 1 commit into from
Nov 12, 2024
Merged
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
Expand Up @@ -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;
Expand Down Expand Up @@ -360,11 +361,88 @@ public InteractionHand getOtherHand() {
*/
protected abstract List<ItemStack> getUsableStacks(StackDiscoveryMode mode);

protected List<ItemStack> getUsableStacksForPlayer(StackDiscoveryMode mode, @Nullable InteractionHand castingHand, ServerPlayer caster) {
return switch (mode) {
case QUERY -> {
var out = new ArrayList<ItemStack>();

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 {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this case check both hands, just prioritizing otherhand. for stuff like self refilling artifacts and whatnot.

Copy link
Member

Choose a reason for hiding this comment

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

i think having this method take a list of hands to check may be better? that way callers can prioritize whichever hand they want while also being able to decide if they want the other hand used also. then just loop over that list, would probably be neater too.

Copy link
Member

Choose a reason for hiding this comment

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

not sure that this would ever actually be used in a case like that though

Copy link
Contributor Author

Choose a reason for hiding this comment

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

iiuc this is used for Place Block&co, not Recharge&co? I was just retaining previous behaviour when provided with a casting hand though

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<ItemStack>();

// 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<HeldItemInfo> getPrimaryStacks();

protected List<HeldItemInfo> 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.
*/
Expand Down Expand Up @@ -463,6 +541,38 @@ public boolean withdrawItem(Predicate<ItemStack> stackOk, int count, boolean act
*/
public abstract boolean replaceItem(Predicate<ItemStack> stackOk, ItemStack replaceWith, @Nullable InteractionHand hand);


public boolean replaceItemForPlayer(Predicate<ItemStack> 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
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,27 @@ public InteractionHand getCastingHand() {
}

@Override
// TODO: Could do something like get items in inventories adjacent to the circle?
protected List<ItemStack> 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<HeldItemInfo> 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<ItemStack> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,106 +70,17 @@ public void postExecution(CastResult result) {

@Override
protected List<ItemStack> getUsableStacks(StackDiscoveryMode mode) {
return switch (mode) {
case QUERY -> {
var out = new ArrayList<ItemStack>();

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<ItemStack>();

// 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<HeldItemInfo> 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<ItemStack> 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
Expand Down
Loading