"Wrong location!" used when an object is added to a piece that it should not be in its coordinates.
Here where (in World.java ) the event is fired (well, in fact, there are several other places, but this is the one used by the players among other objects):
/** * Called when an entity is spawned in the world. This includes players. */ public boolean spawnEntityInWorld(Entity p_72838_1_) { // do not drop any items while restoring blocksnapshots. Prevents dupes if (!this.isRemote && (p_72838_1_ == null || (p_72838_1_ instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false; int i = MathHelper.floor_double(p_72838_1_.posX / 16.0D); int j = MathHelper.floor_double(p_72838_1_.posZ / 16.0D); boolean flag = p_72838_1_.forceSpawn; if (p_72838_1_ instanceof EntityPlayer) { flag = true; } if (!flag && !this.isChunkLoaded(i, j, true)) { return false; } else { if (p_72838_1_ instanceof EntityPlayer) { EntityPlayer entityplayer = (EntityPlayer)p_72838_1_; this.playerEntities.add(entityplayer); this.updateAllPlayersSleepingFlag(); } if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_72838_1_, this)) && !flag) return false; this.getChunkFromChunkCoords(i, j).addEntity(p_72838_1_); this.loadedEntityList.add(p_72838_1_); this.onEntityAdded(p_72838_1_); return true; } }
Please note that i and j (piece coordinates) do not change after updating the playerโs location. Therefore, when Chunk.addEntity is Chunk.addEntity (see below), everything does not work:
public void addEntity(Entity entityIn) { this.hasEntities = true; int i = MathHelper.floor_double(entityIn.posX / 16.0D); int j = MathHelper.floor_double(entityIn.posZ / 16.0D); if (i != this.xPosition || j != this.zPosition) { logger.warn("Wrong location! (" + i + ", " + j + ") should be (" + this.xPosition + ", " + this.zPosition + "), " + entityIn, new Object[] {entityIn}); entityIn.setDead(); }
It kills the player.
I'm not quite sure why it works for the first time. It will work whenever you enter the same block as the one to which you would be teleported, so if you log out when you are in the wrong place, you will log in the next time.
Before proceeding with the fix, a few more notes:
- You do not need to do null validation with an instance -
null will never pass an instance validation. - (At least according to CommandTeleport), you need to teleport
EntityPlayerMP differently using EntityPlayerMP.playerNetServerHandler.setPlayerLocation .
To fix this, you need to postpone teleportation by 1 tick. I'm not quite sure what the canonical forge method is for this, but something like this should work:
List<Entity> playersToTeleport = new ArrayList<Entity>(); @SubscribeEvent public void onEntityJoinWorld(EntityJoinWorldEvent event) { if (event.entity instanceof EntityPlayer && !event.entity.worldObj.isRemote) { playersToTeleport.add(event.entity); } } @SubscribeEvent public void teleportEntiesOnWorldTick(TickEvent.WorldTickEvent event) {
If you need to change the position in which the player will, and will not always enter these specific coordinates, here is one way:
@SubscribeEvent public void onEntityJoinWorld(EntityJoinWorldEvent event) { if (event.entity instanceof EntityPlayer && !event.entity.worldObj.isRemote) { queueTeleportNextTick(event.entity, Math.random() * 200 - 100, 73, Math.random() * 200 - 100, 0, 0); } } private List<TeleportInfo> queuedTeleports = new ArrayList<TeleportInfo>(); private static class TeleportInfo { public TeleportInfo(Entity entity, double x, double y, double z, float yaw, float pitch) { this.entity = entity; this.x = x; this.y = y; this.z = z; this.yaw = yaw; this.pitch = pitch; } public final Entity entity; public final double x; public final double y; public final double z; public final float yaw; public final float pitch; } public void queueTeleportNextTick(Entity entity, double x, double y, double z, float yaw, float pitch) { System.out.printf("Preparing to teleport %s to %f, %f, %f%n", entity, x, y, z); queuedTeleports.add(new TeleportInfo(entity, x, y, z, yaw, pitch)); } @SubscribeEvent public void teleportEntiesOnWorldTick(TickEvent.WorldTickEvent event) {
Also note that to use TickEvent you need to register on a separate bus than to use with EntityJoinWorldEvent , so to fully register the events used here, you must do this:
MinecraftForge.EVENT_BUS.register(this); FMLCommonHandler.instance().bus().register(this);