Jump to content

[1.16.5]Container Problem


yuho170

Recommended Posts

hello. I try to create my custom chest BUT that's make me crazy.

1.if I put an item in my custom chest it become doubled, and if I click it ,it will be dispeared.:(

2.the custom chest what i made use the same container in different blocks.

 

 TileEntity:


public class SFCTileEntity extends TileEntity implements INamedContainerProvider {
        public static final int NUMBER_OF_SLOTS = 27;

        public SFCTileEntity()
        {
            super(TileEntityTypeRegistry.TileEntity.get());
            chestContents = ChestContents.createForTileEntity(NUMBER_OF_SLOTS,
                    this::canPlayerAccessInventory, this::setChanged);
        }


        public boolean canPlayerAccessInventory(PlayerEntity player) {
            if (this.level.getBlockEntity(this.worldPosition) != this) return false;
            final double X_CENTRE_OFFSET = 0.5;
            final double Y_CENTRE_OFFSET = 0.5;
            final double Z_CENTRE_OFFSET = 0.5;
            final double MAXIMUM_DISTANCE_SQ = 8.0 * 8.0;
            return player.distanceToSqr(worldPosition.getX() + X_CENTRE_OFFSET, worldPosition.getY() + Y_CENTRE_OFFSET, worldPosition.getZ() + Z_CENTRE_OFFSET) < MAXIMUM_DISTANCE_SQ;
        }

        private static final String CHESTCONTENTS_INVENTORY_TAG = "contents";


        @Override
        public CompoundNBT save(CompoundNBT parentNBTTagCompound)
        {
            super.save(parentNBTTagCompound);
            CompoundNBT inventoryNBT = chestContents.serializeNBT();
            parentNBTTagCompound.put(CHESTCONTENTS_INVENTORY_TAG, inventoryNBT);
            return parentNBTTagCompound;
        }


        @Override
        public void load(BlockState blockState, CompoundNBT parentNBTTagCompound)
        {
            super.load(blockState, parentNBTTagCompound); 
            CompoundNBT inventoryNBT = parentNBTTagCompound.getCompound(CHESTCONTENTS_INVENTORY_TAG);
            chestContents.deserializeNBT(inventoryNBT);
        }


        @Override
        @Nullable
        public SUpdateTileEntityPacket getUpdatePacket()
        {
            CompoundNBT nbtTagCompound = new CompoundNBT();
            save(nbtTagCompound);
            int tileEntityType = 42;  
            return new SUpdateTileEntityPacket(this.worldPosition, tileEntityType, nbtTagCompound);
        }

        @Override
        public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
            BlockState blockState = level.getBlockState(worldPosition);
            load(blockState, pkt.getTag());
        }

        @Override
        public CompoundNBT getUpdateTag()
        {
            CompoundNBT nbtTagCompound = new CompoundNBT();
            save(nbtTagCompound);
            return nbtTagCompound;
        }

        /* Populates this TileEntity with information from the tag, used by vanilla to transmit from server to client
         *  The vanilla default is suitable for this example but I've included an explicit definition anyway.
         */
        @Override
        public void handleUpdateTag(BlockState blockState, CompoundNBT tag)
        {
            this.load(blockState, tag);
        }


        @Override
        public ITextComponent getDisplayName() {
            return null;
        }


        @Nullable
        @Override
        public Container createMenu(int windowID, PlayerInventory playerInventory, PlayerEntity playerEntity) {
            return SFContainer.createContainerServerSide(windowID, playerInventory, chestContents);
        }

        public static ChestContents getChestContents() {
            return chestContents;
        }

        private static ChestContents chestContents;
    }

 

Container:

public class SFContainer extends Container {
    private static final int HOTBAR_SLOT_COUNT = 9;
    private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
    private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
    private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
    private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;

    private static final int VANILLA_FIRST_SLOT_INDEX = 0;
    private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
    private static final int TE_INVENTORY_SLOT_COUNT = SFCTileEntity.NUMBER_OF_SLOTS;  

    public static final int TILE_INVENTORY_YPOS = 18; 
    public static final int PLAYER_INVENTORY_YPOS = 86;


