Solved Ticks massively dropping

Discussion in 'Spigot Plugin Development' started by Lifeonblack, Jun 12, 2021.

  1. Hello so I have backpack which has multi pages save with HashMap

    so it looks like this
    Code (Java):
    HashMap<Integer, ItemStack[]> contentMap;

    and I'm trying to put all of the items directly to the backpack checking what page is available to have the item, if they are in the last page and still not available give it to player's inventory.
    Code (Java):
    public void addItems(List<ItemStack> itemStack, Player owner) {
        for (int i = 1; i <= backpack.getLevel(); i++) {
                Inventory inventory = backpack.getInventory(i);
                if(inventory.firstEmpty() == -1) {
                    continue;
                }
                HashMap<Integer, ItemStack> hashMap = inventory.addItem(itemStack.toArray(new ItemStack[0]));
                if (hashMap.isEmpty()) {
                    backpack.saveInventory(i, inventory.getContents());
                    itemStack.clear();
                    break;
                }
                backpack.saveInventory(i, inventory.getContents());
                itemStack.clear();
                itemStack.addAll(hashMap.values());
                if(i == backpack.getLevel()) {
                    HashMap<Integer, ItemStack> item = owner.getInventory().addItem(itemStack.toArray(new ItemStack[0]));
                    if(!item.isEmpty()) {
                        Bukkit.getPluginManager().callEvent(new FullInventoryEvent(owner, new ArrayList<>(item.values()).get(0)));
                    }
                }
            }
    }
    saveInventory will just save the contents to the map, The problem is using this method is making the cpu usage overloaded which crashes the server. any idea what's the best method?
     
  2. Try running it on a separate thread.
     
    #2 Dolphin2410, Jun 12, 2021
    Last edited: Jun 12, 2021
  3. What happens is this task is heavy for your server so it stops from running until this task is completed (sync code). What you want, as mentioned above, is to run the heavy task in an async thread. You can use the BukkitRunnable to achieve this.

    Btw instead of doing this:

    Code (Java):
    if (hashMap.isEmpty()) {
        backpack.saveInventory(i, inventory.getContents());
        itemStack.clear();
        break;
    }
    backpack.saveInventory(i, inventory.getContents());
    itemStack.clear();
    You should do this (DRY - dont repeat yourself):

    Code (Java):
    backpack.saveInventory(i, inventory.getContents());
    itemStack.clear();
    if (hashMap.isEmpty()) {
        break;
    }
     
  4. yeah I know that, I'm just testing stuff so it is hardcoded I'll change it afterwards. But bear in mind that each time player mine this method calls so I don't think calling or running a async task will solve this cause player mines faster what more there's bunch of players that will mine.
     
  5. not crashing anymore and have 20 tps for myself haven't tested with players above 20.
     
  6. running async will solve this issue... this task is executed too much on the main thread causing the thread to hold before continuing
     
  7. it run asyc task each time player mine a block, imagine mining 5-10 blocks per second. Also I tried this earlier and it brings me to 10 TPS.
     
  8. so you will have 5-10 different threads, whats wrong with this? maybe this isnt the best way to handle what you want then, 5-10 I/O operations per second seem like a lot

    You do realize that what the other guy suggested is also running it async right? so you went from 20 fps to 10 fps?
     
    #8 Maxx_Qc, Jun 12, 2021
    Last edited: Jun 12, 2021
  9. Before using async code, do you need to add the same items in every level's inventory? All the results of each level's inventory will be the same. If you do, you can use inventory.getContents() and use inventory.set contents for the other ones.
     
  10. The difference is you're creating each time a async task every time u mine a block. compare to what I'm doing right now it is only 1 async task not (bukkit task) and are saved to Queues list which runs every after 5 milliseconds.
     
  11. only 1 page
     
  12. Then check for a valid spot while looping for each inventory and put it there, not directly into the player's inventory. What you are doing is looping the same thing over multiple times, and that might be the reason it crashes the server.
     
  13. check the method closely, if the items to add is empty then it is going to player's inventory instead.
     
  14. Also, I don't think this is a good idea. For example, you can put an oak log where a stack is not filled yet.
    Code (Java):
                if(inventory.firstEmpty() == -1) {
                    continue;
                }
     
  15. Yeah I know, this is outdated code. I just wanna know how to make it faster or how to handle tasks correctly.
     
  16. Sorry. I think running it like this
    Code (Text):
    new Thread(){
       @Override
       public void run(){
          /* Your code */
       }
    }.start()
    or as @Maxx_Qc said
    Code (Text):
    new BukkitRunnable(){
       @Override
       public void run(){
          /* Your code */
       }
    }.runTaskAsynchronously(plugin);
    Is the best I can think of.
     
  17. Thankss for you guys, found a solution here : https://www.spigotmc.org/threads/gu...-how-to-handle-heavy-splittable-tasks.409003/