Jump to content

(1.18.2) sync of block entities with ContainerData


ElTotisPro50

Recommended Posts

So, if you want to access to a int variable from the screen you have to use ContainerData cause the server and client things, from the screen, i can get that value, but i cant from the block entity when the variable is created there (i need to get the value from the block entity too so when i right click the block, it gives me the price

/* The block itself */
    @Override
    public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos,
                                 Player player, InteractionHand pHand, BlockHitResult pHit) {
        ItemStack stack = player.getItemInHand(pHand);
        VendingMachineBlockEntity entity = (VendingMachineBlockEntity) pLevel.getBlockEntity(pPos);

        if(!pLevel.isClientSide) {
            if(!player.isShiftKeyDown()) {
                if(entity instanceof VendingMachineBlockEntity) NetworkHooks.openGui(((ServerPlayer)player), (VendingMachineBlockEntity) entity, pPos);
                else throw new IllegalStateException("The Container provider is missing!");
            } else {
                player.sendMessage(new TextComponent("" + entity.getSlot0Price()), player.getUUID());
            }
        }
        return super.use(pState, pLevel, pPos, player, pHand, pHit);
    }

In this case, the value is the price from the slot 0

 

public class VendingMachineBlockEntity extends BlockEntity implements MenuProvider {

    private int slot0Price = 0;
    private final ContainerData data;

	private final ItemStackHandler itemHandler = new ItemStackHandler(Constants.VENDINGMACHINE_TOTALSLOTS) {
		@Override
		protected void onContentsChanged(int slot) { setChanged(); };
	};

	private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty();

	public VendingMachineBlockEntity(BlockPos pos, BlockState state) {
		super(ModBlockEntities.VENDINGMACHINE_BLOCKENTITY.get(), pos, state);
        this.data = new ContainerData() {
            @Override
            public int get(int index) {
                switch(index) {
                    case 0: return VendingMachineBlockEntity.this.slot0Price;
                    default: return 0;
                }
            }

            @Override
            public void set(int index, int value) {
                switch(index) {
                    case 0: VendingMachineBlockEntity.this.slot0Price = value; break;
                };
            }

            @Override
            public int getCount() {
                return Constants.VENDINGMACHINE_CONTAINERDATASIZE;
            }
        };
	}

    @Override
	public AbstractContainerMenu createMenu(int id, Inventory inv, Player player) {
		return new VendingMachineMenu(id, inv, this, this.data);
	}

	@Override
	public Component getDisplayName() {
		return new TextComponent("");
	}
	
	@Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @javax.annotation.Nullable Direction side) {
        if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return lazyItemHandler.cast();
        }
        return super.getCapability(cap, side);
    }

    @Override
    public void onLoad() {
        super.onLoad();
        lazyItemHandler = LazyOptional.of(() -> itemHandler);
    }

    @Override
    public void invalidateCaps()  {
        super.invalidateCaps();
        lazyItemHandler.invalidate();
    }

    @Override
    protected void saveAdditional(@NotNull CompoundTag tag) {
        tag.put("inventory", itemHandler.serializeNBT());
        tag.putInt("Slot0Price", slot0Price);
        super.saveAdditional(tag);
    }
    @Override
    public void load(CompoundTag nbt) {
        super.load(nbt);
        itemHandler.deserializeNBT(nbt.getCompound("inventory"));
        slot0Price = nbt.getInt("Slot0Price");
    }

    public void drops() {
        SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots());
        for (int i = 0; i < itemHandler.getSlots(); i++) {
            inventory.setItem(i, itemHandler.getStackInSlot(i));
        }

        Containers.dropContents(this.level, this.worldPosition, inventory);
    }

    /*Synchronization to the client*/
    @Nullable
    @Override
    public Packet<ClientGamePacketListener> getUpdatePacket() {
        return ClientboundBlockEntityDataPacket.create(this);
    }
    @Override
    public CompoundTag getUpdateTag() {
        return this.saveWithoutMetadata();
    }
    @Override
    public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
        super.onDataPacket(net, pkt);
        load(pkt.getTag());
    }
    @Override
    public void handleUpdateTag(CompoundTag tag) {
        super.handleUpdateTag(tag);
    }

    public int getSlot0Price() {
        return data.get(0); //this is not getting me the value
        //return slot0Price; //neither this
    }
}

 

 

public class VendingMachineMenu extends AbstractContainerMenu {

	public final VendingMachineBlockEntity blockEntity;
    private final Level level;
    private final ContainerData data;

    // Client constructor
    public VendingMachineMenu(int pContainerId, Inventory inv, FriendlyByteBuf extraData) {
        this(pContainerId, inv, inv.player.level.getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(Constants.VENDINGMACHINE_CONTAINERDATASIZE));
    }