    public SFContainer(int windowID, PlayerInventory playerInventory, ChestContents chestContents) {
        super(ContainerTypeRegistry.Container.get(), windowID);

        PlayerInvWrapper playerInventoryForge = new PlayerInvWrapper(playerInventory);
        this.chestContents = chestContents;
        final int SLOT_X_SPACING = 18;
        final int SLOT_Y_SPACING = 18;
        final int HOTBAR_XPOS = 8;
        final int HOTBAR_YPOS = 144;
        for (int x = 0; x < HOTBAR_SLOT_COUNT; x++) {
            int slotNumber = x;
            addSlot(new SlotItemHandler(playerInventoryForge, slotNumber, HOTBAR_XPOS + SLOT_X_SPACING * x, HOTBAR_YPOS));
        }

        final int PLAYER_INVENTORY_XPOS = 8;
        // Add the rest of the player's inventory to the gui
        for (int y = 0; y < PLAYER_INVENTORY_ROW_COUNT; y++) {
            for (int x = 0; x < PLAYER_INVENTORY_COLUMN_COUNT; x++) {
                int slotNumber = HOTBAR_SLOT_COUNT + y * PLAYER_INVENTORY_COLUMN_COUNT + x;
                int xpos = PLAYER_INVENTORY_XPOS + x * SLOT_X_SPACING;
                int ypos = PLAYER_INVENTORY_YPOS + y * SLOT_Y_SPACING;
                addSlot(new SlotItemHandler(playerInventoryForge, slotNumber,  xpos, ypos));
            }
        }
        // Add the tile inventory container to the gui
       for(int i = 0;i<9;i++){
           addSlot(new Slot(chestContents, i,  8+18*i, 18));
           addSlot(new Slot(chestContents, i+9,  8+18*i, 36));
           addSlot(new Slot(chestContents, i+18,  8+18*i, 54));
       }

    }
    public static SFContainer createContainerServerSide(int windowID, PlayerInventory playerInventory, ChestContents chestContents) {
        return new SFContainer(windowID, playerInventory, chestContents);
    }

    public static SFContainer createContainerClientSide(int windowID, PlayerInventory playerInventory, net.minecraft.network.PacketBuffer extraData) {

        ChestContents chestContents = ChestContents.createForClientSideContainer(SFCTileEntity.NUMBER_OF_SLOTS);


        return new SFContainer(windowID, playerInventory, chestContents);
    }
    @Override
    public boolean stillValid(PlayerEntity playerEntity)
    {

        return chestContents.stillValid(playerEntity);
    }

    @Override
    public ItemStack quickMoveStack(PlayerEntity playerEntity, int sourceSlotIndex)
    {
        Slot sourceSlot = getSlot(sourceSlotIndex);
        if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY;  //EMPTY_ITEM
        ItemStack sourceStack = sourceSlot.getItem();
        ItemStack copyOfSourceStack = sourceStack.copy();

        // Check if the slot clicked is one of the vanilla container slots
        if (sourceSlotIndex >= VANILLA_FIRST_SLOT_INDEX && sourceSlotIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
            // This is a vanilla container slot so merge the stack into the tile inventory
            if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT, false)){
                return ItemStack.EMPTY;  // EMPTY_ITEM
            }
        } else if (sourceSlotIndex >= TE_INVENTORY_FIRST_SLOT_INDEX && sourceSlotIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
            // This is a TE slot so merge the stack into the players inventory
            if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
                return ItemStack.EMPTY;
            }
        } else {
            LOGGER.warn("Invalid slotIndex:" + sourceSlotIndex);
            return ItemStack.EMPTY;
        }

        // If stack size == 0 (the entire stack was moved) set slot contents to null
        if (sourceStack.getCount() == 0) {
            sourceSlot.mayPlace(ItemStack.EMPTY);
        } else {
            sourceSlot.setChanged();
        }

        sourceSlot.onTake(playerEntity, sourceStack);
        return copyOfSourceStack;
    }

    // pass the close container message to the parent inventory (not strictly needed for this example)
    //  see ContainerChest and TileEntityChest - used to animate the lid when no players are accessing the chest any more
    @Override
    public void removed(PlayerEntity playerIn)
    {
        super.removed(playerIn);
    }

    private ChestContents chestContents;
    private static final Logger LOGGER = LogManager.getLogger();
}

 

Link to comment
Share on other sites

12 hours ago, diesieben07 said:

Why is this static? Please understand what static means (if you don't already) and then understand why this should not be static.

Why do you have these?

Use getCapability on the player to get the IItemHandler, don't create a new wrapper. Or just use the inventory directly.

 

I follow this https://github.com/TheGreyGhost/MinecraftByExample/tree/master/src/main/java/minecraftbyexample/mbe30_inventory_basic and try to make changes

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.