package jk_5.nailed.server.teleport;
import jk_5.nailed.api.player.Player;
import jk_5.nailed.api.util.Checks;
import jk_5.nailed.api.util.Location;
import jk_5.nailed.api.util.TeleportOptions;
import jk_5.nailed.api.world.Dimension;
import jk_5.nailed.api.world.World;
import jk_5.nailed.server.NailedPlatform;
import jk_5.nailed.server.player.NailedPlayer;
import jk_5.nailed.server.world.NailedWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S1DPacketEntityEffect;
import net.minecraft.network.play.server.S1FPacketSetExperience;
import net.minecraft.potion.PotionEffect;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import java.util.Collection;
public class Teleporter {
public static boolean teleportPlayer(Player player, TeleportOptions opt){
Checks.notNull(player, "player");
Checks.notNull(opt, "opt");
TeleportOptions options = opt.copy(); //We don't want to accidently modify the options object passed in, so we copy it.
World currentWorld = player.getWorld();
if(!TeleportEventFactory.isTeleportAllowed(currentWorld, opt.getDestination().getWorld(), player, options)){
return false;
}
Location location = TeleportEventFactory.alterDestination(currentWorld, opt.getDestination().getWorld(), player, options);
World destinationWorld = location.getWorld();
EntityPlayerMP entity = ((NailedPlayer) player).getEntity();
teleportEntity(currentWorld, destinationWorld, entity, location, options);
return true;
}
public static Entity teleportEntity(World currentWorld, World destinationWorld, Entity entity, Location location, TeleportOptions options){
int dimension = destinationWorld.getDimensionId();
WorldServer destWorld = ((NailedWorld) destinationWorld).getWrapped();
Player player = null;
if(entity instanceof EntityPlayerMP){
player = NailedPlatform.instance().getPlayer(((EntityPlayerMP) entity).getGameProfile().getId());
}
if(player != null && !TeleportEventFactory.isTeleportAllowed(currentWorld, destinationWorld, player, options)){
return entity;
}
Entity mount = entity.ridingEntity;
if(entity.ridingEntity != null){
entity.mountEntity(null);
mount = teleportEntity(currentWorld, destinationWorld, mount, location, options);
}
double mX = entity.motionX;
double mY = entity.motionY;
double mZ = entity.motionZ;
boolean changingworlds = entity.worldObj != destWorld;
if(player != null){
TeleportEventFactory.onLinkStart(currentWorld, destinationWorld, player, options);
}
entity.worldObj.updateEntityWithOptionalForce(entity, false);
if(entity instanceof EntityPlayerMP){
EntityPlayerMP p = ((EntityPlayerMP) entity);
p.closeScreen();
if(changingworlds){
Dimension oldDimension = currentWorld.getDimension();
Dimension newDimension = destinationWorld.getDimension();
p.dimension = dimension;
if(oldDimension != newDimension){
p.playerNetServerHandler.sendPacket(new S07PacketRespawn(newDimension.getId(), destWorld.getDifficulty(), destWorld.getWorldInfo().getTerrainType(), p.theItemInWorldManager.getGameType()));
}else{
if(newDimension == Dimension.END){
p.playerNetServerHandler.sendPacket(new S07PacketRespawn(-1, destWorld.getDifficulty(), destWorld.getWorldInfo().getTerrainType(), p.theItemInWorldManager.getGameType()));
}else{
p.playerNetServerHandler.sendPacket(new S07PacketRespawn(1, destWorld.getDifficulty(), destWorld.getWorldInfo().getTerrainType(), p.theItemInWorldManager.getGameType()));
}
p.playerNetServerHandler.sendPacket(new S07PacketRespawn(newDimension.getId(), destWorld.getDifficulty(), destWorld.getWorldInfo().getTerrainType(), p.theItemInWorldManager.getGameType()));
}
((WorldServer) p.worldObj).getPlayerManager().removePlayer(p);
}
}
if(changingworlds){
removeEntityFromWorld(entity.worldObj, entity);
}
if(player != null){
TeleportEventFactory.onExitWorld(currentWorld, destinationWorld, player, options);
}
entity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
destWorld.theChunkProviderServer.loadChunk((int)(location.getFloorX() >> 4), (int)(location.getFloorZ() >> 4));
if(changingworlds){
if(!(entity instanceof EntityPlayerMP)){
NBTTagCompound entityNBT = new NBTTagCompound();
entity.isDead = false;
entity.writeToNBTOptional(entityNBT);
entity.isDead = true;
entity = EntityList.createEntityFromNBT(entityNBT, destWorld);
if(entity == null){
return null;
}
entity.dimension = destWorld.provider.getDimensionId();
}
destWorld.spawnEntityInWorld(entity);
entity.setWorld(destWorld);
}
entity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
if(player != null){
TeleportEventFactory.onEnterWorld(currentWorld, destinationWorld, player, options);
}
destWorld.updateEntityWithOptionalForce(entity, false);
entity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
if(entity instanceof EntityPlayerMP){
EntityPlayerMP p = ((EntityPlayerMP) entity);
if(changingworlds){
p.mcServer.getConfigurationManager().preparePlayer(p, destWorld);
}
p.playerNetServerHandler.setPlayerLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
destWorld.updateEntityWithOptionalForce(entity, false);
if(entity instanceof EntityPlayerMP){
EntityPlayerMP p = ((EntityPlayerMP) entity);
if(player != null){
NailedPlayer pl = ((NailedPlayer) player);
pl.world = location.getWorld();
pl.map = pl.world.getMap();
}
p.theItemInWorldManager.setWorld(destWorld);
p.mcServer.getConfigurationManager().updateTimeAndWeatherForPlayer(p, destWorld);
p.mcServer.getConfigurationManager().syncPlayerInventory(p);
//noinspection unchecked
for(PotionEffect effect : (Collection<PotionEffect>) p.getActivePotionEffects()){
p.playerNetServerHandler.sendPacket(new S1DPacketEntityEffect(p.getEntityId(), effect));
}
p.playerNetServerHandler.sendPacket(new S1FPacketSetExperience(p.experience, p.experienceTotal, p.experienceLevel));
}
entity.setLocationAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
if(player != null) TeleportEventFactory.onEnd(currentWorld, destinationWorld, player, options);
/*if(options.isMaintainMomentum()){
entity.motionX = mX;
entity.motionY = mY;
entity.motionZ = mZ;
}*/
if(mount != null){
if(entity instanceof EntityPlayerMP){
destWorld.updateEntityWithOptionalForce(entity, true);
}
entity.mountEntity(mount);
}
if(entity instanceof EntityLiving){
EntityLiving e = ((EntityLiving) entity);
e.setHealth(e.getMaxHealth());
e.fallDistance = 0;
}
return entity;
}
public static void removeEntityFromWorld(net.minecraft.world.World world, Entity entity){
if(entity instanceof EntityPlayerMP){
EntityPlayerMP p = ((EntityPlayerMP) entity);
p.closeScreen();
world.playerEntities.remove(p);
world.updateAllPlayersSleepingFlag();
int x = entity.chunkCoordX;
int z = entity.chunkCoordZ;
if(entity.addedToChunk && world.getChunkProvider().chunkExists(x, z)){
Chunk chunk = world.getChunkFromChunkCoords(x, z);
chunk.removeEntity(entity);
chunk.setChunkModified();
}
world.loadedEntityList.remove(entity);
world.onEntityRemoved(entity);
}else{
world.removeEntity(entity);
world.onEntityRemoved(entity);
}
}
}