Removing entities in unloaded chunks

Discussion in 'Spigot Plugin Development' started by AdamAdam, Aug 5, 2018.

  1. How c an I remove an entity that is in a unloaded chunk? I'm trying to remove it when the plugin disables. Because of that I can't make a task run a couple of ticks after it loaded. I've tried using NMS to remove the entity from the chunk itself but it still serializes (saves) it to the file.

    Any help?
     
  2. I don't know if this will help solve your problem, but there is a setting which prevents entities from ever getting saved when their chunk unloads: Entity.setPersistent.
    Set this to false and the entity will never end up on disk. Removing entities from unloaded chunks may be possible, but strikes me as a terrible idea.
     
  3. Create a list of entities then on ChunUnloadEvent get all the entities in the chunk and add them to the list, on disable iterate through the list and remove those entities.
     
  4. This will not remove entities which are located in unloaded chunks. Their Entity instance will no longer be valid at that point.

    Edit: I assume you meant remove them in the onDisable() function of your plugin, way after the ChunkUnloadEvent. Of course, they are still valid during chunk unload.
     
    #4 StarTux, Aug 5, 2018
    Last edited: Aug 6, 2018
  5. Oh you are right, so this may be not so efficient but you need to save the locations of the entity when the chunk unloads then load him and remove the entity, very not efficient.
     
  6. You would be better off always removing custom entities on chunk unlad, storing their location and other data and then removing them from the world. You would then have to handle the respawning on chunk load. This approach means your custom entities are never saved in the region files.
     
  7. l
    Thanks! I can just remove them when I insnert my entities because their locations will be the same.

    Thanks for all the other replies too!

    And why is it bad to remove entities when the chunk is unloaded. I can guess it would maybe cause desync in some way possibly? Just a guess probably won't but justy a guess.
     
  8. What makes you think it's bad? I guess one thing to consider is if the chunk unload is cancelled so you might want to use monitor level and ignore cancelled events.
     
  9. Chunk loading is very slow, so if your plan is to remove a large amount of entities from unloaded chunks, you have to wait until each of them was loaded so you can delete the actual entity, then save again. It's much more efficient to not save the entity in the first place.

    Plus, if the server crashes and your plugin doesn't unload properly, nobody's going to delete those entities, and the information on where they were is lost, so they will stick around permanently.
     
    • Like Like x 1
  10. How can I prevent an entity from saving though. When I register my custom entity it saves it properly.
    I don't really want to override the save method though.
     
  11. If you're on 1.13, you can call Entity#setPersistent and set it to false.
    If not, you can listen for ChunkUnloadEvent, then check if the chunk contains any of your custom entities, and call Entity#remove() right there.
     
  12. md_5

    Administrator Developer

    Only works on 1.13 though
    I think they're still valid at this point, so you could call .die() or .remove or whatever on them
     
  13. The object will still exist as a strong a reference is held but as the chunk has already been unloaded it will have been serialised, will calling the remove or die method load the chunk and removed the saved entity and unload it again?
     
  14. md_5

    Administrator Developer

    Chunks are not unloaded when the event is called - the event can be cancelled
     
  15. Sure, but as the OP wants to remove entities at plugin unload time they will not know ahead of time if/when this will happen and stopping all chunk unloading doesn't seem like a good idea.
     
  16. I didn't manage to get an entity which is on an unloaded chunk by Bukkit#getServer()#getEntity(UUID);
    It kept returning null if it's in an unloaded chunk.
     
  17. That's expected, you would have to get the entity and hold a reference to it before the chunk is unloaded. However, I'm not sure if removing the reference after chunk unload will remove it from region files and you would have to handle the fact that on chunk reload a new entity object will be created by the server yeilding the one you are holding on to useless which is why I suggested an alternative approach.
     
  18. Great! If the location remains the same you could use the World#getNearbyEntities(Location, double, double, double) method when a chunk containing that location is unloaded to get a Collection of Entity objects that you can iterate through to remove your custom entities.
     
  19. md_5

    Administrator Developer

    Yes it will obviously be null in an unloaded chunk, but it will be ok in an unloading chunk (i.e. during the event)
     
    • Agree Agree x 1
  20. I found a big problem with removing them on load again. On 1.8 they lose their custom entity instance so I can┬Ęt identify them again. I guess the best way to do it it to listen to the chunkUnloaded event. Thanks!