[SPIGOT-7286] Asynchronous entity add! Created: 05/Mar/23  Updated: 25/Dec/24  Resolved: 05/Mar/23

Status: Closed
Project: Spigot
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Developer Team Assignee: Unassigned
Resolution: Invalid Votes: 0
Labels: Drop, Items

Attachments: Java Source File ItemDroper.java    
Version: 1.19.2
Guidelines Read: Yes

 Description   

My code: package net.malejmarabu.gs.games.function;

import net.malejmarabu.gs.addtional.Yamls;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Item;
import org.bukkit.inventory.ItemStack;

import java.util.*;

public class ItemDroper

{      private Yamls yml;      public HashMap<Location, Integer> levels = new HashMap<>();      public HashMap<String, ArrayList<Location>> maps = new HashMap<>();      private HashMap<Location, Long> lastgen = new HashMap<>();      Timer timer = new Timer();      double[] brint = \{1,0.75,0.5,0.25,0.125}

;
     double[] iint = {4,3,2.5,2,1.5};
     double[] glint = {9,7,6,5,3};
     double[] diint = {12,10,8,6,5};
     double[] emint = {20,16,12,8,6};

 

     public void ItemGenerator(Location loc, Material material, int level) {
         World world = loc.getWorld();
         Block block = loc.getBlock();
         Long last = null;
         Long cur = System.currentTimeMillis();
         double interval = 0;
         if (material.equals(Material.BROWN_CONCRETE))

{              interval = brint[level];          }

         if (material.equals(Material.IRON_BLOCK))

{              interval = irint[level];          }

         if (material.equals(Material.GOLD_BLOCK))

{              interval = glint[level];          }

         if (material.equals(Material.DIAMOND_BLOCK))

{              interval = diint[level];          }

         if (material.equals(Material.EMERALD_BLOCK))

{              interval = emint[level];          }

         if(!lastgen.containsKey(loc))

{              lastgen.put(loc, cur);          }

         last = lastgen.get(loc);

         //if (last - cur >= interval * 1000) {
             if (material.equals(Material.DIAMOND_BLOCK))

{                  ItemStack items = new ItemStack(Material.DIAMOND, 1);                  Item item = world.dropItem(block.getLocation(), items);              }

             if (material.equals(Material.GOLD_BLOCK))

{                  ItemStack items = new ItemStack(Material.GOLD_INGOT, 1);                  Item item = world.dropItem(block.getLocation(), items);              }

             if (material.equals(Material.IRON_BLOCK))

{                  ItemStack items = new ItemStack(Material.IRON_INGOT, 1);                  Item item = world.dropItem(block.getLocation(), items);              }

             if (material.equals(Material.BROWN_CONCRETE))

{                  ItemStack items = new ItemStack(Material.BRICK, 1);                  Item item = world.dropItem(block.getLocation(), items);                  item.setCustomName("Bronze");              }

             if (material.equals(Material.EMERALD_BLOCK))

{                  ItemStack items = new ItemStack(Material.EMERALD, 1);                  Item item = world.dropItem(block.getLocation(), items);              }

             //Bukkit.getLogger().info("At position: " + loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ() + " from material: " + material + " here drop item");
             lastgen.put(loc, cur);
         //}
     }

