2013-08-29 08:14:24 +02:00
|
|
|
package StevenDimDoors.mod_pocketDim;
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
import java.util.Random;
|
|
|
|
|
2013-08-29 08:14:24 +02:00
|
|
|
import net.minecraft.entity.Entity;
|
|
|
|
import net.minecraft.entity.EntityList;
|
|
|
|
import net.minecraft.entity.item.EntityMinecart;
|
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
|
|
import net.minecraft.entity.player.EntityPlayerMP;
|
|
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
|
|
import net.minecraft.network.packet.Packet41EntityEffect;
|
|
|
|
import net.minecraft.network.packet.Packet43Experience;
|
|
|
|
import net.minecraft.network.packet.Packet9Respawn;
|
|
|
|
import net.minecraft.potion.PotionEffect;
|
|
|
|
import net.minecraft.util.MathHelper;
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
import net.minecraft.world.WorldServer;
|
|
|
|
import net.minecraftforge.common.DimensionManager;
|
2013-09-02 17:47:12 +02:00
|
|
|
import StevenDimDoors.mod_pocketDim.core.DimLink;
|
|
|
|
import StevenDimDoors.mod_pocketDim.core.LinkTypes;
|
2013-08-29 08:14:24 +02:00
|
|
|
import StevenDimDoors.mod_pocketDim.core.PocketManager;
|
|
|
|
import StevenDimDoors.mod_pocketDim.util.Point4D;
|
2013-09-01 15:21:27 +02:00
|
|
|
import StevenDimDoors.mod_pocketDim.world.PocketBuilder;
|
|
|
|
import cpw.mods.fml.common.registry.GameRegistry;
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
public class DDTeleporter
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
private static final Random random = new Random();
|
|
|
|
public static int cooldown = 0;
|
|
|
|
|
2013-08-29 08:14:24 +02:00
|
|
|
private DDTeleporter() { }
|
2013-09-01 15:21:27 +02:00
|
|
|
|
|
|
|
private static void placeInPortal(Entity entity, WorldServer world, Point4D destination, DDProperties properties)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
|
|
|
int x = destination.getX();
|
|
|
|
int y = destination.getY();
|
|
|
|
int z = destination.getZ();
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
int orientation = getDestinationOrientation(destination, properties);
|
2013-08-29 08:14:24 +02:00
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
if (entity instanceof EntityPlayer)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
EntityPlayer player = (EntityPlayer) entity;
|
2013-08-29 08:14:24 +02:00
|
|
|
player.rotationYaw=(orientation*90)+90;
|
|
|
|
if(orientation==2||orientation==6)
|
|
|
|
{
|
|
|
|
player.setPositionAndUpdate( x+1.5, y-1, z+.5 );
|
|
|
|
}
|
|
|
|
else if(orientation==3||orientation==7)
|
|
|
|
{
|
|
|
|
player.setPositionAndUpdate( x+.5, y-1, z+1.5 );
|
|
|
|
}
|
|
|
|
else if(orientation==0||orientation==4)
|
|
|
|
{
|
|
|
|
player.setPositionAndUpdate(x-.5, y-1, z+.5);
|
|
|
|
}
|
|
|
|
else if(orientation==1||orientation==5)
|
|
|
|
{
|
|
|
|
player.setPositionAndUpdate(x+.5, y-1, z-.5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
player.setPositionAndUpdate(x, y-1, z);
|
|
|
|
}
|
|
|
|
}
|
2013-09-01 15:21:27 +02:00
|
|
|
else if (entity instanceof EntityMinecart)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
entity.motionX=0;
|
|
|
|
entity.motionZ=0;
|
|
|
|
entity.motionY=0;
|
|
|
|
entity.rotationYaw=(orientation*90)+90;
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
if(orientation==2||orientation==6)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity, x+1.5, y, z+.5 );
|
|
|
|
entity.motionX =.39;
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==3||orientation==7)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity, x+.5, y, z+1.5 );
|
|
|
|
entity.motionZ =.39;
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==0||orientation==4)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x-.5, y, z+.5);
|
|
|
|
entity.motionX =-.39;
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==1||orientation==5)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x+.5, y, z-.5);
|
|
|
|
entity.motionZ =-.39;
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x, y, z);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
}
|
2013-09-01 15:21:27 +02:00
|
|
|
else if (entity instanceof Entity)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
entity.rotationYaw=(orientation*90)+90;
|
2013-08-29 08:14:24 +02:00
|
|
|
if(orientation==2||orientation==6)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity, x+1.5, y, z+.5 );
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==3||orientation==7)
|
|
|
|
{
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity, x+.5, y, z+1.5 );
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==0||orientation==4)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x-.5, y, z+.5);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else if(orientation==1||orientation==5)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x+.5, y, z-.5);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.setEntityPosition(entity,x, y, z);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void setEntityPosition(Entity entity, double x, double y, double z)
|
|
|
|
{
|
|
|
|
entity.lastTickPosX = entity.prevPosX = entity.posX = x;
|
|
|
|
entity.lastTickPosY = entity.prevPosY = entity.posY = y + (double)entity.yOffset;
|
|
|
|
entity.lastTickPosZ = entity.prevPosZ = entity.posZ = z;
|
|
|
|
entity.setPosition(x, y, z);
|
|
|
|
}
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
private static int getDestinationOrientation(Point4D door, DDProperties properties)
|
|
|
|
{
|
|
|
|
World world = DimensionManager.getWorld(door.getDimension());
|
|
|
|
if (world == null)
|
|
|
|
{
|
|
|
|
throw new IllegalStateException("The destination world should be loaded!");
|
|
|
|
}
|
|
|
|
|
2013-09-04 20:29:53 +02:00
|
|
|
//Check if the block below that point is actually a door
|
|
|
|
int blockID = world.getBlockId(door.getX(), door.getY() - 1, door.getZ());
|
2013-09-01 15:21:27 +02:00
|
|
|
if (blockID != properties.DimensionalDoorID && blockID != properties.WarpDoorID &&
|
|
|
|
blockID != properties.TransientDoorID && blockID != properties.UnstableDoorID)
|
|
|
|
{
|
|
|
|
//Return the pocket's orientation instead
|
|
|
|
return PocketManager.getDimensionData(door.getDimension()).orientation();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Return the orientation portion of its metadata
|
2013-09-04 20:29:53 +02:00
|
|
|
return world.getBlockMetadata(door.getX(), door.getY() - 1, door.getZ()) & 3;
|
2013-09-01 15:21:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Entity teleportEntity(Entity entity, Point4D destination)
|
|
|
|
{
|
|
|
|
if (entity == null)
|
|
|
|
{
|
|
|
|
throw new IllegalArgumentException("entity cannot be null.");
|
|
|
|
}
|
|
|
|
if (destination == null)
|
|
|
|
{
|
|
|
|
throw new IllegalArgumentException("destination cannot be null.");
|
|
|
|
}
|
|
|
|
|
2013-08-29 08:14:24 +02:00
|
|
|
//This beautiful teleport method is based off of xCompWiz's teleport function.
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
WorldServer oldWorld = (WorldServer) entity.worldObj;
|
2013-08-29 08:14:24 +02:00
|
|
|
WorldServer newWorld;
|
2013-09-01 15:21:27 +02:00
|
|
|
EntityPlayerMP player = (entity instanceof EntityPlayerMP) ? (EntityPlayerMP) entity : null;
|
|
|
|
DDProperties properties = DDProperties.instance();
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
// Is something riding? Handle it first.
|
2013-09-01 15:21:27 +02:00
|
|
|
if (entity.riddenByEntity != null)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
return teleportEntity(entity.riddenByEntity, destination);
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Are we riding something? Dismount and tell the mount to go first.
|
|
|
|
Entity cart = entity.ridingEntity;
|
|
|
|
if (cart != null)
|
|
|
|
{
|
|
|
|
entity.mountEntity(null);
|
2013-09-01 15:21:27 +02:00
|
|
|
cart = teleportEntity(cart, destination);
|
2013-08-29 08:14:24 +02:00
|
|
|
// We keep track of both so we can remount them on the other side.
|
|
|
|
}
|
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
// Determine if our destination is in another realm.
|
2013-09-04 06:34:11 +02:00
|
|
|
boolean difDest = entity.dimension != destination.getDimension();
|
2013-08-29 08:14:24 +02:00
|
|
|
if (difDest)
|
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
// Destination isn't loaded? Then we need to load it.
|
|
|
|
newWorld = DimensionManager.getWorld(destination.getDimension());
|
|
|
|
if (newWorld == null)
|
|
|
|
{
|
|
|
|
DimensionManager.initDimension(destination.getDimension());
|
2013-09-04 06:34:11 +02:00
|
|
|
newWorld = DimensionManager.getWorld(destination.getDimension());
|
2013-09-01 15:21:27 +02:00
|
|
|
}
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newWorld = (WorldServer) oldWorld;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GreyMaria: What is this even accomplishing? We're doing the exact same thing at the end of this all.
|
|
|
|
// TODO Check to see if this is actually vital.
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.placeInPortal(entity, newWorld, destination, properties);
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
if (difDest) // Are we moving our target to a new dimension?
|
|
|
|
{
|
|
|
|
if(player != null) // Are we working with a player?
|
|
|
|
{
|
|
|
|
// We need to do all this special stuff to move a player between dimensions.
|
|
|
|
|
|
|
|
// Set the new dimension and inform the client that it's moving to a new world.
|
2013-09-01 15:21:27 +02:00
|
|
|
player.dimension = destination.getDimension();
|
2013-08-29 08:14:24 +02:00
|
|
|
player.playerNetServerHandler.sendPacketToPlayer(new Packet9Respawn(player.dimension, (byte)player.worldObj.difficultySetting, newWorld.getWorldInfo().getTerrainType(), newWorld.getHeight(), player.theItemInWorldManager.getGameType()));
|
|
|
|
|
|
|
|
// GreyMaria: Used the safe player entity remover before.
|
|
|
|
// This should fix an apparently unreported bug where
|
|
|
|
// the last non-sleeping player leaves the Overworld
|
|
|
|
// for a pocket dimension, causing all sleeping players
|
|
|
|
// to remain asleep instead of progressing to day.
|
|
|
|
oldWorld.removePlayerEntityDangerously(player);
|
2013-09-01 15:21:27 +02:00
|
|
|
player.isDead = false;
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
// Creates sanity by ensuring that we're only known to exist where we're supposed to be known to exist.
|
|
|
|
oldWorld.getPlayerManager().removePlayer(player);
|
|
|
|
newWorld.getPlayerManager().addPlayer(player);
|
|
|
|
|
|
|
|
player.theItemInWorldManager.setWorld((WorldServer)newWorld);
|
|
|
|
|
|
|
|
// Synchronize with the server so the client knows what time it is and what it's holding.
|
|
|
|
player.mcServer.getConfigurationManager().updateTimeAndWeatherForPlayer(player, (WorldServer)newWorld);
|
|
|
|
player.mcServer.getConfigurationManager().syncPlayerInventory(player);
|
|
|
|
for(Object potionEffect : player.getActivePotionEffects())
|
|
|
|
{
|
|
|
|
PotionEffect effect = (PotionEffect)potionEffect;
|
|
|
|
player.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(player.entityId, effect));
|
|
|
|
}
|
|
|
|
|
|
|
|
player.playerNetServerHandler.sendPacketToPlayer(new Packet43Experience(player.experience, player.experienceTotal, player.experienceLevel));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates sanity by removing the entity from its old location's chunk entity list, if applicable.
|
|
|
|
int entX = entity.chunkCoordX;
|
|
|
|
int entZ = entity.chunkCoordZ;
|
|
|
|
if ((entity.addedToChunk) && (oldWorld.getChunkProvider().chunkExists(entX, entZ)))
|
|
|
|
{
|
|
|
|
oldWorld.getChunkFromChunkCoords(entX, entZ).removeEntity(entity);
|
|
|
|
oldWorld.getChunkFromChunkCoords(entX, entZ).isModified = true;
|
|
|
|
}
|
|
|
|
// Memory concerns.
|
|
|
|
oldWorld.releaseEntitySkin(entity);
|
|
|
|
|
|
|
|
if (player == null) // Are we NOT working with a player?
|
|
|
|
{
|
|
|
|
NBTTagCompound entityNBT = new NBTTagCompound();
|
|
|
|
entity.isDead = false;
|
|
|
|
entity.addEntityID(entityNBT);
|
|
|
|
entity.isDead = true;
|
|
|
|
entity = EntityList.createEntityFromNBT(entityNBT, newWorld);
|
|
|
|
|
|
|
|
if (entity == null)
|
2013-09-01 15:21:27 +02:00
|
|
|
{
|
|
|
|
// TODO FIXME IMPLEMENT NULL CHECKS THAT ACTUALLY DO SOMETHING.
|
2013-08-29 08:14:24 +02:00
|
|
|
/*
|
|
|
|
* shit ourselves in an organized fashion, preferably
|
|
|
|
* in a neat pile instead of all over our users' games
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, respawn the entity in its new home.
|
|
|
|
newWorld.spawnEntityInWorld(entity);
|
|
|
|
entity.setWorld(newWorld);
|
|
|
|
}
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, false);
|
|
|
|
|
|
|
|
// Hey, remember me? It's time to remount.
|
|
|
|
if (cart != null)
|
|
|
|
{
|
|
|
|
// Was there a player teleported? If there was, it's important that we update shit.
|
|
|
|
if (player != null)
|
|
|
|
{
|
|
|
|
entity.worldObj.updateEntityWithOptionalForce(entity, true);
|
|
|
|
}
|
|
|
|
entity.mountEntity(cart);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did we teleport a player? Load the chunk for them.
|
2013-09-01 15:21:27 +02:00
|
|
|
if (player != null)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
newWorld.getChunkProvider().loadChunk(MathHelper.floor_double(entity.posX) >> 4, MathHelper.floor_double(entity.posZ) >> 4);
|
2013-08-29 08:14:24 +02:00
|
|
|
|
|
|
|
// Tell Forge we're moving its players so everyone else knows.
|
|
|
|
// Let's try doing this down here in case this is what's killing NEI.
|
|
|
|
GameRegistry.onPlayerChangedDimension((EntityPlayer)entity);
|
|
|
|
|
|
|
|
}
|
2013-09-01 15:21:27 +02:00
|
|
|
DDTeleporter.placeInPortal(entity, newWorld, destination, properties);
|
2013-08-29 08:14:24 +02:00
|
|
|
return entity;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Primary function used to teleport the player using doors. Performs numerous null checks, and also generates the destination door/pocket if it has not done so already.
|
2013-09-01 15:21:27 +02:00
|
|
|
* Also ensures correct orientation relative to the door.
|
|
|
|
* @param world - world the player is currently in
|
|
|
|
* @param link - the link the player is using to teleport; sends the player to its destination
|
|
|
|
* @param player - the instance of the player to be teleported
|
2013-08-29 08:14:24 +02:00
|
|
|
*/
|
2013-09-02 17:47:12 +02:00
|
|
|
public static void traverseDimDoor(World world, DimLink link, Entity entity)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
if (world == null)
|
|
|
|
{
|
|
|
|
throw new IllegalArgumentException("world cannot be null.");
|
|
|
|
}
|
|
|
|
if (link == null)
|
|
|
|
{
|
|
|
|
throw new IllegalArgumentException("link cannot be null.");
|
|
|
|
}
|
|
|
|
if (entity == null)
|
|
|
|
{
|
|
|
|
throw new IllegalArgumentException("entity cannot be null.");
|
|
|
|
}
|
2013-08-29 08:14:24 +02:00
|
|
|
if (world.isRemote)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-09-01 15:21:27 +02:00
|
|
|
|
|
|
|
if (cooldown == 0 || entity instanceof EntityPlayer)
|
2013-08-29 08:14:24 +02:00
|
|
|
{
|
2013-09-01 15:21:27 +02:00
|
|
|
cooldown = 2 + random.nextInt(2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-08-29 08:14:24 +02:00
|
|
|
|
2013-09-01 15:21:27 +02:00
|
|
|
if (!initializeDestination(link, DDProperties.instance()))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
entity = teleportEntity(entity, link.destination());
|
|
|
|
entity.worldObj.playSoundEffect(entity.posX, entity.posY, entity.posZ, "mob.endermen.portal", 1.0F, 1.0F);
|
|
|
|
}
|
2013-08-29 08:14:24 +02:00
|
|
|
|
2013-09-02 17:47:12 +02:00
|
|
|
private static boolean initializeDestination(DimLink link, DDProperties properties)
|
2013-09-01 15:21:27 +02:00
|
|
|
{
|
|
|
|
//FIXME: Change this later to support rooms that have been wiped and must be regenerated.
|
|
|
|
if (link.hasDestination())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check the destination type and respond accordingly
|
|
|
|
//FIXME: Add missing link types.
|
|
|
|
//FIXME: Add code for restoring the destination-side door.
|
|
|
|
switch (link.linkType())
|
|
|
|
{
|
2013-09-02 17:47:12 +02:00
|
|
|
case LinkTypes.DUNGEON:
|
2013-09-01 15:21:27 +02:00
|
|
|
return PocketBuilder.generateNewDungeonPocket(link, properties);
|
2013-09-02 17:47:12 +02:00
|
|
|
case LinkTypes.POCKET:
|
2013-09-01 15:21:27 +02:00
|
|
|
return PocketBuilder.generateNewPocket(link, properties);
|
2013-09-02 17:47:12 +02:00
|
|
|
case LinkTypes.NORMAL:
|
2013-09-01 15:21:27 +02:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
throw new IllegalArgumentException("link has an unrecognized link type.");
|
2013-08-29 08:14:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|