DimDoors/StevenDimDoors/mod_pocketDim/DDTeleporter.java

377 lines
13 KiB
Java
Raw Normal View History

package StevenDimDoors.mod_pocketDim;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;
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;
import StevenDimDoors.mod_pocketDim.core.IDimLink;
import StevenDimDoors.mod_pocketDim.core.PocketManager;
import StevenDimDoors.mod_pocketDim.util.Point4D;
public class DDTeleporter
{
private DDTeleporter() { }
/**
* Create a new portal near an entity.
*/
public static void placeInPortal(Entity par1Entity, WorldServer world, IDimLink link)
{
Point4D destination = link.destination();
int x = destination.getX();
int y = destination.getY();
int z = destination.getZ();
//TODO Temporary workaround for mismatched door/rift metadata cases. Gives priority to the door.
int orientation = PocketManager.getDestinationOrientation(link);
int receivingDoorMeta = world.getBlockMetadata(x, y - 1, z);
int receivingDoorID = world.getBlockId(x, y, z);
if (receivingDoorMeta != orientation)
{
if (receivingDoorID == mod_pocketDim.dimDoor.blockID || receivingDoorID == mod_pocketDim.ExitDoor.blockID)
{
orientation = receivingDoorMeta;
}
}
if (par1Entity instanceof EntityPlayer)
{
EntityPlayer player = (EntityPlayer) par1Entity;
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);
}
}
else if (par1Entity instanceof EntityMinecart)
{
par1Entity.motionX=0;
par1Entity.motionZ=0;
par1Entity.motionY=0;
par1Entity.rotationYaw=(orientation*90)+90;
if(orientation==2||orientation==6)
{
DDTeleporter.setEntityPosition(par1Entity, x+1.5, y, z+.5 );
par1Entity.motionX =.39;
par1Entity.worldObj.updateEntityWithOptionalForce(par1Entity, false);
}
else if(orientation==3||orientation==7)
{
DDTeleporter.setEntityPosition(par1Entity, x+.5, y, z+1.5 );
par1Entity.motionZ =.39;
par1Entity.worldObj.updateEntityWithOptionalForce(par1Entity, false);
}
else if(orientation==0||orientation==4)
{
DDTeleporter.setEntityPosition(par1Entity,x-.5, y, z+.5);
par1Entity.motionX =-.39;
par1Entity.worldObj.updateEntityWithOptionalForce(par1Entity, false);
}
else if(orientation==1||orientation==5)
{
DDTeleporter.setEntityPosition(par1Entity,x+.5, y, z-.5);
par1Entity.motionZ =-.39;
par1Entity.worldObj.updateEntityWithOptionalForce(par1Entity, false);
}
else
{
DDTeleporter.setEntityPosition(par1Entity,x, y, z);
}
}
else if (par1Entity instanceof Entity)
{
par1Entity.rotationYaw=(orientation*90)+90;
if(orientation==2||orientation==6)
{
DDTeleporter.setEntityPosition(par1Entity, x+1.5, y, z+.5 );
}
else if(orientation==3||orientation==7)
{
DDTeleporter.setEntityPosition(par1Entity, x+.5, y, z+1.5 );
}
else if(orientation==0||orientation==4)
{
DDTeleporter.setEntityPosition(par1Entity,x-.5, y, z+.5);
}
else if(orientation==1||orientation==5)
{
DDTeleporter.setEntityPosition(par1Entity,x+.5, y, z-.5);
}
else
{
DDTeleporter.setEntityPosition(par1Entity,x, y, z);
}
}
}
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);
}
public static Entity teleportEntity(World world, Entity entity, IDimLink link)
{
//This beautiful teleport method is based off of xCompWiz's teleport function.
WorldServer oldWorld = (WorldServer)world;
WorldServer newWorld;
EntityPlayerMP player = (entity instanceof EntityPlayerMP) ? (EntityPlayerMP)entity : null;
// Is something riding? Handle it first.
if(entity.riddenByEntity != null)
{
return teleportEntity(oldWorld, entity.riddenByEntity, link);
}
// Are we riding something? Dismount and tell the mount to go first.
Entity cart = entity.ridingEntity;
if (cart != null)
{
entity.mountEntity(null);
cart = teleportEntity(oldWorld, cart, link);
// We keep track of both so we can remount them on the other side.
}
// Destination doesn't exist? We need to make it.
if (DimensionManager.getWorld(link.destination().getDimension()) == null)
{
//FIXME: I think this is where I need to add initialization code for pockets!!! REALLY IMPORTANT!!!
DimensionManager.initDimension(link.destination().getDimension());
}
// Determine if our destination's in another realm.
boolean difDest = link.source().getDimension() != link.destination().getDimension();
if (difDest)
{
newWorld = DimensionManager.getWorld(link.destination().getDimension());
}
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.
DDTeleporter.placeInPortal(entity, newWorld, link);
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.
player.dimension = link.destination().getDimension();
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);
player.isDead=false;
// 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)
{ // TODO FIXME IMPLEMENT NULL CHECKS THAT ACTUALLY DO SOMETHING.
/*
* 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.
if(player != null)
{
WorldServer.class.cast(newWorld).getChunkProvider().loadChunk(MathHelper.floor_double(entity.posX) >> 4, MathHelper.floor_double(entity.posZ) >> 4);
// 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);
}
DDTeleporter.placeInPortal(entity, newWorld, link);
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.
* Also ensures correct orientation relative to the door using DDTeleporter.
* @param world- world the player is currently in
* @param linkData- the link the player is using to teleport, sends the player to its dest information.
* @param player- the instance of the player to be teleported
* @param orientation- the orientation of the door used to teleport, determines player orientation and door placement on arrival
* @Return
*/
public static void traverseDimDoor(World world, IDimLink linkData, Entity entity)
{
DDProperties properties = DDProperties.instance();
if (world.isRemote)
{
return;
}
if (linkData != null)
{
int destinationID = link.destination().getDimension();
if(PocketManager.dimList.containsKey(destinationID) && PocketManager.dimList.containsKey(world.provider.dimensionId))
{
this.generatePocket(linkData);
if(mod_pocketDim.teleTimer==0||entity instanceof EntityPlayer)
{
mod_pocketDim.teleTimer=2+rand.nextInt(2);
}
else
{
return;
}
if(!world.isRemote)
{
entity = this.teleportEntity(world, entity, linkData);
}
entity.worldObj.playSoundEffect(entity.posX, entity.posY, entity.posZ, "mob.endermen.portal", 1.0F, 1.0F);
int playerXCoord=MathHelper.floor_double(entity.posX);
int playerYCoord=MathHelper.floor_double(entity.posY);
int playerZCoord=MathHelper.floor_double(entity.posZ);
if(!entity.worldObj.isBlockOpaqueCube(playerXCoord, playerYCoord-1,playerZCoord )&&PocketManager.instance.getDimData(linkData.locDimID).isDimRandomRift&&!linkData.hasGennedDoor)
{
for(int count=0;count<20;count++)
{
if(!entity.worldObj.isAirBlock(playerXCoord, playerYCoord-2-count,playerZCoord))
{
if(Block.blocksList[entity.worldObj.getBlockId(playerXCoord, playerYCoord-2-count,playerZCoord)].blockMaterial.isLiquid())
{
entity.worldObj.setBlock(playerXCoord, playerYCoord-1, playerZCoord, properties.FabricBlockID);
break;
}
}
if(entity.worldObj.isBlockOpaqueCube(playerXCoord, playerYCoord-1-count,playerZCoord))
{
break;
}
if(count==19)
{
entity.worldObj.setBlock(playerXCoord, playerYCoord-1, playerZCoord, properties.FabricBlockID);
}
}
}
this.generateDoor(world,linkData);
if(!entity.worldObj.isAirBlock(playerXCoord,playerYCoord+1,playerZCoord))
{
if(Block.blocksList[entity.worldObj.getBlockId(playerXCoord,playerYCoord+1,playerZCoord)].isOpaqueCube() &&
!mod_pocketDim.blockRift.isBlockImmune(entity.worldObj, playerXCoord+1,playerYCoord,playerZCoord))
{
entity.worldObj.setBlock(playerXCoord,playerYCoord+1,playerZCoord,0);
}
}
if (!entity.worldObj.isAirBlock(playerXCoord,playerYCoord,playerZCoord))
{
if(Block.blocksList[entity.worldObj.getBlockId(playerXCoord,playerYCoord,playerZCoord)].isOpaqueCube() &&
!mod_pocketDim.blockRift.isBlockImmune(entity.worldObj, playerXCoord,playerYCoord,playerZCoord))
{
entity.worldObj.setBlock(playerXCoord,playerYCoord,playerZCoord,0);
}
}
}
}
return;
}
}