     public void setup() {
         Bukkit.getLogger().info("Item generation starts");

         this.yml = new Yamls();
         for(int i = 0; i <= yml.getGens().getInt("Rows"); i++) {
             //Bukkit.getLogger().info(Integer.toString);

                 //Location loc = new Location(Bukkit.getWorld(yml.getGens().getString("Generators." + i + ".loc.world")), yml.getGens().getDouble("Generators." + i + ".loc.x"), yml.getGens().getDouble("Generators." + i + ".loc.y"), yml.getGens().getDouble("Generators." + i + ".loc .of"));
             Location loc = yml.getGens().getLocation("Generators." + i + ".loc");
             String map = yml.getGens().getString("Generators." + i + ".map");
                 if (loc == null)

{                      //yml.getGens().set("Rows", i);                  }

else {
                     if (!maps.containsKey(map))

{                          maps.put(map, new ArrayList<>());                      }

                     maps.get(map).add(loc);
                     levels.put(loc, 1);

             }
         }

         Timer timer = new Timer();
         TimerTask task = new TimerTask() {
             @Override
             public void run() {
                 yml = new Yamls();
                 for(int i = 0; i <= yml.getGens().getInt("Rows"); i++) {
                     //Bukkit.getLogger().info(Integer.toString);
                     //Location loc = new Location(Bukkit.getWorld(yml.getGens().getString("Generators." + i + ".loc.world")), yml.getGens().getDouble("Generators." + i + ".loc.x"), yml.getGens().getDouble("Generators." + i + ".loc.y"), yml.getGens().getDouble("Generators." + i + ".loc .of"));
                     Location loc = yml.getGens().getLocation("Generators." + i + ".loc");
                     Material material = Material.getMaterial(yml.getGens().getString("Generators." + i + ".material"));
                     if (loc == null)

{                         //yml.getGens().set("Rows", i);                      }

else {
                         //Bukkit.getLogger().info("At position: " + loc.getBlockX() + " " + loc.getBlockY() + " " + loc.getBlockZ() + " from material: " + material + " here drop item");
                         int level = 0;
                         if(!levels.containsKey(loc))

{                              level = 1;                          }

else

{                              level = levels.get(loc);                          }

                         ItemGenerator(loc, material, level);
                     }
                 }
             }
         };
         timer.scheduleAtFixedRate(task, 0, 10);
         this.timer = timer;
     }

     public void stop()

{          timer.cancel();      }

}

 

The error is that the timer stops and suddenly it prints this error:
[16:48:15] [Timer-62/WARN]: Exception in thread "Timer-62" java.lang.IllegalStateException: Asynchronous entity add!
[16:48:15] [Timer-62/WARN]: at org.spigotmc.AsyncCatcher.catchOp(AsyncCatcher.java:14)
[16:48:15] [Timer-62/WARN]: at net.minecraft.server.level.WorldServer.addEntity(WorldServer.java:1017)
[16:48:15] [Timer-62/WARN]: at net.minecraft.server.level.WorldServer.addFreshEntity(WorldServer.java:960)
[16:48:15] [Timer-62/WARN]: at org.bukkit.craftbukkit.v1_19_R1.CraftWorld.dropItem(CraftWorld.java:491)
[16:48:15] [Timer-62/WARN]: at org.bukkit.craftbukkit.v1_19_R1.CraftWorld.dropItem(CraftWorld.java:480)
[16:48:15] [Timer-62/WARN]: at net.malejmarabu.gs.games.function.ItemDroper.ItemGenerator(ItemDroper.java:76)
[16:48:15] [Timer-62/WARN]: at net.malejmarabu.gs.games.function.ItemDroper$1.run(ItemDroper.java:129)
[16:48:15] [Timer-62/WARN]: at java.base/java.util.TimerThread.mainLoop(Timer.java:566)
[16:48:15] [Timer-62/WARN]: at java.base/java.util.TimerThread.run(Timer.java:516)

I don't know how to fix it.



 Comments   
Comment by Developer Team [ 05/Mar/23 ]

Thanks

Comment by Black Hole [ 05/Mar/23 ]

For help using the Bukkit scheduler, please ask on the Spigot forums.

Comment by FreeSoccerHDX [ 05/Mar/23 ]

Like the exception says you cant add entities to the world from another thread then the main-thread.
You use the Java-Timer and not der Bukkit.getScheduler() to run Main-Thread-Sync stuff like that^^

The following Call is the Problem:

Item item = world.dropItem(block.getLocation(), items); 

Option 1 is to use the Bukkit-Scheduler for all
Option 2 is to call only the dropItem in Bukkit-Scheduler

BukkitScheduler

Generated at Tue Apr 22 03:43:27 UTC 2025 using Jira 10.3.5#10030005-sha1:190c783f2bd6c69cd5accdb70f97e48812a78d14.