Trouble teleporting non-player entities between worlds

Recently I have been developing a plugin allowing players to teleport any kind of entity anywhere in a server.

I have a problem when I attempt to teleport a non-player entity from one world to another using the entity.teleport(Location<World>) method. Players can be teleported fairly seamlessly between worlds, and non-player entities can be teleported around in the same world just fine. But when I teleport a non-player entity into another world, the entity will vanish. I have checked the entity’s location using entity.getLocation() after the teleport and the position is changed correctly, but the world remains the same world that the entity was teleported from. Furthermore, when I go to the reported location that entity.getLocation() says the entity is at, the entity is gone. I have checked the area for the teleported entity in MCEdit but was unable to find it.

Back when I wrote this plugin for Bukkit, I faced the same problems. The main difference between Bukkit’s behavior and Sponge’s behavior is that in Bukkit the entities could be found at the position they were supposed to be teleported to, but in the world they were supposed to be teleported from. I solved the problem in my Bukkit plugin by killing the entity in the old world and copying the data to an entity spawned in the new world.

I have tried the same approach I used in my Bukkit plugin in my Sponge plugin, but have encountered problems with it (spawn condition constraints like being unable to spawn a minecart on the ground or in a block, and some weird effects when automatically remounting a teleported player onto the teleported entity, but that might be unrelated). There might have been some problems with my Sponge version of this solution. For example: I used entity.toContainer() and created the new entity from the returned DataContainer, but I am not sure if that is a good idea.

In short: I am searching for a way to teleport non-player entities from one world to any location in another world without having to worry about de-sync, the teleported entity getting lost along the way, satisfying spawn conditions, or defining custom cases for every entity type to copy the entity’s data to a newly spawned one.

Any help would be appreciated.
Thanks in advance. :slight_smile:

Have you tried setLocation?

I know this method exists for Player entities, but it should also work on other entities.

Yes I have tried using Entity.setLocation(Location<World>). The problem is when I use this method, the non-player entity will vanish. A check using Entity.getLocation() right after teleportation will return a Location<World> with the new correct position, but with the old world that the entity was supposed to be teleported from. Even stranger is when I go to that location, there is no entity there at all.

I may be just using the Entity.setLocation() method wrong. If you have been able to teleport a non-player entity from one world to another, I would love to see your code!

Thank you for your suggestion! :slight_smile:

Are you sure that the target location is loaded? IIRC, setLocation may not actually load the chunks for non-player entities.

Loading chunks before using setLocation() doesn’t appear to have any effect. The teleported entity continues to be moved to the correct position but in the world it was supposed to be teleported from.

I have been using Chunk.loadChunk(boolean). I am not sure if that is the right way to load chunks though.

Thanks for your help. :slight_smile:

Ive always had a problem of getting unloaded chunk objects. So i load the chunks though the world because i know it works. Have a go doing it this way

Location<World> telTo;
Vector3I chunkPos = telTo.getChunkPos();
telTo.getExtent().loadChunk(chunkPos, true);

That will load the chunk for you, it does work however i have only teleported entities on the same world when testing it.

Also have you tried this

Entity entity;
Location<World> loc;
entity.transferToWorld(loc.getExtent().getUnquieId(), loc.getBlockPos());

I know it is used for unloaded worlds, but it says it is equivalent to

setTransform(); 

But its worth a try right

setLocation should be fixed now

Thank you. The problem is fixed in SpongeForge and SpongeVanilla.

However, there does seem to be a little bit of de-sync when teleporting a player riding another entity in SpongeForge, and I am having a little bit of trouble remounting the player onto the ridden entity in SpongeVanilla. But those are different problems from what I asked about.

Thank you so much!