    // Server constructor
    public VendingMachineMenu(int pContainerId, Inventory inv, BlockEntity entity, ContainerData data) {
        super(ModMenuTypes.VENDINGMACHINE_MENU.get(), pContainerId);
        checkContainerSize(inv, Constants.VENDINGMACHINE_TOTALSLOTS);
        blockEntity = ((VendingMachineBlockEntity) entity);
        this.level = inv.player.level;
        this.data = data;

        addPlayerInventory(inv);
        addPlayerHotbar(inv);

        this.blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(handler -> {
        	//The third and fourth numbers are the position of the slots
            // (this.addSlot(new SlotItemHandler(handler, 0, THIRD, FOURTH));)
        	//in an editing program, put your mouse above one of the slots at the top left part 
        	//(the mouse goes starting from the lightest grey pixel)
            this.addSlot(new SlotItemHandler(handler, 0, 62, 0));
            this.addSlot(new SlotItemHandler(handler, 1, 80, 0));
            this.addSlot(new SlotItemHandler(handler, 2, 98, 0));

            this.addSlot(new SlotItemHandler(handler, 3, 62, 18));
            this.addSlot(new SlotItemHandler(handler, 4, 80, 18));
            this.addSlot(new SlotItemHandler(handler, 5, 98, 18));

            this.addSlot(new SlotItemHandler(handler, 6, 62, 36));
            this.addSlot(new SlotItemHandler(handler, 7, 80, 36));
            this.addSlot(new SlotItemHandler(handler, 8, 98, 36));

            this.addSlot(new SlotItemHandler(handler, 9, 62, 54));
            this.addSlot(new SlotItemHandler(handler, 10, 80, 54));
            this.addSlot(new SlotItemHandler(handler, 11, 98, 54));

            this.addSlot(new SlotItemHandler(handler, 12, 62, 72));
            this.addSlot(new SlotItemHandler(handler, 13, 80, 72));
            this.addSlot(new SlotItemHandler(handler, 14, 98, 72));

            //for(int i = 0; i < 5; i++) { // downwards
                //for(int l = 0; l < 3; l++) { // rightwards
                    //this.addSlot(new SlotItemHandler(handler, l + i * 3 + 3, 62 + l * 18, 0 + i * 18));
                //}
            //}
        });

        addDataSlots(data);
    }

    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;

    // THIS YOU HAVE TO DEFINE!
    private static final int TE_INVENTORY_SLOT_COUNT = Constants.VENDINGMACHINE_TOTALSLOTS - 1;  // must be the number of slots you have!

    @Override
    public ItemStack quickMoveStack(Player playerIn, int index) {
        Slot sourceSlot = slots.get(index);
        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 (index < 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 (index < 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 {
            System.out.println("Invalid slotIndex:" + index);
            return ItemStack.EMPTY;
        }
        // If stack size == 0 (the entire stack was moved) set slot contents to null
        if (sourceStack.getCount() == 0) {
            sourceSlot.set(ItemStack.EMPTY);
        } else {
            sourceSlot.setChanged();
        }
        sourceSlot.onTake(playerIn, sourceStack);
        return copyOfSourceStack;
    }

    @Override
    public boolean stillValid(Player pPlayer) {
        return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()),
                pPlayer, ModBlocks.VENDING_MACHINE.get());
    }

    private final void addPlayerInventory(Inventory playerInventory) {
        for (int i = 0; i < 3; ++i) {
            for (int l = 0; l < 9; ++l) {
                this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 102 + i * 18)); //default: 122
            }
        }
    }
    private final void addPlayerHotbar(Inventory playerInventory) {
        for (int i = 0; i < 9; ++i) {
            this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 160)); //default: 180
        }
    }

    public int getPriceFromSlot(int slot) {
        return data.get(slot);
    }

    public void setSlot0Price(int price) {
        data.set(0, price);
    }
}

 

public class VendingMachineScreen extends AbstractContainerScreen<VendingMachineMenu> {

	public static final String UP_ARROW = "\u2191";
	public static final String DOWN_ARROW = "\u2193";
	public static final String LEFT_ARROW = "\u2190";
	public static final String RIGHT_ARROW = "\u2192";
	public static final ResourceLocation TEXTURE = new ResourceLocation(Constants.MOD_ID, "textures/gui/vendingmachine_gui.png");

	private final Player player;
	private Button button;
	public EditBox box;

	public VendingMachineScreen(VendingMachineMenu menu, Inventory inv, Component component) {
		super(menu, inv, component);
		this.player = inv.player;
		inventoryLabelY = -1000;
	}

