package mekanism.common; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.util.ArrayList; import java.util.List; import mekanism.api.Object3D; import mekanism.common.network.IMekanismPacket; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.INetworkManager; import net.minecraft.network.packet.Packet250CustomPayload; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.PacketDispatcher; import cpw.mods.fml.common.network.Player; /** * Mekanism packet handler. As always, use packets sparingly! * @author AidanBrady * */ public class PacketHandler implements IPacketHandler { public static List> packets = new ArrayList>(); @Override public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { ByteArrayDataInput dataStream = ByteStreams.newDataInput(packet.data); EntityPlayer entityplayer = (EntityPlayer)player; if(packet.channel.equals("Mekanism")) { try { int packetIndex = dataStream.readInt(); if(packets.get(packetIndex) == null) { System.err.println("[Mekanism] Received unknown packet identifier '" + packetIndex + ".' Ignorning!"); return; } IMekanismPacket packetType = packets.get(packetIndex).newInstance(); if(packetType == null) { System.err.println("[Mekanism] Unable to create instance of packet type '" + packetIndex + ".' Ignoring!"); return; } try { packetType.read(dataStream, entityplayer, entityplayer.worldObj); } catch(Exception e) { System.err.println("[Mekanism] Error while reading '" + packetType.getName() + "' packet."); } } catch(Exception e) { System.err.println("[Mekanism] Error while handling packet."); e.printStackTrace(); } } } public static void registerPacket(Class packetClass) { for(Class iteration : packets) { if(iteration == packetClass) { return; } } packets.add(packetClass); } public static void encode(Object[] dataValues, DataOutputStream output, int ignore) { int iterations = 0; try { for(Object data : dataValues) { if(iterations++ < ignore) { continue; } if(data instanceof Integer) { output.writeInt((Integer)data); } else if(data instanceof Boolean) { output.writeBoolean((Boolean)data); } else if(data instanceof Double) { output.writeDouble((Double)data); } else if(data instanceof Float) { output.writeFloat((Float)data); } else if(data instanceof String) { output.writeUTF((String)data); } else if(data instanceof Byte) { output.writeByte((Byte)data); } else if(data instanceof int[]) { for(int i : (int[])data) { output.writeInt(i); } } else if(data instanceof byte[]) { for(byte b : (byte[])data) { output.writeByte(b); } } else if(data instanceof ArrayList) { encode(((ArrayList)data).toArray(), output, 0); } } } catch(Exception e) { System.err.println("[Mekanism] Error while encoding packet data."); e.printStackTrace(); } } public static void sendPacket(Transmission trans, IMekanismPacket packetType, Object... transParams) { if(packetType == null) { System.err.println("[Mekanism] Attempted to send null packet, ignoring!"); return; } if(!packets.contains(packetType.getClass())) { System.err.println("[Mekanism] Attempted to send unregistered packet '" + packetType.getName() + ",' ignoring!"); return; } ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream(bytes); try { data.writeInt(packets.indexOf(packetType.getClass())); packetType.write(data); } catch(Exception e) { System.err.println("[Mekanism] Error while encoding packet data."); e.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "Mekanism"; packet.data = bytes.toByteArray(); packet.length = packet.data.length; switch(trans) { case SERVER: PacketDispatcher.sendPacketToServer(packet); break; case ALL_CLIENTS: PacketDispatcher.sendPacketToAllPlayers(packet); break; case CLIENTS_RANGE: Object3D obj = (Object3D)transParams[0]; PacketDispatcher.sendPacketToAllAround(obj.xCoord, obj.yCoord, obj.zCoord, (Double)transParams[1], obj.dimensionId, packet); break; case SINGLE_CLIENT: ((EntityPlayerMP)transParams[0]).playerNetServerHandler.sendPacketToPlayer(packet); break; } log(trans, packetType, transParams); } private static void log(Transmission trans, IMekanismPacket packetType, Object[] transParams) { if(Mekanism.logPackets) { switch(trans) { case SERVER: System.out.println("[Mekanism] Sent '" + packetType.getName() + "' packet to server."); break; case ALL_CLIENTS: System.out.println("[Mekanism] Sent '" + packetType.getName() + "' packet to all clients."); break; case CLIENTS_RANGE: System.out.println("[Mekanism] Sent '" + packetType.getName() + "' packet to clients in a " + (Double)transParams[1] + " block range."); break; case SINGLE_CLIENT: System.out.println("[Mekanism] Sent '" + packetType.getName() + "' packet to " + ((EntityPlayer)transParams[0]).username); break; } } } public static enum Transmission { /** No additional parameters. */ SERVER(0), /** No additional parameters. */ ALL_CLIENTS(0), /** 2 parameters - Object3D representing the location of the transmission, and a double of the distance this packet can be sent in. */ CLIENTS_RANGE(2), /** 1 parameter - EntityPlayer to send this packet to. */ SINGLE_CLIENT(1); public int parameters; private Transmission(int params) { parameters = params; } } }