package net.minecraft.network.packet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IntHashMap;
public abstract class Packet
{
/** Maps packet id to packet class */
public static IntHashMap packetIdToClassMap = new IntHashMap();
/** Maps packet class to packet id */
private static Map packetClassToIdMap = new HashMap();
/** List of the client's packet IDs. */
private static Set clientPacketIdList = new HashSet();
/** List of the server's packet IDs. */
private static Set serverPacketIdList = new HashSet();
/** the system time in milliseconds when this packet was created. */
public final long creationTimeMillis = System.currentTimeMillis();
public static long receivedID;
public static long receivedSize;
/** Assumed to be sequential by the profiler. */
public static long sentID;
public static long sentSize;
/**
* Only true for Packet51MapChunk, Packet52MultiBlockChange, Packet53BlockChange and Packet59ComplexEntity. Used to
* separate them into a different send queue.
*/
public boolean isChunkDataPacket = false;
/**
* Adds a two way mapping between the packet ID and packet class.
*/
public static void addIdClassMapping(int par0, boolean par1, boolean par2, Class par3Class)
{
if (packetIdToClassMap.containsItem(par0))
{
throw new IllegalArgumentException("Duplicate packet id:" + par0);
}
else if (packetClassToIdMap.containsKey(par3Class))
{
throw new IllegalArgumentException("Duplicate packet class:" + par3Class);
}
else
{
packetIdToClassMap.addKey(par0, par3Class);
packetClassToIdMap.put(par3Class, Integer.valueOf(par0));
if (par1)
{
clientPacketIdList.add(Integer.valueOf(par0));
}
if (par2)
{
serverPacketIdList.add(Integer.valueOf(par0));
}
}
}
/**
* Returns a new instance of the specified Packet class.
*/
public static Packet getNewPacket(int par0)
{
try
{
Class var1 = (Class)packetIdToClassMap.lookup(par0);
return var1 == null ? null : (Packet)var1.newInstance();
}
catch (Exception var2)
{
var2.printStackTrace();
System.out.println("Skipping packet with id " + par0);
return null;
}
}
/**
* Writes a byte array to the DataOutputStream
*/
public static void writeByteArray(DataOutputStream par0DataOutputStream, byte[] par1ArrayOfByte) throws IOException
{
par0DataOutputStream.writeShort(par1ArrayOfByte.length);
par0DataOutputStream.write(par1ArrayOfByte);
}
/**
* the first short in the stream indicates the number of bytes to read
*/
public static byte[] readBytesFromStream(DataInputStream par0DataInputStream) throws IOException
{
short var1 = par0DataInputStream.readShort();
if (var1 < 0)
{
throw new IOException("Key was smaller than nothing! Weird key!");
}
else
{
byte[] var2 = new byte[var1];
par0DataInputStream.read(var2);
return var2;
}
}
/**
* Returns the ID of this packet.
*/
public final int getPacketId()
{
return ((Integer)packetClassToIdMap.get(this.getClass())).intValue();
}
/**
* Read a packet, prefixed by its ID, from the data stream.
*/
public static Packet readPacket(DataInputStream par0DataInputStream, boolean par1, Socket par2Socket) throws IOException
{
boolean var3 = false;
Packet var4 = null;
int var5 = par2Socket.getSoTimeout();
int var8;
try
{
var8 = par0DataInputStream.read();
if (var8 == -1)
{
return null;
}
if (par1 && !serverPacketIdList.contains(Integer.valueOf(var8)) || !par1 && !clientPacketIdList.contains(Integer.valueOf(var8)))
{
throw new IOException("Bad packet id " + var8);
}
var4 = getNewPacket(var8);
if (var4 == null)
{
throw new IOException("Bad packet id " + var8);
}
if (var4 instanceof Packet254ServerPing)
{
par2Socket.setSoTimeout(1500);
}
var4.readPacketData(par0DataInputStream);
++receivedID;
receivedSize += (long)var4.getPacketSize();
}
catch (EOFException var7)
{
System.out.println("Reached end of stream");
return null;
}
PacketCount.countPacket(var8, (long)var4.getPacketSize());
++receivedID;
receivedSize += (long)var4.getPacketSize();
par2Socket.setSoTimeout(var5);
return var4;
}
/**
* Writes a packet, prefixed by its ID, to the data stream.
*/
public static void writePacket(Packet par0Packet, DataOutputStream par1DataOutputStream) throws IOException
{
par1DataOutputStream.write(par0Packet.getPacketId());
par0Packet.writePacketData(par1DataOutputStream);
++sentID;
sentSize += (long)par0Packet.getPacketSize();
}
/**
* Writes a String to the DataOutputStream
*/
public static void writeString(String par0Str, DataOutputStream par1DataOutputStream) throws IOException
{
if (par0Str.length() > 32767)
{
throw new IOException("String too big");
}
else
{
par1DataOutputStream.writeShort(par0Str.length());
par1DataOutputStream.writeChars(par0Str);
}
}
/**
* Reads a string from a packet
*/
public static String readString(DataInputStream par0DataInputStream, int par1) throws IOException
{
short var2 = par0DataInputStream.readShort();
if (var2 > par1)
{
throw new IOException("Received string length longer than maximum allowed (" + var2 + " > " + par1 + ")");
}
else if (var2 < 0)
{
throw new IOException("Received string length is less than zero! Weird string!");
}
else
{
StringBuilder var3 = new StringBuilder();
for (int var4 = 0; var4 < var2; ++var4)
{
var3.append(par0DataInputStream.readChar());
}
return var3.toString();
}
}
/**
* Abstract. Reads the raw packet data from the data stream.
*/
public abstract void readPacketData(DataInputStream var1) throws IOException;
/**
* Abstract. Writes the raw packet data to the data stream.
*/
public abstract void writePacketData(DataOutputStream var1) throws IOException;
/**
* Passes this Packet on to the NetHandler for processing.
*/
public abstract void processPacket(NetHandler var1);
/**
* Abstract. Return the size of the packet (not counting the header).
*/
public abstract int getPacketSize();
/**
* only false for the abstract Packet class, all real packets return true
*/
public boolean isRealPacket()
{
return false;
}
/**
* eg return packet30entity.entityId == entityId; WARNING : will throw if you compare a packet to a different packet
* class
*/
public boolean containsSameEntityIDAs(Packet par1Packet)
{
return false;
}
/**
* If this returns true, the packet may be processed on any thread; otherwise it is queued for the main thread to
* handle.
*/
public boolean canProcessAsync()
{
return false;
}
public String toString()
{
String var1 = this.getClass().getSimpleName();
return var1;
}
/**
* Reads a ItemStack from the InputStream
*/
public static ItemStack readItemStack(DataInputStream par0DataInputStream) throws IOException
{
ItemStack var1 = null;
short var2 = par0DataInputStream.readShort();
if (var2 >= 0)
{
byte var3 = par0DataInputStream.readByte();
short var4 = par0DataInputStream.readShort();
var1 = new ItemStack(var2, var3, var4);
var1.stackTagCompound = readNBTTagCompound(par0DataInputStream);
}
return var1;
}
/**
* Writes the ItemStack's ID (short), then size (byte), then damage. (short)
*/
public static void writeItemStack(ItemStack par0ItemStack, DataOutputStream par1DataOutputStream) throws IOException
{
if (par0ItemStack == null)
{
par1DataOutputStream.writeShort(-1);
}
else
{
par1DataOutputStream.writeShort(par0ItemStack.itemID);
par1DataOutputStream.writeByte(par0ItemStack.stackSize);
par1DataOutputStream.writeShort(par0ItemStack.getItemDamage());
NBTTagCompound var2 = null;
if (par0ItemStack.getItem().isDamageable() || par0ItemStack.getItem().getShareTag())
{
var2 = par0ItemStack.stackTagCompound;
}
writeNBTTagCompound(var2, par1DataOutputStream);
}
}
/**
* Reads a compressed NBTTagCompound from the InputStream
*/
public static NBTTagCompound readNBTTagCompound(DataInputStream par0DataInputStream) throws IOException
{
short var1 = par0DataInputStream.readShort();
if (var1 < 0)
{
return null;
}
else
{
byte[] var2 = new byte[var1];
par0DataInputStream.readFully(var2);
return CompressedStreamTools.decompress(var2);
}
}
/**
* Writes a compressed NBTTagCompound to the OutputStream
*/
protected static void writeNBTTagCompound(NBTTagCompound par0NBTTagCompound, DataOutputStream par1DataOutputStream) throws IOException
{
if (par0NBTTagCompound == null)
{
par1DataOutputStream.writeShort(-1);
}
else
{
byte[] var2 = CompressedStreamTools.compress(par0NBTTagCompound);
par1DataOutputStream.writeShort((short)var2.length);
par1DataOutputStream.write(var2);
}
}
static
{
addIdClassMapping(0, true, true, Packet0KeepAlive.class);
addIdClassMapping(1, true, true, Packet1Login.class);
addIdClassMapping(2, false, true, Packet2ClientProtocol.class);
addIdClassMapping(3, true, true, Packet3Chat.class);
addIdClassMapping(4, true, false, Packet4UpdateTime.class);
addIdClassMapping(5, true, false, Packet5PlayerInventory.class);
addIdClassMapping(6, true, false, Packet6SpawnPosition.class);
addIdClassMapping(7, false, true, Packet7UseEntity.class);
addIdClassMapping(8, true, false, Packet8UpdateHealth.class);
addIdClassMapping(9, true, true, Packet9Respawn.class);
addIdClassMapping(10, true, true, Packet10Flying.class);
addIdClassMapping(11, true, true, Packet11PlayerPosition.class);
addIdClassMapping(12, true, true, Packet12PlayerLook.class);
addIdClassMapping(13, true, true, Packet13PlayerLookMove.class);
addIdClassMapping(14, false, true, Packet14BlockDig.class);
addIdClassMapping(15, false, true, Packet15Place.class);
addIdClassMapping(16, true, true, Packet16BlockItemSwitch.class);
addIdClassMapping(17, true, false, Packet17Sleep.class);
addIdClassMapping(18, true, true, Packet18Animation.class);
addIdClassMapping(19, false, true, Packet19EntityAction.class);
addIdClassMapping(20, true, false, Packet20NamedEntitySpawn.class);
addIdClassMapping(22, true, false, Packet22Collect.class);
addIdClassMapping(23, true, false, Packet23VehicleSpawn.class);
addIdClassMapping(24, true, false, Packet24MobSpawn.class);
addIdClassMapping(25, true, false, Packet25EntityPainting.class);
addIdClassMapping(26, true, false, Packet26EntityExpOrb.class);
addIdClassMapping(28, true, false, Packet28EntityVelocity.class);
addIdClassMapping(29, true, false, Packet29DestroyEntity.class);
addIdClassMapping(30, true, false, Packet30Entity.class);
addIdClassMapping(31, true, false, Packet31RelEntityMove.class);
addIdClassMapping(32, true, false, Packet32EntityLook.class);
addIdClassMapping(33, true, false, Packet33RelEntityMoveLook.class);
addIdClassMapping(34, true, false, Packet34EntityTeleport.class);
addIdClassMapping(35, true, false, Packet35EntityHeadRotation.class);
addIdClassMapping(38, true, false, Packet38EntityStatus.class);
addIdClassMapping(39, true, false, Packet39AttachEntity.class);
addIdClassMapping(40, true, false, Packet40EntityMetadata.class);
addIdClassMapping(41, true, false, Packet41EntityEffect.class);
addIdClassMapping(42, true, false, Packet42RemoveEntityEffect.class);
addIdClassMapping(43, true, false, Packet43Experience.class);
addIdClassMapping(51, true, false, Packet51MapChunk.class);
addIdClassMapping(52, true, false, Packet52MultiBlockChange.class);
addIdClassMapping(53, true, false, Packet53BlockChange.class);
addIdClassMapping(54, true, false, Packet54PlayNoteBlock.class);
addIdClassMapping(55, true, false, Packet55BlockDestroy.class);
addIdClassMapping(56, true, false, Packet56MapChunks.class);
addIdClassMapping(60, true, false, Packet60Explosion.class);
addIdClassMapping(61, true, false, Packet61DoorChange.class);
addIdClassMapping(62, true, false, Packet62LevelSound.class);
addIdClassMapping(70, true, false, Packet70GameEvent.class);
addIdClassMapping(71, true, false, Packet71Weather.class);
addIdClassMapping(100, true, false, Packet100OpenWindow.class);
addIdClassMapping(101, true, true, Packet101CloseWindow.class);
addIdClassMapping(102, false, true, Packet102WindowClick.class);
addIdClassMapping(103, true, false, Packet103SetSlot.class);
addIdClassMapping(104, true, false, Packet104WindowItems.class);
addIdClassMapping(105, true, false, Packet105UpdateProgressbar.class);
addIdClassMapping(106, true, true, Packet106Transaction.class);
addIdClassMapping(107, true, true, Packet107CreativeSetSlot.class);
addIdClassMapping(108, false, true, Packet108EnchantItem.class);
addIdClassMapping(130, true, true, Packet130UpdateSign.class);
addIdClassMapping(131, true, true, Packet131MapData.class);
addIdClassMapping(132, true, false, Packet132TileEntityData.class);
addIdClassMapping(200, true, false, Packet200Statistic.class);
addIdClassMapping(201, true, false, Packet201PlayerInfo.class);
addIdClassMapping(202, true, true, Packet202PlayerAbilities.class);
addIdClassMapping(203, true, true, Packet203AutoComplete.class);
addIdClassMapping(204, false, true, Packet204ClientInfo.class);
addIdClassMapping(205, false, true, Packet205ClientCommand.class);
addIdClassMapping(250, true, true, Packet250CustomPayload.class);
addIdClassMapping(252, true, true, Packet252SharedKey.class);
addIdClassMapping(253, true, false, Packet253ServerAuthData.class);
addIdClassMapping(254, false, true, Packet254ServerPing.class);
addIdClassMapping(255, true, true, Packet255KickDisconnect.class);
}
}