Jump to content
  • Home
  • Files
  • Docs
Topics
  • All Content

  • This Topic
  • This Forum

  • Advanced Search
  • Existing user? Sign In  

    Sign In



    • Not recommended on shared computers


    • Forgot your password?

  • Sign Up
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.16.3] Sync inventory changes
Currently Supported: 1.16.X (Latest) and 1.15.X (LTS)
Sign in to follow this  
Followers 2
JimiIT92

[1.16.3] Sync inventory changes

By JimiIT92, October 8, 2020 in Modder Support

  • Reply to this topic
  • Start new topic

Recommended Posts

JimiIT92    20

JimiIT92

JimiIT92    20

  • Dragon Slayer
  • JimiIT92
  • Members
  • 20
  • 745 posts
Posted October 8, 2020

I am attempting to create a mod that adds the new 1.17 Bundles. To do this I listen to the mouse click event on an Inventory slot. Now, inside the Player container everything works fine, if I am in creative mode. However if I use the Bundle when another container is open (for example a Chest), or if the player is just in survival mode, whatever changes I made to the inventory won't be reflected as soon as I close the container or update it somehow.
For example, I have this survival inventory
image.png.0c446d58aef6500fe0cf25ba605a04ce.png

I then take the Bundle (the item near the crafting table) and click on the stack of 40 stone. When I click, only 32 items of the stack will go inside the bundle. The other items will remain inside the Inventory

image.png.6c7ebc9db05eb186089a2c92ffa52af1.pngimage.png.dd7cc661b535600a65768b1acc417df5.png

As you can see everything is right, but as soon as I click the Bundle again, I got this situation (if I close and open again the Inventory I still see the stone stack been shrinked to 8)

image.png.d98f8f7e17c5843c2b1ce352538ad48b.png

 

 

This is the method I use to add the Items to the Bundle
 

public static void addItemStackToBundle(ItemStack bundle, ItemStack stack, PlayerEntity player, Container container) {
  if(!isBundle(bundle) || isFull(bundle) || isBundle(stack)) {
    return;
  }
  ItemStack stackToAdd = stack.copy();
  int maxItemsToAdd = bundle.getMaxDamage() - getBundleItemsCount(bundle);
  stackToAdd.setCount(Math.min(getMaxStackSizeForBundleToInsert(stackToAdd), maxItemsToAdd));
  CompoundNBT bundleTag = bundle.getOrCreateTag();
  ListNBT items = bundleTag.getList(BundleResources.BUNDLE_ITEMS_LIST_NBT_RESOURCE_LOCATION, Constants.NBT.TAG_COMPOUND);
  CompoundNBT itemStackNbt = new CompoundNBT();
  ItemStack stackFromBundle = getItemStackFor(bundle, stackToAdd.getItem());
  int index = getItemStackIndex(bundle, stackFromBundle);
  if(!stackFromBundle.isEmpty()) {
    stackToAdd.setCount(Math.min(stackToAdd.getCount(), getMaxStackSizeForBundle(stack) - stackFromBundle.getCount()));
  }
  if(index != -1) {
    stackFromBundle.setCount(stackFromBundle.getCount() + stackToAdd.getCount());
    stackFromBundle.write(itemStackNbt);
    items.remove(index);
    items.add(index, itemStackNbt);
  } else {
    stackToAdd.write(itemStackNbt);
    items.add(itemStackNbt);
  }
  bundleTag.put(BundleResources.BUNDLE_ITEMS_LIST_NBT_RESOURCE_LOCATION, items);
  bundle.setTag(bundleTag);
  stack.setCount(stack.getCount() - stackToAdd.getCount());
  bundle.setDamage(bundle.getMaxDamage() - getBundleItemsCount(bundle));
  container.detectAndSendChanges();
  player.playSound(SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 1.0F, 1.0F);
}


