Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.16.5] Synchronize when inventory changes on screen


Zemelua
 Share

Recommended Posts

I have a backpack item with ItemStackHandler capability. A player can change the item's inventory on screen. The container gets the ItemStackHandler capability from the backpack in the player's chest slot and dynamically changes the inventory. so it needs to be synchronized with the client backpack when the container is opened or the inventory changes. How do I use packets to synchronize the server ItemStack capability with the client ItemStack capability?

My code is here .

Edited by Zemelua
Link to comment
Share on other sites

15 minutes ago, Zemelua said:

But in fact it is not saved.

What do you mean by this?

15 minutes ago, Zemelua said:

When is the container and screen synced?

All the time. The inventory slots are checked for changes every tick on the server and sent to the client if they change. The client communicates any slot interactions to the server as well.

Link to comment
Share on other sites

2 hours ago, diesieben07 said:

What do you mean by this?

My explanation was insufficient. The problem I'm having is that if I change the chest backpack with the BelongingsUMUPlayerContainer open, its contents will appear in the backpack slot. However, if I make changes to the backpack slot in that state, the changes are not saved when I close the container. When I reopen it, it will return to the state before I made the change.

 

2 hours ago, loordgek said:

what are you doing here ?

In AbstractBelongingSlot, unlike the SlotItemHandler class, itemHandler field is dynamic (not final). When SlotItemHandler class references an itemHandler, it's basically via getItemHandler(), so I can override it to return a dynamic inventory. However, some methods that are not related to the inventory contents refer directly to the itemHandler field. In other words, the itemHandler field is fine with dynamic inventory, but I'm just passing another baseItemHandler to get some elements. Its contents are not used. You don't have to worry about it.

Link to comment
Share on other sites

after a bit of testing i found the problem

