Solved Run code for all entities inside saved locations every 5 seconds

Discussion in 'Spigot Plugin Development' started by astaspasta, Apr 1, 2020.

  1. Hello everyone, I want to run some code for every saved location I have but i am not sure how that would be done without making the server crash.

    I used to use PlayerMoveEvent and run the same code every time a player moved a whole block and that was fine until now. Now I also need to run the same code for LivingEntities but there is no EntityMoveEvent since it would crash the server. So I made the following code to test if any living entity in a few locations which would run every 5 seconds.

    Code (Text):

            Bukkit.getScheduler().scheduleSyncRepeatingTask(pl, new Runnable() {
             
                public void run() {
                    if (enableMobs) {
                        for (CustomPortal portal : portals) {
                            if (portalLocations.getLocations(portal)==null) continue;
                            for (World world : portalLocations.getLocations(portal).keySet()) {
                                for (Location loc : portalLocations.getLocations(portal, world)) {
                                    for (Entity en : world.getNearbyEntities(loc, 1,1,1)) {
                                        if (!(en instanceof LivingEntity)) continue;
                                        if (isOnTimer((LivingEntity) en) || portalListeners.isOnHold((LivingEntity) en)) continue;
                                        addToTimer((LivingEntity) en, portal);
                                    }
                                }
                            }
                        }
                    }
                }
            }, 100,100);

     
    But that wouldn't be good for the server if the server many locations saved. Would it help if it was like that?
    Code (Text):
         
    public SavedLocation(Location location) {
                Bukkit.getScheduler().scheduleSyncRepeatingTask(pl, new Runnable() {
                 
                    public void run() {
                        if (enableMobs) {
                            for (Entity en : location.getWorld().getNearbyEntities(location, 1,1,1)) {
                                if (!(en instanceof LivingEntity)) continue;
                                if (isOnTimer((LivingEntity) en) || portalListeners.isOnHold((LivingEntity) en)) continue;
                                addToTimer((LivingEntity) en, portal);
                            }
                        }
                    }
                }, 100,100);
            }
     
    Is there any way it could be done? How does minecraft's nether portal blocks check if there are entities inside them

    Thanks for the help in advance
     
  2. Managing many entities based on there location will never be really good for the server, but the greatest way to manage it is to check every time all location's nearby entities... There isn't many other solutions...
     
  3. Would it be better if every location checked for entities every 20 ticks or use a for loop to go through every location every 100 ticks
     
  4. the second option, separating it will use more resources, but may help TPS if the checks are done on separate thread (which I don't think can be done here)
     
  5. drives_a_ford

    Moderator

    If you don't need this information every tick, then you can simply spread out the work over multiple ticks. For instance, you could have a task running for each world at different ticks. Of course, if you have more worlds than there is ticks between when you need this information, this wouldn't really work.

    Also, unless you're manually loading both sides of the portal, I'd suggest checking if the portal (on either side) is in a loaded chunk before continuing with the rest of the code. There's no need to look for entities near a portal that's not loaded, is there?

    Building on the latter, I'd use the ChunkLoadEvent and ChunkUnloadEvent to keep track of (in a different collection) which portals (or which ends of portals) are in loaded chunks. That way, when it comes time to iterate over them, you'll only iterate over ones that are in loaded chunks.
     
    • Winner Winner x 1
  6. I was checking if the chunk was loaded but didn't think of running the repeating task on chunk load event and stop it on unload. I guess I'll go with that. Thanks for the help everyone