package WayofTime.alchemicalWizardry.common;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.EnumMap;

import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.Packet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import WayofTime.alchemicalWizardry.AlchemicalWizardry;
import WayofTime.alchemicalWizardry.common.tileEntity.TEAltar;
import WayofTime.alchemicalWizardry.common.tileEntity.TEOrientable;
import WayofTime.alchemicalWizardry.common.tileEntity.TEPedestal;
import WayofTime.alchemicalWizardry.common.tileEntity.TEPlinth;
import WayofTime.alchemicalWizardry.common.tileEntity.TESocket;
import WayofTime.alchemicalWizardry.common.tileEntity.TETeleposer;
import WayofTime.alchemicalWizardry.common.tileEntity.TEWritingTable;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

/**
* Handles the packet wrangling for IronChest
* @author cpw
*
*/
public enum NewPacketHandler 
{
   INSTANCE;

   /**
    * Our channel "pair" from {@link NetworkRegistry}
    */
   private EnumMap<Side, FMLEmbeddedChannel> channels;


   /**
    * Make our packet handler, and add an {@link IronChestCodec} always
    */
   private NewPacketHandler()
   {
       // request a channel pair for IronChest from the network registry
       // Add the IronChestCodec as a member of both channel pipelines
       this.channels = NetworkRegistry.INSTANCE.newChannel("BloodMagic", new TEAltarCodec());
       if (FMLCommonHandler.instance().getSide() == Side.CLIENT)
       {
           addClientHandler();
       }
   }


   /**
    * This is only called on the client side - it adds an
    * {@link IronChestMessageHandler} to the client side pipeline, since the
    * only place we expect to <em>handle</em> messages is on the client.
    */
   @SideOnly(Side.CLIENT)
   private void addClientHandler() 
   {
       FMLEmbeddedChannel clientChannel = this.channels.get(Side.CLIENT);

       String tileAltarCodec = clientChannel.findChannelHandlerNameForType(TEAltarCodec.class);
       clientChannel.pipeline().addAfter(tileAltarCodec, "TEAltarHandler", new TEAltarMessageHandler());  
       clientChannel.pipeline().addAfter(tileAltarCodec, "TEOrientableHandler", new TEOrientableMessageHandler()); 
       clientChannel.pipeline().addAfter(tileAltarCodec, "TEPedestalHandler", new TEPedestalMessageHandler()); 
       clientChannel.pipeline().addAfter(tileAltarCodec, "TEPlinthHandler", new TEPlinthMessageHandler());      
       clientChannel.pipeline().addAfter(tileAltarCodec, "TESocketHandler", new TESocketMessageHandler());      
       clientChannel.pipeline().addAfter(tileAltarCodec, "TETeleposerHandler", new TETeleposerMessageHandler());      
       clientChannel.pipeline().addAfter(tileAltarCodec, "TEWritingTableHandler", new TEWritingTableMessageHandler());
       clientChannel.pipeline().addAfter(tileAltarCodec, "ParticleHandler", new ParticleMessageHandler());
       clientChannel.pipeline().addAfter(tileAltarCodec, "VelocityHandler", new VelocityMessageHandler());
   }