this.player.getItemStackFromSlot(EquipmentSlotType.CHEST).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(new ItemStackHandler(36)

.orElse(new ItemStackHandler(36) < that is the problem

NEVER EVER do that.

you should never return a new object in .orElse

Edited by loordgek
Link to comment
Share on other sites

fixed

here you are trying to get your capablilty from your backpack w/ no side(null)

https://github.com/Zemelua/UMU-Mod/blob/main/src/main/java/io/github/zemelua/umumod/inventory/container/BelongingsUMUPlayerContainer.java#L61

here you check if there is no side(null)

https://github.com/Zemelua/UMU-Mod/blob/main/src/main/java/io/github/zemelua/umumod/capability/FunctionalBackpackCapabilityProvider.java#L29

so you never get the capablilty

use ifPresent instead of orElse

so .ifPresent(add the slots in here)

Link to comment
Share on other sites

10 hours ago, loordgek said:

.orElse(new ItemStackHandler(36) < that is the problem

I fixed. Backpacks should always have Capability.

.orElseThrow(() -> new IllegalStateException("Backpack inventory is Empty!"))

 

9 hours ago, loordgek said:

so you never get the capablilty

It's confusing, but there are two types, Backpack and Functional Backpack, and Backpack doesn't require a side argument. In the test, I used only Backpack, so there was no problem.

 

I've solved these issues, but I'm still not solving the issue where inventory isn't applied ...

https://github.com/Zemelua/UMU-Mod/blob/main/src/main/java/io/github/zemelua/umumod/inventory/container/AbstractUMUPlayerContainer.java#L37

It's possible that there's a problem with the arguments I'm passing on this line, but I'm not sure what's wrong. The method of implementing IContainerListener and updating the inventory as a listener also didn't work. (It looks like I need to update backpack's inventory before slotClick() is done.)

Link to comment
Share on other sites

1. Prepare two Backpacks.
2. With one Backpack on your chest, open the BelongingsScreen.
3. In the BelongingsScreen, remove the equipped Backpack and equip another one.
4. Place any items in the backpack slot.
5. Close the Screen as it is.
6. When you open the Screen again with the second Backpack equipped, the items you should have put in are missing.

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.

Guest
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.

 Share



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • thankyou for your input. I grab the GUI object on the GuiOpenEvent and the on the world tick event i keep checking it until the inventory loads. this successfully grabs the chest inventory from the client side. here is my final code. package com.example.examplemod; import java.util.ArrayList; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket; import net.minecraft.world.InteractionHand; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.*; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.event.GuiContainerEvent; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fmlclient.registry.ClientRegistry; @Mod.EventBusSubscriber public class ForgeEventHandler { private static ArrayList<BlockPos> homeBase = new ArrayList<BlockPos>(); private static Boolean pressed = false; public static final KeyMapping keyBinding = new KeyMapping("pam SETUP", 79, "PAM"); private static Screen GUI = null; @SubscribeEvent public static void setup(FMLClientSetupEvent event) { ClientRegistry.registerKeyBinding(keyBinding); } @SubscribeEvent public static void updatePlayer(TickEvent.PlayerTickEvent event) { /*if(event.player.canEat(false)){ for(ItemStack inventoryStack : event.player.getInventory().items){ if (inventoryStack.isEdible()) { ForgeEventFactory.onItemUseStart(event.player, inventoryStack, 0); ItemStack result = inventoryStack.getItem().finishUsingItem(inventoryStack, event.player.getCommandSenderWorld(), event.player); ForgeEventFactory.onItemUseFinish(event.player, inventoryStack, 0, result); if (!event.player.canEat(false)) { break; } } } }*/ if (keyBinding.isDown() && !pressed) { pressed = true; homeBase.add(((BlockHitResult) Minecraft.getInstance().player.pick(20.0D, 0.0F, false)).getBlockPos()); System.out.println("set postion"); if (homeBase.size()>=2) { System.out.println("opening container"); openBlock(detectContainers(homeBase).get(0)); homeBase.clear(); } if (!keyBinding.isDown()) { pressed=false; } } } @SubscribeEvent public static void updateWorld(TickEvent.WorldTickEvent event) { if (GUI != null) { if (GUI instanceof AbstractContainerScreen) { AbstractContainerScreen container = ((AbstractContainerScreen)GUI); NonNullList<Slot> slots = container.getMenu().slots; for (int i=0; i<slots.size();i++) { ItemStack temp = slots.get(i).getItem(); System.out.print(temp.getDisplayName().getString()+" | "); } System.out.println(""); GUI = null; } } } @SubscribeEvent public static void openChest(GuiOpenEvent event) { GUI = event.getGui(); } private static ArrayList<Vec3> detectContainers(ArrayList<BlockPos> homebase) { ArrayList<Vec3> chests = new ArrayList<Vec3>(); int x = homebase.get(1).getX()-homebase.get(0).getX(); int y = homebase.get(1).getY()-homebase.get(0).getY(); int z = homebase.get(1).getZ()-homebase.get(0).getZ(); for (int i=homebase.get(0).getX();i!=homebase.get(1).getX();i+=Math.signum(x)) { for (int j=homebase.get(0).getY();j!=homebase.get(1).getY();j+=Math.signum(y)) { for (int k=homebase.get(0).getZ();k!=homebase.get(1).getZ();k+=Math.signum(z)) { BlockEntity temp = Minecraft.getInstance().level.getBlockEntity(new BlockPos(i,j,k)); if (temp instanceof RandomizableContainerBlockEntity && !(temp instanceof HopperBlockEntity)) { chests.add(new Vec3(i,j,k)); } } } } return chests; } @SuppressWarnings("resource") private static void openBlock(Vec3 blockPos){ /*BlockHitResult hit = new BlockHitResult(blockPos, Direction.DOWN, new BlockPos(blockPos), false);*/ BlockHitResult hit = (BlockHitResult) Minecraft.getInstance().player.pick(20.0D, 0.0F, false); Minecraft.getInstance().getConnection().send(new ServerboundUseItemOnPacket(InteractionHand.MAIN_HAND,hit)); } }  
    • Yea, you shouldn't be starting the Minecraft server. That starts a vanilla one. You need to start the forge jar and I think you need to use the bat file that gets generated instead of just opening the jar.
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.