I pass in the Container object for the slot that has been clicked and in the end call the detectAndSendChanges method, which should sync the inventory content between client and server (as the Click event is only fired client side, all I do here won't be visible to the server until I sync). Do I need to send a custom packet to the server to sync the inventory?

  • Quote

Don't blame me if i always ask for your help. I just want to learn to be better :)

Share this post


Link to post
Share on other sites

ChampionAsh5357    165

ChampionAsh5357

ChampionAsh5357    165

  • World Shaper
  • ChampionAsh5357
  • Members
  • 165
  • 1038 posts
Posted October 9, 2020
1 hour ago, JimiIT92 said:

To do this I listen to the mouse click event on an Inventory slot.

Handling this on the wrong side. You would send the information to the server which would modify the values and affect the creative screen respectively.

1 hour ago, JimiIT92 said:

Do I need to send a custom packet to the server to sync the inventory?

Most likely as the handling would need to be custom.

  • Quote

Share this post


Link to post
Share on other sites

JimiIT92    20

JimiIT92

JimiIT92    20

  • Dragon Slayer
  • JimiIT92
  • Members
  • 20
  • 745 posts
Posted October 9, 2020

Ok, so right now I do this

@SubscribeEvent(priority = EventPriority.HIGHEST)
  public static void onMouseReleased(final GuiScreenEvent.MouseReleasedEvent event) {
  if(!event.isCanceled() && event.getGui() instanceof ContainerScreen<?>) {
    ContainerScreen<?> containerScreen = (ContainerScreen<?>)event.getGui();
    Slot slot = containerScreen.getSlotUnderMouse();
    if(slot != null && !(slot instanceof CraftingResultSlot)) {
      PlayerEntity player = Minecraft.getInstance().player;
      if(player != null) {
        ItemStack draggedItemStack = player.inventory.getItemStack();
        ItemStack slotStack = slot.getStack();
        Container container = containerScreen.getContainer();
        if(slot.canTakeStack(player) && slot.isEnabled()
           && container.canMergeSlot(draggedItemStack, slot)
           && slot.isItemValid(draggedItemStack)
           && slot.getHasStack() && event.getButton() == 0
           && BundleItemUtils.isBundle(draggedItemStack)
           && BundleItemUtils.canAddItemStackToBundle(draggedItemStack, slotStack)) {
          BundleItemUtils.addItemStackToBundle(draggedItemStack, slotStack, player, container);
          event.setResult(Event.Result.DENY);
          event.setCanceled(true);
        }
      }
    }
  }
}


From what I understand, instead of calling directly BundleItemUtils I have to send a packet to the server with all the informations I need (draggedItemStack, slotStack, player and container) and then call the addItemStackToBundle while being on the server, am I right?

  • Quote

Don't blame me if i always ask for your help. I just want to learn to be better :)

Share this post


Link to post
Share on other sites

poopoodice    118

poopoodice

poopoodice    118

  • Dragon Slayer
  • poopoodice
  • Members
  • 118
  • 928 posts
Posted October 9, 2020

Imo instead of sending stacks, you should probably send the slot numbers and let the server check then modify them.

  • Quote

Share this post


Link to post
Share on other sites

JimiIT92    20

JimiIT92

JimiIT92    20

  • Dragon Slayer
  • JimiIT92
  • Members
  • 20
  • 745 posts
Posted October 9, 2020 (edited)
2 hours ago, poopoodice said:

Imo instead of sending stacks, you should probably send the slot numbers and let the server check then modify them.

Ok, so what I'm doing now is this. In the event handle, instead of calling the BundleItemUtils, I send a message to the server
 

BundleResources.NETWORK.sendToServer(new BundleServerMessage(draggedItemStack, Math.max(slot.slotNumber, slot.getSlotIndex()), false));

 Which when handled will do this
 

private static void processMessage(BundleServerMessage message, ServerPlayerEntity playerEntity) {
        Container container = playerEntity.openContainer;
        Slot slot = container.getSlot(message.slotId);
        ItemStack slotStack = slot.getStack();
        if(message.empty) {
            BundleItemUtils.emptyBundle(message.bundle, playerEntity, container);
        } else {
            BundleItemUtils.addItemStackToBundle(message.bundle, slotStack, playerEntity, container);
            slot.putStack(slotStack);
            playerEntity.inventory.setItemStack(message.bundle);
        }
    }


But I'm still having some quarkiness where Items gets duped now. Do I need to send something to the Client? If so, what should I send to it?

Edited October 9, 2020 by JimiIT92
Updated code
  • Quote

Don't blame me if i always ask for your help. I just want to learn to be better :)

Share this post


Link to post
Share on other sites

ChampionAsh5357    165

ChampionAsh5357

ChampionAsh5357    165

  • World Shaper
  • ChampionAsh5357
  • Members
  • 165
  • 1038 posts
Posted October 9, 2020
1 hour ago, JimiIT92 said:

slot.putStack(slotStack); playerEntity.inventory.setItemStack(message.bundle);

If you're in the player container, you shouldn't need to set anything directly to the inventory. Set it only to the container slot stacks, those will update the inventory. Second, if the item is getting duplicated, you probably aren't removing the stack on click. That should be handled cliently where when you click, you send the bundle and the slot it clicks. You remove the bundle from the slot clicked in the screen, but you don't add the other stack in its place if it's not empty. Similarly on the server, you grab the stack in the slot where you clicked, put it into the bundle, and put your stack in the slot replacing the cobblestone. Please make sure that you copied the stack you're adding or else you will dupe the bundle most likely.

  • Quote

Share this post


Link to post
Share on other sites

JimiIT92    20

JimiIT92

JimiIT92    20

  • Dragon Slayer
  • JimiIT92
  • Members
  • 20
  • 745 posts
Posted October 9, 2020

Ok, I'm slowly understanding how this works. Unfortunately I've never maged the inventory directly for a case like this, where the item stack you are dragging around with you mouse will be modified when you click but not put into the inventory yet. Now I made it kinda work, by essentially doing the same operation both on the client and on the server. I already know this is bad, however I don't know how to optimize this. Plus for some reason is working fine only inside the Player container and Creative Container and other fews. If I am, for example, inside the Furnace Container and left click a Bundle, the Items will be taken out of the Bundle, but the Bundle itself won't be updated, leading to the situation where if you spam the left click you will dupe the items inside the Bundle.

I've setup a GitHub repository so you can look up at what exactly is going on, from what I understand it has to do something with the fact that I'm setting the player inventory ItemStack (which is the item stack the player is dragging with its mouse) but if I remove entirely this then it doesn't get synced :/ 
Here is the repository https://github.com/JimiIT92/BundlesMod

Please I'm really lost into this :/ 

  • Quote

Don't blame me if i always ask for your help. I just want to learn to be better :)

Share this post


Link to post
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.   Paste as plain text instead

  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.

    • Insert image from URL
×
  • Desktop
  • Tablet
  • Phone
Sign in to follow this  
Followers 2
Go To Topic Listing



  • Recently Browsing

    No registered users viewing this page.

  • Posts

    • GhostGamesFSM
      1.16 Ore generation.

      By GhostGamesFSM · Posted just now

      sorry for the txt, but thanks for the comment. I don't have a BiomeLoadingEvent, but I just have to see how I do that. When I have that I send you a message if that works.
    • HOTSAUCEMAN
      help with loading my world

      By HOTSAUCEMAN · Posted 1 minute ago

      just ran it again to get more updated logs  debug-1.log.gz
    • HOTSAUCEMAN
      help with loading my world

      By HOTSAUCEMAN · Posted 5 minutes ago

      when loading into my world it says its loading, and then changes to a dirt background with no text; i've looked at multiple threads, forums and videos but i can't find any issue similar to mine (at least on a similar version)  debug-1.log.gz
    • Beethoven92
      [1.16.5] Beacon Overwrite (Screen Error)

      By Beethoven92 · Posted 12 minutes ago

      I apologize...i misread the part where you say that your custom beacon inventory actually opens fine! Yeah, the proximity check is doing its job, the problem seems to be that when pressing the confirm button you are sending a vanilla CUpdateBeaconPacket, then handled by the server, which will check if your open container is a BeaconContainer. It would be helpful to see the complete code you have, please post a link to your repository
    • Beethoven92
      [1.16.5] How to make EnchantedBook go to Custom ItemGroup

      By Beethoven92 · Posted 30 minutes ago

      Show what you tried then. It should be "enchantment.your_mod_id.your_enchantment_id"
  • Topics

    • GhostGamesFSM
      2
      1.16 Ore generation.

      By GhostGamesFSM
      Started 17 hours ago

    • HOTSAUCEMAN
      1
      help with loading my world

      By HOTSAUCEMAN
      Started 5 minutes ago

    • Nyko
      3
      [1.16.5] Beacon Overwrite (Screen Error)

      By Nyko
      Started Yesterday at 07:22 AM

    • samjviana
      5
      [1.16.5] How to make EnchantedBook go to Custom ItemGroup

      By samjviana
      Started Sunday at 10:00 PM

    • DrigglyEast
      0
      Fatally Missing Registry Entries

      By DrigglyEast
      Started 2 hours ago

  • Who's Online (See full list)

    • GhostGamesFSM
    • Beethoven92
    • IntentScarab
    • CookieLukas
    • Tavi007
    • HOTSAUCEMAN
    • zlappedx3
    • am pro
    • Abrynos
    • vemerion
  • All Activity
  • Home
  • Mod Developer Central
  • Modder Support
  • [1.16.3] Sync inventory changes
  • Theme

Copyright © 2019 ForgeDevelopment LLC · Ads by Longitude Ads LLC Powered by Invision Community