Add conversion methods to WirePacket

This commit is contained in:
Dan Mulloy 2016-07-06 15:47:43 -04:00
parent 242b25eb1e
commit 26c29d9c85

View File

@ -16,30 +16,71 @@
*/ */
package com.comphenix.protocol.injector.netty; package com.comphenix.protocol.injector.netty;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.Method;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
/** /**
* A packet represented only by its id and bytes.
* @author dmulloy2 * @author dmulloy2
*/ */
public class WirePacket { public class WirePacket {
private final int id; private final int id;
private final byte[] bytes; private final byte[] bytes;
/**
* Constructs a new WirePacket with a given type and contents
* @param type Type of the packet
* @param bytes Contents of the packet
*/
public WirePacket(PacketType type, byte[] bytes) {
this.id = checkNotNull(type, "type cannot be null").getCurrentId();
this.bytes = bytes;
}
/**
* Constructs a new WirePacket with a given id and contents
* @param id ID of the packet
* @param bytes Contents of the packet
*/
public WirePacket(int id, byte[] bytes) { public WirePacket(int id, byte[] bytes) {
this.id = id; this.id = id;
this.bytes = bytes; this.bytes = bytes;
} }
/**
* Gets this packet's ID
* @return The ID
*/
public int getId() { public int getId() {
return id; return id;
} }
/**
* Gets this packet's contents as a byte array
* @return The contents
*/
public byte[] getBytes() { public byte[] getBytes() {
return bytes; return bytes;
} }
/**
* Writes the id of this packet to a given output
* @param output Output to write to
*/
public void writeId(ByteBuf output) { public void writeId(ByteBuf output) {
checkNotNull(output, "output cannot be null!");
// From PacketDataSerializer#d(int)
int i = id; int i = id;
while ((i & -128) != 0) { while ((i & -128) != 0) {
output.writeByte(i & 127 | 128); output.writeByte(i & 127 | 128);
@ -49,7 +90,78 @@ public class WirePacket {
output.writeByte(i); output.writeByte(i);
} }
/**
* Writes the contents of this packet to a given output
* @param output Output to write to
*/
public void writeBytes(ByteBuf output) { public void writeBytes(ByteBuf output) {
checkNotNull(output, "output cannot be null!");
output.writeBytes(bytes); output.writeBytes(bytes);
} }
/**
* Fully writes the ID and contents of this packet to a given output
* @param output Output to write to
*/
public void writeFully(ByteBuf output) {
writeId(output);
writeBytes(output);
}
/**
* Serializes this packet into a byte buffer
* @return The buffer
*/
public ByteBuf serialize() {
ByteBuf buffer = Unpooled.buffer();
writeFully(buffer);
return buffer;
}
/**
* Creates a WirePacket from an existing PacketContainer
* @param packet Existing packet
* @return The resulting WirePacket
*/
public static WirePacket fromPacket(PacketContainer packet) {
checkNotNull(packet, "packet cannot be null!");
int id = packet.getType().getCurrentId();
ByteBuf buffer = PacketContainer.createPacketBuffer();
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
try {
write.invoke(packet.getHandle(), buffer);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to serialize packet contents.", ex);
}
return new WirePacket(id, buffer.array());
}
/**
* Creates a WirePacket from an existing Minecraft packet
* @param packet Existing Minecraft packet
* @return The resulting WirePacket
* @throws IllegalArgumentException If the packet is null or not a Minecraft packet
*/
public static WirePacket fromPacket(Object packet) {
checkNotNull(packet, "packet cannot be null!");
checkArgument(MinecraftReflection.isPacketClass(packet), "packet must be a Minecraft packet");
PacketType type = PacketType.fromClass(packet.getClass());
int id = type.getCurrentId();
ByteBuf buffer = PacketContainer.createPacketBuffer();
Method write = MinecraftMethods.getPacketWriteByteBufMethod();
try {
write.invoke(packet, buffer);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Failed to serialize packet contents.", ex);
}
return new WirePacket(id, buffer.array());
}
} }