	@Override
	protected void init() {
		super.init();
		this.minecraft.keyboardHandler.setSendRepeatsToGui(true);
		this.box = new EditBox(font, leftPos + 122, topPos + 15, 76, 15, TextComponent.EMPTY);
		this.box.setCanLoseFocus(false);
		this.box.setTextColor(-1);
		this.box.setTextColorUneditable(-1);
		this.box.setBordered(true);
		this.box.setMaxLength(50);
		//this.box.setSuggestion("Introduce a 4 characters password");
		this.box.setValue("");
		this.addWidget(this.box);
		this.setInitialFocus(this.box);
		this.button = addRenderableWidget(new Button(leftPos + 128, topPos + 60, 66, 20, new TextComponent("Set price"), thebutton -> {
			// slot;price
			String slot = TotisJavaUtils.removeSymbol(TotisJavaUtils.removeSpaces(TotisJavaUtils.separateBySymbol(this.box.getValue(), ";", 0)), ".");
			String price = TotisJavaUtils.removeSymbol(TotisJavaUtils.removeSpaces(TotisJavaUtils.separateBySymbol(this.box.getValue(), ";", 1)), ".");

			if (slot == null || price == null || this.box.getValue().equalsIgnoreCase("") ||
				this.box.getValue().length() < 1) return;

			if(menu.blockEntity.getItemFromSlot(Integer.parseInt(slot)).is(Items.AIR) ||
					menu.blockEntity.getItemFromSlot(Integer.parseInt(slot)).sameItem(ItemStack.EMPTY)) {
				player.sendMessage(new TextComponent(ChatFormatting.RED + "That slot does not have an item"), player.getUUID());
				return;
			}
			this.menu.setSlot0Price(Integer.parseInt(price));
			this.menu.blockEntity.getSlot0Price();
			player.sendMessage(new TextComponent(this.menu.getPriceFromSlot(0) + " is the price"), player.getUUID());

			player.sendMessage(new TextComponent(ChatFormatting.BLUE + "The item from slot " + slot + " now has a price of $" + price), player.getUUID());
			player.closeContainer();
		}));
	}

	@Override
	public void resize(Minecraft pMinecraft, int pWidth, int pHeight) {
		super.resize(pMinecraft, pWidth, pHeight);
		String s = this.box.getValue();
		this.box.setValue(s);
	}

	@Override
	public void removed() {
		super.removed();
		this.minecraft.keyboardHandler.setSendRepeatsToGui(false);
	}

	public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {
		if (pKeyCode == 256) {
			this.minecraft.player.closeContainer();
		}

		return !this.box.keyPressed(pKeyCode, pScanCode, pModifiers) && !this.box.canConsumeInput() ? super.keyPressed(pKeyCode, pScanCode, pModifiers) : true;
	}

	@Override
	protected void renderLabels(PoseStack p_97808_, int p_97809_, int p_97810_) {
		super.renderLabels(p_97808_, p_97809_, p_97810_);
	}

	@Override
	protected void renderBg(PoseStack stack, float partialTick, int mouseX, int mouseY) {
		RenderSystem.setShader(GameRenderer::getPositionTexShader);
        RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
        RenderSystem.setShaderTexture(0, TEXTURE);
        //int x = (width - imageWidth) / 2;
        //int y = (height - imageHeight) / 2;
		int x = this.leftPos;
		int y = this.topPos;

        this.blit(stack, x, y - 20, 0, 0, imageWidth + 30, imageHeight + 36);
	}
	
	@Override
    public void render(PoseStack pPoseStack, int mouseX, int mouseY, float delta) {
        renderBackground(pPoseStack);
        super.render(pPoseStack, mouseX, mouseY, delta);
		this.renderFg(pPoseStack, mouseX, mouseY, delta);
        renderTooltip(pPoseStack, mouseX, mouseY);
    }

	public void renderFg(PoseStack pPoseStack, int pMouseX, int pMouseY, float pPartialTick) {
		this.box.render(pPoseStack, pMouseX, pMouseY, pPartialTick);
	}
}

)

Link to comment
Share on other sites

I think you will find nobody is going to read this.

Despite dumping a large amount a code in the forums you still don't include important information,

e.g. what is this value?


            @Override
            public int getCount() {
                return Constants.VENDINGMACHINE_CONTAINERDATASIZE;
            }

Generally, if you want help, you need to put your code on github where we can see everything (not just the bits you think are important).

The code should compile and run.

 

Better is to show some understanding, so you can point us to the relevant code you think should work instead.

Just saying "please find the bug" in some random code will likely mean busy people ignore your question as too much work.

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

32 minutes ago, warjort said:

e.g. what is this value?

That is an integer(1) because im only using 1 ContainerData

 

33 minutes ago, warjort said:

Despite dumping a large amount a code in the forums you still don't include important information

Im not very good to explain myself so i tried to put almost all the code (not the smartest idea) and it didnt result well

Basically, i had to use a ContainerData to get the integer value (private int slot0Price = 0;), so for example if i press a created button and get/set the integer value, it will work, but if i right click the block and try to do the same it wont work

@Override
    public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos,
                                 Player player, InteractionHand pHand, BlockHitResult pHit) {
        ItemStack stack = player.getItemInHand(pHand);
        VendingMachineBlockEntity entity = (VendingMachineBlockEntity) pLevel.getBlockEntity(pPos);

        if(!pLevel.isClientSide) {
            player.sendmessage(entity.getSlot0Price(), blahblah);
        }
        return super.use(pState, pLevel, pPos, player, pHand, pHit);
    }

With "it wont work" i mean that when i change the integer with the screen (button and editbox) it sets the value to anything i want or gets it, but as i said it doesnt do it directly from the block entity

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.



×
×
  • Create New...

Important Information

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