mojira.dev

Kenny Zhang

Assigned

No issues.

Reported

MC-100584 Dropper into minecart offset by .5 of a block in negative x and z direction Fixed

Comments

Reproduced in 1.20.1.

Did a bit of testing, seems like the client doesn't get told about the teleport so it tries to move the player back to the entrance: https://youtu.be/rW2_QgqzfVY

Another way to reproduce: swim inside some water, then throw an ender pearl so you teleport somewhere high up and fall to your death.

After trying snapshot after snapshot, it seems like this was fixed in 17w47a

By looking at Minecraft's source code using Forge, I have determined the issue: Droppers, when looking for an inventory at a position, use the block's -x, -y, -z corner to search, while hoppers use the block's center. Because droppers directly use TileEntityHopper's getInventoryAtPosition method, this causes the dropper's searching location to be offset in the -x and -z direction. The fix is simple, and only requires one line to be changed:

BlockDropper.java:
...
    protected void dispense(World worldIn, BlockPos pos)
    {
        BlockSourceImpl blocksourceimpl = new BlockSourceImpl(worldIn, pos);
        TileEntityDispenser tileentitydispenser = (TileEntityDispenser)blocksourceimpl.getBlockTileEntity();

        if (tileentitydispenser != null)
        {
            int i = tileentitydispenser.getDispenseSlot();

            if (i < 0)
            {
                worldIn.playAuxSFX(1001, pos, 0);
            }
            else
            {
                ItemStack itemstack = tileentitydispenser.getStackInSlot(i);

                if (itemstack != null && net.minecraftforge.items.VanillaInventoryCodeHooks.dropperInsertHook(worldIn, pos, tileentitydispenser, i, itemstack))
                {
                    EnumFacing enumfacing = (EnumFacing)worldIn.getBlockState(pos).getValue(FACING);
                    BlockPos blockpos = pos.offset(enumfacing);

// ===========================================================================================
//                  IInventory iinventory = TileEntityHopper.getInventoryAtPosition(worldIn, (double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ());
                    IInventory iinventory = TileEntityHopper.getInventoryAtPosition(worldIn, (double)blockpos.getX() + 0.5, (double)blockpos.getY() + 0.5, (double)blockpos.getZ() + 0.5);
// ===========================================================================================

                    ItemStack itemstack1;

                    if (iinventory == null)
                    {
                        itemstack1 = this.dropBehavior.dispense(blocksourceimpl, itemstack);

                        if (itemstack1 != null && itemstack1.stackSize <= 0)
                        {
                            itemstack1 = null;
                        }
                    }
                    else
                    {
                        itemstack1 = TileEntityHopper.putStackInInventoryAllSlots(iinventory, itemstack.copy().splitStack(1), enumfacing.getOpposite());

                        if (itemstack1 == null)
                        {
                            itemstack1 = itemstack.copy();

                            if (--itemstack1.stackSize <= 0)
                            {
                                itemstack1 = null;
                            }
                        }
                        else
                        {
                            itemstack1 = itemstack.copy();
                        }
                    }

                    tileentitydispenser.setInventorySlotContents(i, itemstack1);
                }
            }
        }
    }
...