   /**
    * This class simply handles the {@link IronChestMessage} when it's received
    * at the client side It can contain client only code, because it's only run
    * on the client.
    *
    * @author cpw
    *
    */
   private static class TEAltarMessageHandler extends SimpleChannelInboundHandler<TEAltarMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TEAltarMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TEAltar)
           {
               TEAltar altar = (TEAltar) te;

               altar.handlePacketData(msg.items, msg.fluids, msg.capacity);
           }
       }
   }
   
   private static class TEOrientableMessageHandler extends SimpleChannelInboundHandler<TEOrientableMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TEOrientableMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TEOrientable)
           {
        	   TEOrientable tile = (TEOrientable)te;

               ((TEOrientable) te).setInputDirection(ForgeDirection.getOrientation(msg.input));
               ((TEOrientable) te).setOutputDirection(ForgeDirection.getOrientation(msg.output));
           }
       }
   }
   
   private static class TEPedestalMessageHandler extends SimpleChannelInboundHandler<TEPedestalMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TEPedestalMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TEPedestal)
           {
               TEPedestal pedestal = (TEPedestal) te;

               pedestal.handlePacketData(msg.items);
           }
       }
   }
   
   private static class TEPlinthMessageHandler extends SimpleChannelInboundHandler<TEPlinthMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TEPlinthMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TEPlinth)
           {
               TEPlinth Plinth = (TEPlinth) te;

               Plinth.handlePacketData(msg.items);
           }
       }
   }
   
   private static class TESocketMessageHandler extends SimpleChannelInboundHandler<TESocketMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TESocketMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TESocket)
           {
               TESocket Socket = (TESocket) te;

               Socket.handlePacketData(msg.items);
           }
       }
   }
   
   private static class TETeleposerMessageHandler extends SimpleChannelInboundHandler<TETeleposerMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TETeleposerMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TETeleposer)
           {
               TETeleposer Teleposer = (TETeleposer) te;

               Teleposer.handlePacketData(msg.items);
           }
       }
   }
   
   private static class TEWritingTableMessageHandler extends SimpleChannelInboundHandler<TEWritingTableMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, TEWritingTableMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           TileEntity te = world.getTileEntity(msg.x, msg.y, msg.z);
           if (te instanceof TEWritingTable)
           {
               TEWritingTable WritingTable = (TEWritingTable) te;

               WritingTable.handlePacketData(msg.items);
           }
       }
   }
   
   private static class ParticleMessageHandler extends SimpleChannelInboundHandler<ParticleMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, ParticleMessage msg) throws Exception
       {
           World world = AlchemicalWizardry.proxy.getClientWorld();
           
           world.spawnParticle(msg.particle, msg.xCoord, msg.yCoord, msg.zCoord, msg.xVel, msg.yVel, msg.zVel);
       }
   }
   
   private static class VelocityMessageHandler extends SimpleChannelInboundHandler<VelocityMessage>
   {
       @Override
       protected void channelRead0(ChannelHandlerContext ctx, VelocityMessage msg) throws Exception
       {
           EntityPlayer player = Minecraft.getMinecraft().thePlayer;
           
           if(player!=null)
           {
        	   player.motionX = msg.xVel;
        	   player.motionY = msg.yVel;
        	   player.motionZ = msg.zVel;
           }
       }
   }

   public static class BMMessage
   {
	   int index;
   }
   
   public static class TEAltarMessage extends BMMessage
   {
       int x;
       int y;
       int z;

       int[] items;
       int[] fluids;
       int capacity;
   }
   
   public static class TEOrientableMessage extends BMMessage
   {
       int x;
       int y;
       int z;
       
       int input;
       int output;
   }
   
   public static class TEPedestalMessage extends BMMessage
   {
	   int x;
       int y;
       int z;

       int[] items;
   }
   
   public static class TEPlinthMessage extends BMMessage
   {
	   int x;
       int y;
       int z;

       int[] items;
   }
   
   public static class TESocketMessage extends BMMessage
   {
	   int x;
       int y;
       int z;

       int[] items;
   }
   
   public static class TETeleposerMessage extends BMMessage
   {
	   int x;
       int y;
       int z;

       int[] items;
   }
   
   public static class TEWritingTableMessage extends BMMessage
   {
	   int x;
       int y;
       int z;

       int[] items;
   }
   
   public static class ParticleMessage extends BMMessage
   {
	   String particle;
	   
	   double xCoord;
	   double yCoord;
	   double zCoord;
	   
	   double xVel;
	   double yVel;
	   double zVel;
   }
   
   public static class VelocityMessage extends BMMessage
   {
	   double xVel;
	   double yVel;
	   double zVel;
   }

   private class TEAltarCodec extends FMLIndexedMessageToMessageCodec<BMMessage>
   {
       public TEAltarCodec()
       {
           addDiscriminator(0, TEAltarMessage.class);
           addDiscriminator(1, TEOrientableMessage.class);
           addDiscriminator(2, TEPedestalMessage.class);
           addDiscriminator(3, TEPlinthMessage.class);
           addDiscriminator(4, TESocketMessage.class);
           addDiscriminator(5, TETeleposerMessage.class);
           addDiscriminator(6, TEWritingTableMessage.class);
           addDiscriminator(7, ParticleMessage.class);
           addDiscriminator(8, VelocityMessage.class);
       }
       
       @Override
       public void encodeInto(ChannelHandlerContext ctx, BMMessage msg, ByteBuf target) throws Exception
       {
    	   target.writeInt(msg.index);
    	   
    	   switch(msg.index)
    	   {
    	   case 0:
    		   target.writeInt(((TEAltarMessage)msg).x);
               target.writeInt(((TEAltarMessage)msg).y);
               target.writeInt(((TEAltarMessage)msg).z);

               target.writeBoolean(((TEAltarMessage)msg).items != null);
               if (((TEAltarMessage)msg).items != null)
               {
                   int[] items = ((TEAltarMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
               target.writeBoolean(((TEAltarMessage)msg).fluids != null);
               if(((TEAltarMessage)msg).fluids != null)
               {
            	   int[] fluids = ((TEAltarMessage)msg).fluids;
            	   for (int j = 0; j < fluids.length; j++)
                   {
                       int i = fluids[j];
                       target.writeInt(i);
                   }
               }
               
               target.writeInt(((TEAltarMessage)msg).capacity); 
               
               break;
               
    	   case 1:
    		   target.writeInt(((TEOrientableMessage)msg).x);
               target.writeInt(((TEOrientableMessage)msg).y);
               target.writeInt(((TEOrientableMessage)msg).z);

               target.writeInt(((TEOrientableMessage)msg).input);
               target.writeInt(((TEOrientableMessage)msg).output);
               
               break;
               
    	   case 2:
    		   target.writeInt(((TEPedestalMessage)msg).x);
               target.writeInt(((TEPedestalMessage)msg).y);
               target.writeInt(((TEPedestalMessage)msg).z);

               target.writeBoolean(((TEPedestalMessage)msg).items != null);
               if (((TEPedestalMessage)msg).items != null)
               {
                   int[] items = ((TEPedestalMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
               break;
               
    	   case 3:
    		   target.writeInt(((TEPlinthMessage)msg).x);
               target.writeInt(((TEPlinthMessage)msg).y);
               target.writeInt(((TEPlinthMessage)msg).z);

               target.writeBoolean(((TEPlinthMessage)msg).items != null);
               if (((TEPlinthMessage)msg).items != null)
               {
                   int[] items = ((TEPlinthMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
    		   break;
    		   
    	   case 4:
    		   target.writeInt(((TESocketMessage)msg).x);
               target.writeInt(((TESocketMessage)msg).y);
               target.writeInt(((TESocketMessage)msg).z);

               target.writeBoolean(((TESocketMessage)msg).items != null);
               if (((TESocketMessage)msg).items != null)
               {
                   int[] items = ((TESocketMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
    		   break;
    		   
    	   case 5:
    		   target.writeInt(((TETeleposerMessage)msg).x);
               target.writeInt(((TETeleposerMessage)msg).y);
               target.writeInt(((TETeleposerMessage)msg).z);

               target.writeBoolean(((TETeleposerMessage)msg).items != null);
               if (((TETeleposerMessage)msg).items != null)
               {
                   int[] items = ((TETeleposerMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
    		   break;
    		   
    	   case 6:
    		   target.writeInt(((TEWritingTableMessage)msg).x);
               target.writeInt(((TEWritingTableMessage)msg).y);
               target.writeInt(((TEWritingTableMessage)msg).z);

               target.writeBoolean(((TEWritingTableMessage)msg).items != null);
               if (((TEWritingTableMessage)msg).items != null)
               {
                   int[] items = ((TEWritingTableMessage)msg).items;
                   for (int j = 0; j < items.length; j++)
                   {
                       int i = items[j];
                       target.writeInt(i);
                   }
               }
               
    		   break;
    		   
    	   case 7:
    		   String str = ((ParticleMessage)msg).particle;
    		   target.writeInt(str.length());
    		   for(int i=0; i<str.length(); i++)
    		   {
    			   target.writeChar(str.charAt(i));
    		   }
    		   
    		   target.writeDouble(((ParticleMessage)msg).xCoord);
    		   target.writeDouble(((ParticleMessage)msg).yCoord);
    		   target.writeDouble(((ParticleMessage)msg).zCoord);
    		   
    		   target.writeDouble(((ParticleMessage)msg).xVel);
    		   target.writeDouble(((ParticleMessage)msg).yVel);
    		   target.writeDouble(((ParticleMessage)msg).zVel);
    		   
    		   break;
    		   
    	   case 8:
    		   target.writeDouble(((VelocityMessage)msg).xVel);
    		   target.writeDouble(((VelocityMessage)msg).yVel);
    		   target.writeDouble(((VelocityMessage)msg).zVel);
    		   
    		   break;
    	   }
       }


       @Override
       public void decodeInto(ChannelHandlerContext ctx, ByteBuf dat, BMMessage msg)
       {
    	   int index = dat.readInt();
    	   
    	   switch(index)
    	   {
    	   case 0:
    		   ((TEAltarMessage)msg).x = dat.readInt();
               ((TEAltarMessage)msg).y = dat.readInt();
               ((TEAltarMessage)msg).z = dat.readInt();
               boolean hasStacks = dat.readBoolean();
               
               ((TEAltarMessage)msg).items = new int[TEAltar.sizeInv*3];
               if (hasStacks)
               {
                   ((TEAltarMessage)msg).items = new int[TEAltar.sizeInv*3];
                   for (int i = 0; i < ((TEAltarMessage)msg).items.length; i++)
                   {
                       ((TEAltarMessage)msg).items[i] = dat.readInt();
                   }
               }
               
               boolean hasFluids = dat.readBoolean();
               ((TEAltarMessage)msg).fluids = new int[6];
               if(hasFluids)
    	           for (int i = 0; i < ((TEAltarMessage)msg).fluids.length; i++)
    	           {
    	               ((TEAltarMessage)msg).fluids[i] = dat.readInt();
    	           }
               
               ((TEAltarMessage)msg).capacity = dat.readInt();
               
               break;
               
    	   case 1:
    		   ((TEOrientableMessage)msg).x = dat.readInt();
               ((TEOrientableMessage)msg).y = dat.readInt();
               ((TEOrientableMessage)msg).z = dat.readInt();
               
               ((TEOrientableMessage)msg).input = dat.readInt();
               ((TEOrientableMessage)msg).output = dat.readInt();
               
               break;
               
    	   case 2:
    		   ((TEPedestalMessage)msg).x = dat.readInt();
               ((TEPedestalMessage)msg).y = dat.readInt();
               ((TEPedestalMessage)msg).z = dat.readInt();

               boolean hasStacks1 = dat.readBoolean();
               
               ((TEPedestalMessage)msg).items = new int[TEPedestal.sizeInv*3];
               if (hasStacks1)
               {
                   ((TEPedestalMessage)msg).items = new int[TEPedestal.sizeInv*3];
                   for (int i = 0; i < ((TEPedestalMessage)msg).items.length; i++)
                   {
                       ((TEPedestalMessage)msg).items[i] = dat.readInt();
                   }
               }
               
    		   break;
               
    	   case 3:
    		   ((TEPlinthMessage)msg).x = dat.readInt();
               ((TEPlinthMessage)msg).y = dat.readInt();
               ((TEPlinthMessage)msg).z = dat.readInt();

               boolean hasStacks2 = dat.readBoolean();
               
               ((TEPlinthMessage)msg).items = new int[TEPlinth.sizeInv*3];
               if (hasStacks2)
               {
                   ((TEPlinthMessage)msg).items = new int[TEPlinth.sizeInv*3];
                   for (int i = 0; i < ((TEPlinthMessage)msg).items.length; i++)
                   {
                       ((TEPlinthMessage)msg).items[i] = dat.readInt();
                   }
               }
               
    		   break;
               
    	   case 4:
    		   ((TESocketMessage)msg).x = dat.readInt();
               ((TESocketMessage)msg).y = dat.readInt();
               ((TESocketMessage)msg).z = dat.readInt();

               boolean hasStacks3 = dat.readBoolean();
               
               ((TESocketMessage)msg).items = new int[TESocket.sizeInv*3];
               if (hasStacks3)
               {
                   ((TESocketMessage)msg).items = new int[TESocket.sizeInv*3];
                   for (int i = 0; i < ((TESocketMessage)msg).items.length; i++)
                   {
                       ((TESocketMessage)msg).items[i] = dat.readInt();
                   }
               }
               
    		   break;
               
    	   case 5:
    		   ((TETeleposerMessage)msg).x = dat.readInt();
               ((TETeleposerMessage)msg).y = dat.readInt();
               ((TETeleposerMessage)msg).z = dat.readInt();

               boolean hasStacks4 = dat.readBoolean();
               
               ((TETeleposerMessage)msg).items = new int[TETeleposer.sizeInv*3];
               if (hasStacks4)
               {
                   ((TETeleposerMessage)msg).items = new int[TETeleposer.sizeInv*3];
                   for (int i = 0; i < ((TETeleposerMessage)msg).items.length; i++)
                   {
                       ((TETeleposerMessage)msg).items[i] = dat.readInt();
                   }
               }
               
    		   break;
               
    	   case 6:
    		   ((TEWritingTableMessage)msg).x = dat.readInt();
               ((TEWritingTableMessage)msg).y = dat.readInt();
               ((TEWritingTableMessage)msg).z = dat.readInt();

               boolean hasStacks5 = dat.readBoolean();
               
               ((TEWritingTableMessage)msg).items = new int[TEWritingTable.sizeInv*3];
               if (hasStacks5)
               {
                   ((TEWritingTableMessage)msg).items = new int[TEWritingTable.sizeInv*3];
                   for (int i = 0; i < ((TEWritingTableMessage)msg).items.length; i++)
                   {
                       ((TEWritingTableMessage)msg).items[i] = dat.readInt();
                   }
               }
               
    		   break;   
    		   
    	   case 7:
    		   int size = dat.readInt();
	           String str = "";

	           for (int i = 0; i < size; i++)
	           {
	               str = str + dat.readChar();
	           }
	           
	           ((ParticleMessage)msg).particle = str;
	           
	           ((ParticleMessage)msg).xCoord = dat.readDouble();
	           ((ParticleMessage)msg).yCoord = dat.readDouble();
	           ((ParticleMessage)msg).zCoord = dat.readDouble();
	           
	           ((ParticleMessage)msg).xVel = dat.readDouble();
	           ((ParticleMessage)msg).yVel = dat.readDouble();
	           ((ParticleMessage)msg).zVel = dat.readDouble();
	           
	           break;
	           
    	   case 8:
    		   ((VelocityMessage)msg).xVel = dat.readDouble();
    		   ((VelocityMessage)msg).yVel = dat.readDouble();
    		   ((VelocityMessage)msg).zVel = dat.readDouble();
    		   
    		   break;
    	   }
       }
   }

   //Packets to be obtained
   public static Packet getPacket(TEAltar tileAltar)
   {
       TEAltarMessage msg = new TEAltarMessage();
       msg.index = 0;
       msg.x = tileAltar.xCoord;
       msg.y = tileAltar.yCoord;
       msg.z = tileAltar.zCoord;
       msg.items = tileAltar.buildIntDataList();
       msg.fluids = tileAltar.buildFluidList();
       msg.capacity = tileAltar.getCapacity();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TEOrientable tileOrientable)
   {
       TEOrientableMessage msg = new TEOrientableMessage();
       msg.index = 1;
       msg.x = tileOrientable.xCoord;
       msg.y = tileOrientable.yCoord;
       msg.z = tileOrientable.zCoord;
       msg.input = tileOrientable.getIntForForgeDirection(tileOrientable.getInputDirection());
       msg.output = tileOrientable.getIntForForgeDirection(tileOrientable.getOutputDirection());
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TEPedestal tilePedestal)
   {
       TEPedestalMessage msg = new TEPedestalMessage();
       msg.index = 2;
       msg.x = tilePedestal.xCoord;
       msg.y = tilePedestal.yCoord;
       msg.z = tilePedestal.zCoord;
       msg.items = tilePedestal.buildIntDataList();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TEPlinth tilePlinth)
   {
       TEPlinthMessage msg = new TEPlinthMessage();
       msg.index = 3;
       msg.x = tilePlinth.xCoord;
       msg.y = tilePlinth.yCoord;
       msg.z = tilePlinth.zCoord;
       msg.items = tilePlinth.buildIntDataList();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TESocket tileSocket)
   {
       TESocketMessage msg = new TESocketMessage();
       msg.index = 4;
       msg.x = tileSocket.xCoord;
       msg.y = tileSocket.yCoord;
       msg.z = tileSocket.zCoord;
       msg.items = tileSocket.buildIntDataList();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TETeleposer tileTeleposer)
   {
       TETeleposerMessage msg = new TETeleposerMessage();
       msg.index = 5;
       msg.x = tileTeleposer.xCoord;
       msg.y = tileTeleposer.yCoord;
       msg.z = tileTeleposer.zCoord;
       msg.items = tileTeleposer.buildIntDataList();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getPacket(TEWritingTable tileWritingTable)
   {
       TEWritingTableMessage msg = new TEWritingTableMessage();
       msg.index = 6;
       msg.x = tileWritingTable.xCoord;
       msg.y = tileWritingTable.yCoord;
       msg.z = tileWritingTable.zCoord;
       msg.items = tileWritingTable.buildIntDataList();
       
       return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getParticlePacket(String str, double xCoord, double yCoord, double zCoord, double xVel, double yVel, double zVel)
   {
	   ParticleMessage msg = new ParticleMessage();
	   msg.index = 7;
	   msg.particle = str;
	   msg.xCoord = xCoord;
	   msg.yCoord = yCoord;
	   msg.zCoord = zCoord;
	   msg.xVel = xVel;
	   msg.yVel = yVel;
	   msg.zVel = zVel;
	   
	   return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public static Packet getVelSettingPacket(double xVel, double yVel, double zVel)
   {
	   VelocityMessage msg = new VelocityMessage();
	   msg.index = 8;
	   msg.xVel = xVel;
	   msg.yVel = yVel;
	   msg.zVel = zVel;
	   
	   return INSTANCE.channels.get(Side.SERVER).generatePacketFrom(msg);
   }
   
   public void sendTo(Packet message, EntityPlayerMP player) 
   {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }
   
   public void sendToAll(Packet message) 
   {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }
   
   public void sendToAllAround(Packet message, NetworkRegistry.TargetPoint point) 
   {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }
}