1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-02-08 15:10:05 +00:00

Fix pocket computers not being active in the off-hand

While Item.inventoryTick is passed a slot number, apparently that slot
corresponds to the offset within a particular inventory compartment
(such as the main inventory or armour)[^1], rather than the inventory as
a whole.

In the case of the off-hand, this means the pocket computer is set to be
in slot 0. When we next tick the computer (to send terminal updates), we
then assume the item has gone missing, and so skip sending updates.

Fixes #1945.

[^1]: A fun side effect of this is that the "selected" flag is true for
  the off-hand iff the player has slot 0 active. This whole thing feels
  like a vanilla bug, but who knows!
This commit is contained in:
Jonathan Coates 2024-08-19 17:28:02 +01:00
parent d7cea55e2a
commit 8080dcdd9e
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
2 changed files with 31 additions and 2 deletions

View File

@ -128,12 +128,16 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
}
@Override
public void inventoryTick(ItemStack stack, Level world, Entity entity, int slotNum, boolean selected) {
public void inventoryTick(ItemStack stack, Level world, Entity entity, int compartmentSlot, boolean selected) {
// This (in vanilla at least) is only called for players. Don't bother to handle other entities.
if (world.isClientSide || !(entity instanceof ServerPlayer player)) return;
// Find the actual slot the item exists in, aborting if it can't be found.
var slot = InventoryUtil.getInventorySlotFromCompartment(player, compartmentSlot, stack);
if (slot < 0) return;
// If we're in the inventory, create a computer and keep it alive.
var holder = new PocketHolder.PlayerHolder(player, slotNum);
var holder = new PocketHolder.PlayerHolder(player, slot);
var brain = getOrCreateBrain((ServerLevel) world, holder, stack);
brain.computer().keepAlive();

View File

@ -9,9 +9,12 @@ import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
@ -35,6 +38,28 @@ public final class InventoryUtil {
};
}
/**
* Map a slot inside a player's compartment to a slot in the full player's inventory.
* <p>
* {@link Inventory#tick()} passes in a slot to {@link Item#inventoryTick(ItemStack, Level, Entity, int, boolean)}.
* However, this slot corresponds to the index within the current compartment (items, armour, offhand) and not
* the actual slot.
* <p>
* This method searches the relevant compartments (inventory and offhand, skipping armour) for the stack, returning
* its slot if found.
*
* @param player The player holding the item.
* @param slot The slot inside the compartment.
* @param stack The stack being ticked.
* @return The inventory slot, or {@code -1} if the item could not be found in the inventory.
*/
public static int getInventorySlotFromCompartment(Player player, int slot, ItemStack stack) {
if (stack.isEmpty()) throw new IllegalArgumentException("Cannot search for empty stack");
if (player.getInventory().getItem(slot) == stack) return slot;
if (player.getInventory().getItem(Inventory.SLOT_OFFHAND) == stack) return Inventory.SLOT_OFFHAND;
return -1;
}
public static @Nullable Container getEntityContainer(ServerLevel level, BlockPos pos, Direction side) {
var vecStart = new Vec3(
pos.getX() + 0.5 + 0.6 * side.getStepX(),