Implement Optional UUIDs

Implement Meta Rewriting
Implement Type Converters

Implement System so it can be tested.

Most of it works excluding the missing packets, also fixes some stupid mistakes :)
This commit is contained in:
Myles 2016-03-15 00:34:20 +00:00
parent 89427cb2da
commit c300c47a14
31 changed files with 540 additions and 85 deletions

View File

@ -60,29 +60,7 @@ public class ChunkManager {
* @param packet to transform
* @return List of chunk data packets
*/
public List<Object> transformMapChunkBulk(Object packet) {
List<Object> list = Lists.newArrayList();
try {
int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class);
int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class);
Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class);
for(int i = 0; i < chunkMaps.length; i++) {
int x = xcoords[i];
int z = zcoords[i];
Object chunkMap = chunkMaps[i];
Object chunkPacket = mapChunkRef.newInstance();
mapChunkRef.setFieldValue("a", chunkPacket, x);
mapChunkRef.setFieldValue("b", chunkPacket, z);
mapChunkRef.setFieldValue("c", chunkPacket, chunkMap);
mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up
bulkChunks.add(toLong(x, z)); // Store for later
list.add(chunkPacket);
}
} catch(Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunk bulk", e);
}
return list;
}
/**
* Read chunk from 1.8 chunk data.

View File

@ -3,17 +3,15 @@ package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.ClientChunks;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class ViaChunkHandler extends MessageToMessageEncoder {
private final ConnectionInfo info;
private final UserConnection info;
public ViaChunkHandler(ConnectionInfo info) {
public ViaChunkHandler(UserConnection info) {
this.info = info;
}
@ -26,7 +24,7 @@ public class ViaChunkHandler extends MessageToMessageEncoder {
info.setLastPacket(o);
/* This transformer is more for fixing issues which we find hard at packet level :) */
if(o.getClass().getName().endsWith("PacketPlayOutMapChunkBulk") && info.isActive()) {
list.addAll(info.getChunkManager().transformMapChunkBulk(o));
list.addAll(info.get(ClientChunks.class).transformMapChunkBulk(o));
return;
}
}

View File

@ -4,22 +4,22 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.transformers.IncomingTransformer;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import java.util.List;
public class ViaDecodeHandler extends ByteToMessageDecoder {
private final IncomingTransformer incomingTransformer;
private final ByteToMessageDecoder minecraftDecoder;
private final ConnectionInfo info;
private final UserConnection info;
public ViaDecodeHandler(ConnectionInfo info, ByteToMessageDecoder minecraftDecoder) {
public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
this.info = info;
this.minecraftDecoder = minecraftDecoder;
this.incomingTransformer = new IncomingTransformer(info);
}
@Override
@ -29,9 +29,14 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
if (info.isActive()) {
int id = PacketUtil.readVarInt(bytebuf);
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
incomingTransformer.transform(id, bytebuf, newPacket);
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper);
ByteBuf newPacket = ctx.alloc().buffer();
wrapper.writeToBuffer(newPacket);
bytebuf.clear();
bytebuf = newPacket;
} catch (Exception e) {

View File

@ -5,22 +5,24 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol.base.ProtocolInfo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ViaEncodeHandler extends MessageToByteEncoder {
private final ConnectionInfo info;
private final UserConnection info;
private final MessageToByteEncoder minecraftEncoder;
private final OutgoingTransformer outgoingTransformer;
public ViaEncodeHandler(ConnectionInfo info, MessageToByteEncoder minecraftEncoder) {
public ViaEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
this.info = info;
this.minecraftEncoder = minecraftEncoder;
this.outgoingTransformer = new OutgoingTransformer(info);
}
@ -40,7 +42,10 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
ByteBuf oldPacket = bytebuf.copy();
bytebuf.clear();
try {
outgoingTransformer.transform(id, oldPacket, bytebuf);
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
wrapper.writeToBuffer(bytebuf);
} catch (Exception e) {
bytebuf.clear();
throw e;

View File

@ -5,7 +5,8 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol.ProtocolPipeline;
import java.lang.reflect.Method;
@ -26,7 +27,10 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ConnectionInfo info = new ConnectionInfo(socketChannel);
UserConnection info = new UserConnection(socketChannel);
// init protocol
System.out.println("init pipeline");
new ProtocolPipeline(info);
// Add originals
this.method.invoke(this.oldInit, socketChannel);
// Add our transformers

View File

@ -24,7 +24,7 @@ public enum PacketType {
STATUS_RESPONSE(State.STATUS, Direction.OUTGOING, 0x00),
STATUS_PONG(State.STATUS, Direction.OUTGOING, 0x01),
/* Play serverbound */
PLAY_TP_CONFIRM(State.PLAY, Direction.INCOMING, -1, 0x00), // TODO
PLAY_TP_CONFIRM(State.PLAY, Direction.INCOMING, -1, 0x00), // Mapped
PLAY_TAB_COMPLETE_REQUEST(State.PLAY, Direction.INCOMING, 0x14, 0x01), // Mapped
PLAY_CHAT_MESSAGE_CLIENT(State.PLAY, Direction.INCOMING, 0x01, 0x02), // Mapped
PLAY_CLIENT_STATUS(State.PLAY, Direction.INCOMING, 0x16, 0x03), // Mapped
@ -40,8 +40,8 @@ public enum PacketType {
PLAY_PLAYER_POSITION_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x06, 0x0D), // Mapped
PLAY_PLAYER_LOOK_REQUEST(State.PLAY, Direction.INCOMING, 0x05, 0x0E), // Mapped
PLAY_PLAYER(State.PLAY, Direction.INCOMING, 0x03, 0x0F), // Mapped
PLAY_VEHICLE_MOVE_REQUEST(State.PLAY, Direction.INCOMING, -1, 0x10), // TODO
PLAY_STEER_BOAT(State.PLAY, Direction.INCOMING, -1, 0x11), // TODO
PLAY_VEHICLE_MOVE_REQUEST(State.PLAY, Direction.INCOMING, -1, 0x10), // Mapped
PLAY_STEER_BOAT(State.PLAY, Direction.INCOMING, -1, 0x11), // Mapped
PLAY_PLAYER_ABILITIES_REQUEST(State.PLAY, Direction.INCOMING, 0x13, 0x12), // Mapped
PLAY_PLAYER_DIGGING(State.PLAY, Direction.INCOMING, 0x07, 0x13), // Mapped
PLAY_ENTITY_ACTION(State.PLAY, Direction.INCOMING, 0x0B, 0x14), // Mapped
@ -55,7 +55,7 @@ public enum PacketType {
PLAY_ANIMATION_REQUEST(State.PLAY, Direction.INCOMING, 0x0A, 0x1A), // Mapped
PLAY_SPECTATE(State.PLAY, Direction.INCOMING, 0x18, 0x1B), // Mapped
PLAY_PLAYER_BLOCK_PLACEMENT(State.PLAY, Direction.INCOMING, 0x08, 0x1C), // Mapped
PLAY_USE_ITEM(State.PLAY, Direction.INCOMING, -1, 0x1D), // TODO
PLAY_USE_ITEM(State.PLAY, Direction.INCOMING, -1, 0x1D), // Mapped
/* Play clientbound */
PLAY_SPAWN_OBJECT(State.PLAY, Direction.OUTGOING, 0x0E, 0x00), // Mapped
PLAY_SPAWN_XP_ORB(State.PLAY, Direction.OUTGOING, 0x11, 0x01), // Mapped

View File

@ -2,11 +2,13 @@ package us.myles.ViaVersion2.api;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.remapper.ValueCreator;
import us.myles.ViaVersion2.api.type.Type;
import us.myles.ViaVersion2.api.type.TypeConverter;
import us.myles.ViaVersion2.api.util.Pair;
import java.io.IOException;
@ -60,7 +62,6 @@ public class PacketWrapper {
public <T> T read(Type<T> type) throws Exception {
if (readableObjects.isEmpty()) {
Preconditions.checkNotNull(inputBuffer, "This packet does not have an input buffer.");
System.out.println("Reading: " + type.getTypeName());
// We could in the future log input read values, but honestly for things like bulk maps, mem waste D:
return type.read(inputBuffer);
} else {
@ -75,7 +76,6 @@ public class PacketWrapper {
public <T> void write(Type<T> type, T value) {
System.out.println("Writing " + type.getTypeName() + " - " + value);
packetValues.add(new Pair<Type, Object>(type, value));
}
@ -89,22 +89,44 @@ public class PacketWrapper {
if (id != -1) {
Type.VAR_INT.write(buffer, id);
}
int index = 0;
for (Pair<Type, Object> packetValue : packetValues) {
packetValue.getKey().write(buffer, packetValue.getValue());
System.out.println("writing: " + packetValue.getKey().getTypeName() + " value: " + packetValue.getValue() + " ID: " + getId());
try {
Object value = packetValue.getValue();
if(value != null) {
if (!value.getClass().equals(packetValue.getKey().getOutputClass())) {
// attempt conversion
if (packetValue.getKey() instanceof TypeConverter) {
value = ((TypeConverter) packetValue.getKey()).from(value);
} else {
System.out.println("Possible type mismatch: " + value.getClass().getName() + " -> " + packetValue.getKey().getTypeName());
}
}
}
packetValue.getKey().write(buffer, value);
}catch (Exception e){
System.out.println(getId() + " Index: " + index + " Type: " + packetValue.getKey().getTypeName());
throw e;
}
index++;
}
if(packetValues.size() != 0){
if(inputBuffer != null){
System.out.println(">> Writing remaining: " + inputBuffer.readableBytes() + " ID: " + getId());
}
}
writeRemaining(buffer);
}
private void writeRemaining(ByteBuf output) {
if (inputBuffer != null) {
System.out.println("Writing remaining: " + output.readableBytes());
output.writeBytes(inputBuffer);
}
}
public void send() throws Exception {
ByteBuf output = inputBuffer.alloc().buffer();
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
writeToBuffer(output);
user().sendRawPacket(output);
}

View File

@ -3,13 +3,22 @@ package us.myles.ViaVersion2.api.data;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.SocketChannel;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
public class UserConnection {
private final SocketChannel channel;
List<StoredObject> storedObjects = new ArrayList<>();
@Getter
@Setter
private boolean active = true;
private final SocketChannel channel;
@Getter
@Setter
private Object lastPacket;
public UserConnection(SocketChannel socketChannel) {
this.channel = socketChannel;

View File

@ -9,7 +9,8 @@ import us.myles.ViaVersion2.api.type.Type;
@Getter
@Setter
public class Metadata {
private final int id;
private int id;
private int typeID;
private Type type;
private Object value;
}

View File

@ -7,6 +7,7 @@ import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.util.Pair;
@ -50,7 +51,6 @@ public abstract class Protocol {
if (packetMap.containsKey(statePacket)) {
protocolPacket = packetMap.get(statePacket);
} else {
System.out.println("Packet not found: " + packetWrapper.getId());
return;
}
// write packet id
@ -58,6 +58,7 @@ public abstract class Protocol {
packetWrapper.setId(newID);
// remap
if (protocolPacket.getRemapper() != null) {
System.out.println("Remapping for " + getClass().getName() + " - " + newID + "<- " + direction + " " + state);
protocolPacket.getRemapper().remap(packetWrapper);
if(packetWrapper.isCancelled())
throw new CancelException();

View File

@ -1,7 +1,5 @@
package us.myles.ViaVersion2.api.protocol;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
@ -13,16 +11,25 @@ import java.util.ArrayList;
import java.util.LinkedList;
public class ProtocolPipeline extends Protocol {
LinkedList<Protocol> protocolList = new LinkedList<>();
LinkedList<Protocol> protocolList;
private UserConnection userConnection;
public ProtocolPipeline(UserConnection userConnection) {
super();
init(userConnection);
}
@Override
protected void registerPackets() {
protocolList = new LinkedList<>();
// This is a pipeline so we register basic pipes
protocolList.addLast(new BaseProtocol());
}
@Override
public void init(UserConnection userConnection) {
this.userConnection = userConnection;
ProtocolInfo protocolInfo = new ProtocolInfo();
protocolInfo.setPipeline(this);
@ -34,14 +41,25 @@ public class ProtocolPipeline extends Protocol {
}
}
public void add(Protocol protocol) {
if (protocolList != null) {
System.out.println("Adding protocol to list!!");
protocolList.addLast(protocol);
protocol.init(userConnection);
} else {
throw new NullPointerException("Tried to add protocol to early");
}
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
// System.out.println("--> Packet ID incoming: " + packetWrapper.getId() + " - " + state);
for (Protocol protocol : new ArrayList<>(protocolList)) { // Copy to prevent from removal.
protocol.transform(direction, state, packetWrapper);
// Reset the reader for the packetWrapper (So it can be recycled across packets)
packetWrapper.resetReader();
}
super.transform(direction, state, packetWrapper);
System.out.println("--> Sending Packet ID: " + packetWrapper.getId() + " " + state + " " + direction);
}
}

View File

@ -8,6 +8,7 @@ import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.data.UserConnection;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.type.Type;
@ -56,6 +57,7 @@ public class BaseProtocol extends Protocol {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) {
System.out.println("play state");
ProtocolInfo info = wrapper.user().get(ProtocolInfo.class);
info.setState(State.PLAY);
UUID uuid = UUID.fromString(wrapper.get(Type.STRING, 0));
@ -85,7 +87,10 @@ public class BaseProtocol extends Protocol {
ProtocolInfo info = wrapper.user().get(ProtocolInfo.class);
info.setProtocolVersion(protVer);
// TODO: Choose the right pipe
// We'll just cheat lol
wrapper.user().get(ProtocolInfo.class).getPipeline().add(new Protocol1_9TO1_8());
System.out.println("I should decide on a protocol for " + protVer);
wrapper.set(Type.VAR_INT, 0, 47); // TODO remove hard code
// Change state
int state = wrapper.get(Type.VAR_INT, 1);
if (state == 1) {

View File

@ -47,6 +47,7 @@ public class Protocol1_9TO1_8 extends Protocol {
@Override
protected void registerPackets() {
System.out.println("Registering packets for 1.9 to 1.8");
SpawnPackets.register(this);
InventoryPackets.register(this);
EntityPackets.register(this);

View File

@ -0,0 +1,162 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.metadata;
import org.bukkit.entity.EntityType;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.metadata.MetaIndex;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.metadata.Type;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion2.api.metadata.Metadata;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MetadataRewriter {
public static void transform(EntityType type, List<Metadata> list) {
short id = -1;
int data = -1;
for (Metadata entry : new ArrayList<>(list)) {
MetaIndex metaIndex = MetaIndex.getIndex(type, entry.getId());
try {
if (metaIndex.getNewType() != NewType.Discontinued) {
if (metaIndex.getNewType() != NewType.BlockID || id != -1 && data == -1 || id == -1 && data != -1) { // block ID is only written if we have both parts
entry.setId(metaIndex.getNewIndex());
entry.setTypeID(metaIndex.getNewType().getTypeID());
}
Object value = entry.getValue();
switch (metaIndex.getNewType()) {
case Byte:
entry.setType(us.myles.ViaVersion2.api.type.Type.BYTE);
// convert from int, byte
if (metaIndex.getOldType() == Type.Byte) {
entry.setValue(value);
}
if (metaIndex.getOldType() == Type.Int) {
entry.setValue(((Integer) value).byteValue());
}
// After writing the last one
if (metaIndex == MetaIndex.ENTITY_STATUS && type == EntityType.PLAYER) {
Byte val = 0;
if ((((Byte) value) & 0x10) == 0x10) { // Player eating/aiming/drinking
val = 1;
}
int newIndex = MetaIndex.PLAYER_HAND.getNewIndex();
int typeID = MetaIndex.PLAYER_HAND.getNewType().getTypeID();
Metadata metadata = new Metadata(newIndex, typeID, us.myles.ViaVersion2.api.type.Type.BYTE, val);
// list.add(metadata);
}
break;
case OptUUID:
entry.setType(us.myles.ViaVersion2.api.type.Type.OPTIONAL_UUID);
String owner = (String) value;
UUID toWrite = null;
if (owner.length() != 0) {
try {
toWrite = UUID.fromString(owner);
} catch (Exception ignored) {
}
}
entry.setValue(toWrite);
break;
case BlockID:
entry.setType(us.myles.ViaVersion2.api.type.Type.VAR_INT);
// if we have both sources :))
if (metaIndex.getOldType() == Type.Byte) {
data = (Byte) value;
}
if (metaIndex.getOldType() == Type.Short) {
id = (Short) value;
}
if (id != -1 && data != -1) {
int combined = id << 4 | data;
data = -1;
id = -1;
entry.setValue(combined);
} else {
list.remove(entry);
}
break;
case VarInt:
entry.setType(us.myles.ViaVersion2.api.type.Type.VAR_INT);
// convert from int, short, byte
if (metaIndex.getOldType() == Type.Byte) {
entry.setValue(((Byte) value).intValue());
}
if (metaIndex.getOldType() == Type.Short) {
entry.setValue(((Short) value).intValue());
}
if (metaIndex.getOldType() == Type.Int) {
entry.setValue(value);
}
break;
case Float:
entry.setType(us.myles.ViaVersion2.api.type.Type.FLOAT);
entry.setValue(value);
break;
case String:
entry.setType(us.myles.ViaVersion2.api.type.Type.STRING);
entry.setValue(value);
break;
case Boolean:
entry.setType(us.myles.ViaVersion2.api.type.Type.BOOLEAN);
if (metaIndex == MetaIndex.AGEABLE_AGE)
entry.setValue((Byte) value < 0);
else
entry.setValue((Byte) value != 0);
break;
case Slot:
entry.setType(us.myles.ViaVersion2.api.type.Type.ITEM);
entry.setValue(value);
// ItemSlotRewriter.ItemStack item = (ItemSlotRewriter.ItemStack) value;
// ItemSlotRewriter.fixIdsFrom1_8To1_9(item);
// ItemSlotRewriter.writeItemStack(item, output);
// TODO
break;
case Position:
entry.setType(us.myles.ViaVersion2.api.type.Type.VECTOR);
Vector vector = (Vector) value;
entry.setValue(vector);
break;
case Vector3F:
entry.setType(us.myles.ViaVersion2.api.type.Type.ROTATION);
EulerAngle angle = (EulerAngle) value;
entry.setValue(angle);
break;
case Chat:
entry.setType(us.myles.ViaVersion2.api.type.Type.STRING);
value = OutgoingTransformer.fixJson((String) value);
entry.setValue(value);
break;
default:
System.out.println("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
list.remove(entry);
break;
}
System.out.println("List Item: " + entry.getType().getTypeName() + " - " + entry.getValue() + " New Type: " + metaIndex.getNewType());
} else {
list.remove(entry);
}
} catch (Exception e) {
list.remove(entry);
if (!((ViaVersionPlugin) ViaVersion.getInstance()).isSuppressMetadataErrors()) {
System.out.println("INCLUDE THIS IN YOUR ERROR LOG!");
if (type != null)
System.out.println("An error occurred with entity meta data for " + type + " OldID: " + entry.getId());
else
System.out.println("An error occurred with entity meta data for UNKNOWN_ENTITY OldID: " + entry.getId());
if (metaIndex != null) {
System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex());
System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType());
}
e.printStackTrace();
}
}
}
// TODO: Holo patch and bossbar patch
}
}

View File

@ -1,4 +1,4 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8;
package us.myles.ViaVersion2.api.protocol1_9to1_8.metadata;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

View File

@ -4,14 +4,18 @@ import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.metadata.MetadataRewriter;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.remapper.ValueTransformer;
import us.myles.ViaVersion2.api.type.Type;
import java.util.List;
public class EntityPackets {
public static ValueTransformer<Byte, Short> toNewShort = new ValueTransformer<Byte, Short>(Type.SHORT) {
@Override
@ -75,6 +79,7 @@ public class EntityPackets {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
System.out.println("handling holo for tp");
int entityID = wrapper.get(Type.VAR_INT, 0);
if (((ViaVersionPlugin) ViaVersion.getInstance()).isHologramPatch()) {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
@ -86,6 +91,8 @@ public class EntityPackets {
}
}
});
}
});
// Entity Look Move Packet
@ -106,6 +113,7 @@ public class EntityPackets {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
System.out.println("look move");
int entityID = wrapper.get(Type.VAR_INT, 0);
if (((ViaVersionPlugin) ViaVersion.getInstance()).isHologramPatch()) {
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
@ -174,7 +182,19 @@ public class EntityPackets {
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Protocol1_9TO1_8.METADATA_LIST); // 1 - Metadata List
// TODO Transform metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if(tracker.getClientEntityTypes().containsKey(entityID)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityID), metadataList);
}else{
System.out.println("Unable to find entity for metadata, entity ID: " + entityID);
}
}
});
}
});

View File

@ -4,6 +4,7 @@ import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
import us.myles.ViaVersion2.api.remapper.ValueCreator;
import us.myles.ViaVersion2.api.type.Type;
@ -41,7 +42,8 @@ public class InventoryPackets {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.ITEM); // 2 - Slot Value
// TODO Brewing patch
@ -55,6 +57,7 @@ public class InventoryPackets {
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.ITEM_ARRAY); // 1 - Window Values
// TODO Brewing patch
// TODO - ItemStack rewriter
}
@ -115,7 +118,6 @@ public class InventoryPackets {
map(Type.SHORT);
map(Type.BYTE);
map(Type.ITEM);
// TODO: Transform Item Patch
// TODO: Throw elytra and brewing patch
}
@ -140,6 +142,16 @@ public class InventoryPackets {
protocol.registerIncoming(State.PLAY, 0x11, 0x06); // Enchant Item Packet
// TODO Held Item change blocking patch
protocol.registerIncoming(State.PLAY, 0x09, 0x17); // Held Item Change Packet
protocol.registerIncoming(State.PLAY, 0x09, 0x17, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
System.out.println("held item");
}
});
}
}); // Held Item Change Packet
}
}

View File

@ -162,7 +162,6 @@ public class PlayerPackets {
public void handle(PacketWrapper wrapper) throws Exception {
int action = wrapper.get(Type.VAR_INT, 0);
int count = wrapper.get(Type.VAR_INT, 1);
for (int i = 0; i < count; i++) {
wrapper.passthrough(Type.UUID); // Player UUID
if (action == 0) { // add player
@ -213,6 +212,7 @@ public class PlayerPackets {
protocol.registerOutgoing(State.PLAY, 0x48, 0x32); // Resource Pack Send Packet
protocol.registerOutgoing(State.PLAY, 0x07, 0x33); // Respawn Packet
protocol.registerOutgoing(State.PLAY, 0x43, 0x36); // Camera Packet
protocol.registerOutgoing(State.PLAY, 0x2B, 0x1E); // Change Game State Packet
protocol.registerOutgoing(State.PLAY, 0x09, 0x37); // Held Item Change Packet
@ -262,6 +262,58 @@ public class PlayerPackets {
}
});
// TP Confirm
protocol.registerIncoming(State.PLAY, -1, 0x00, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
// Vehicle Move
protocol.registerIncoming(State.PLAY, -1, 0x10, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
// Steer Boat
protocol.registerIncoming(State.PLAY, -1, 0x11, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
// Use Item TODO
protocol.registerIncoming(State.PLAY, -1, 0x1D, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
/* Packets which do not have any field remapping or handlers */
protocol.registerIncoming(State.PLAY, 0x01, 0x02); // Chat Message Packet
@ -277,5 +329,7 @@ public class PlayerPackets {
protocol.registerIncoming(State.PLAY, 0x03, 0x0F); // Player Packet
// TODO Plugin Channels :(
protocol.registerIncoming(State.PLAY, 0x17, 0x09); // plugin message incoming
protocol.registerOutgoing(State.PLAY, 0x3F, 0x18); // plugin message outgoing
}
}

View File

@ -4,8 +4,10 @@ import org.bukkit.entity.EntityType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.util.EntityUtil;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol.Protocol;
import us.myles.ViaVersion2.api.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion2.api.protocol1_9to1_8.metadata.MetadataRewriter;
import us.myles.ViaVersion2.api.protocol1_9to1_8.storage.EntityTracker;
import us.myles.ViaVersion2.api.remapper.PacketHandler;
import us.myles.ViaVersion2.api.remapper.PacketRemapper;
@ -13,6 +15,8 @@ import us.myles.ViaVersion2.api.remapper.ValueCreator;
import us.myles.ViaVersion2.api.remapper.ValueTransformer;
import us.myles.ViaVersion2.api.type.Type;
import java.util.List;
public class SpawnPackets {
public static ValueTransformer<Integer, Double> toNewDouble = new ValueTransformer<Integer, Double>(Type.DOUBLE) {
@Override
@ -62,7 +66,7 @@ public class SpawnPackets {
create(new ValueCreator() {
@Override
public void write(PacketWrapper wrapper) throws Exception {
int data = wrapper.get(Type.INT, 3); // Data (4th Integer)
int data = wrapper.get(Type.INT, 0); // Data (1st Integer)
short vX = 0, vY = 0, vZ = 0;
if (data > 0) {
@ -165,8 +169,21 @@ public class SpawnPackets {
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
// TODO Rewrite Metadata
map(Protocol1_9TO1_8.METADATA_LIST);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if(tracker.getClientEntityTypes().containsKey(entityID)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityID), metadataList);
}else{
System.out.println("Unable to find entity for metadata, entity ID: " + entityID);
}
}
});
}
});
@ -218,8 +235,21 @@ public class SpawnPackets {
map(Type.SHORT, Type.NOTHING); // Current Item is discontinued
// TODO Rewrite Metadata
map(Protocol1_9TO1_8.METADATA_LIST);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadataList = wrapper.get(Protocol1_9TO1_8.METADATA_LIST, 0);
int entityID = wrapper.get(Type.VAR_INT, 0);
EntityTracker tracker = wrapper.user().get(EntityTracker.class);
if(tracker.getClientEntityTypes().containsKey(entityID)) {
MetadataRewriter.transform(tracker.getClientEntityTypes().get(entityID), metadataList);
}else{
System.out.println("Unable to find entity for metadata, entity ID: " + entityID);
}
}
});
}
});

View File

@ -1,5 +1,6 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.packets;
import us.myles.ViaVersion.chunks.Chunk;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion2.api.PacketWrapper;
import us.myles.ViaVersion2.api.protocol.Protocol;
@ -32,6 +33,12 @@ public class WorldPackets {
// Everything else get's written through
// TODO: Effect canceller patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
@ -44,6 +51,12 @@ public class WorldPackets {
// Everything else get's written through
// TODO: Sound Effect translator patch
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
}
});
}
});
@ -53,9 +66,16 @@ public class WorldPackets {
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception{
public void handle(PacketWrapper wrapper) throws Exception {
ClientChunks clientChunks = wrapper.user().get(ClientChunks.class);
wrapper.passthrough(new ChunkType(clientChunks));
Chunk chunk = wrapper.passthrough(new ChunkType(clientChunks));
if (chunk.isUnloadPacket()) {
PacketWrapper unload = wrapper.create(0x1D);
unload.write(Type.INT, chunk.getX());
unload.write(Type.INT, chunk.getZ());
unload.send();
wrapper.cancel();
}
}
});
}
@ -101,7 +121,7 @@ public class WorldPackets {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int status = wrapper.get(Type.UNSIGNED_BYTE, 0);
if(status == 6)
if (status == 6)
wrapper.cancel();
}
});

View File

@ -1,13 +1,59 @@
package us.myles.ViaVersion2.api.protocol1_9to1_8.storage;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Getter;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion2.api.data.StoredObject;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@Getter
public class ClientChunks extends StoredObject {
private final Set<Long> loadedChunks = Sets.newConcurrentHashSet();
private final Set<Long> bulkChunks = Sets.newConcurrentHashSet();
// Reflection
private static ReflectionUtil.ClassReflection mapChunkBulkRef;
private static ReflectionUtil.ClassReflection mapChunkRef;
static {
try {
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunk reflection", e);
}
}
public List<Object> transformMapChunkBulk(Object packet) {
List<Object> list = Lists.newArrayList();
try {
int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class);
int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class);
Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class);
for (int i = 0; i < chunkMaps.length; i++) {
int x = xcoords[i];
int z = zcoords[i];
Object chunkMap = chunkMaps[i];
Object chunkPacket = mapChunkRef.newInstance();
mapChunkRef.setFieldValue("a", chunkPacket, x);
mapChunkRef.setFieldValue("b", chunkPacket, z);
mapChunkRef.setFieldValue("c", chunkPacket, chunkMap);
mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up
bulkChunks.add(toLong(x, z)); // Store for later
list.add(chunkPacket);
}
} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunk bulk", e);
}
return list;
}
private static long toLong(int msw, int lsw) {
return ((long) msw << 32) + lsw - -2147483648L;
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
public class MetadataListType extends Type<List<Metadata>> {
public MetadataListType() {
super(List.class);
super("Metadata List", List.class);
}
@Override
@ -31,6 +31,7 @@ public class MetadataListType extends Type<List<Metadata>> {
public void write(ByteBuf buffer, List<Metadata> object) throws Exception {
for (Metadata m : object) {
Protocol1_9TO1_8.METADATA.write(buffer, m);
System.out.println("Writing meta data: " + m.getType().getTypeName() + " - " + m.getId() + " - " + m.getTypeID());
}
// Write end of list
Protocol1_9TO1_8.METADATA.write(buffer, null);

View File

@ -3,7 +3,7 @@ package us.myles.ViaVersion2.api.protocol1_9to1_8.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion2.api.metadata.Metadata;
import us.myles.ViaVersion2.api.protocol1_9to1_8.MetadataTypes;
import us.myles.ViaVersion2.api.protocol1_9to1_8.metadata.MetadataTypes;
import us.myles.ViaVersion2.api.type.Type;
public class MetadataType extends Type<Metadata> {
@ -16,17 +16,20 @@ public class MetadataType extends Type<Metadata> {
public Metadata read(ByteBuf buffer) throws Exception {
byte item = buffer.readByte();
if (item == 127) return null; // end of metadata
MetadataTypes type = MetadataTypes.byId((item & 0xE0) >> 5);
int typeID = (item & 0xE0) >> 5;
MetadataTypes type = MetadataTypes.byId(typeID);
int id = item & 0x1F;
return new Metadata(id, type.getType(), type.getType().read(buffer));
return new Metadata(id, typeID, type.getType(), type.getType().read(buffer));
}
@Override
public void write(ByteBuf buffer, Metadata object) throws Exception {
if (object == null) {
buffer.writeByte(127);
buffer.writeByte(255);
System.out.println("writing null :)");
} else {
buffer.writeByte(object.getId());
buffer.writeByte(object.getTypeID());
object.getType().write(buffer, object.getValue());
}
}

View File

@ -60,6 +60,8 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<CompoundTag> NBT = new NBTType();
public static final Type<UUID> OPTIONAL_UUID = new OptUUIDType();
public static final Type<Item> ITEM = new ItemType();
public static final Type<Item[]> ITEM_ARRAY = new ItemArrayType();
/* Actual Class */

View File

@ -0,0 +1,5 @@
package us.myles.ViaVersion2.api.type;
public interface TypeConverter<T> {
public T from(Object o);
}

View File

@ -3,6 +3,8 @@ package us.myles.ViaVersion2.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion2.api.type.Type;
import java.lang.reflect.Array;
public class ArrayType<T> extends Type<T[]> {
private final Type<T> elementType;
@ -14,11 +16,13 @@ public class ArrayType<T> extends Type<T[]> {
@Override
public T[] read(ByteBuf buffer) throws Exception{
int amount = Type.VAR_INT.read(buffer);
Object[] array = new Object[amount];
T[] array = (T[]) Array.newInstance(elementType.getOutputClass(), amount);
System.out.println("READING ARRAY " + array.length);
for (int i = 0; i < amount; i++) {
array[i] = elementType.read(buffer);
}
return (T[]) array;
return array;
}
@Override

View File

@ -2,8 +2,9 @@ package us.myles.ViaVersion2.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion2.api.type.Type;
import us.myles.ViaVersion2.api.type.TypeConverter;
public class ByteType extends Type<Byte> {
public class ByteType extends Type<Byte> implements TypeConverter<Byte> {
public ByteType() {
super(Byte.class);
}
@ -17,4 +18,12 @@ public class ByteType extends Type<Byte> {
public void write(ByteBuf buffer, Byte object) {
buffer.writeByte(object);
}
@Override
public Byte from(Object o) {
if (o instanceof Number) {
return ((Number) o).byteValue();
}
return (Byte) o;
}
}

View File

@ -2,8 +2,9 @@ package us.myles.ViaVersion2.api.type.types;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion2.api.type.Type;
import us.myles.ViaVersion2.api.type.TypeConverter;
public class VoidType extends Type<Void> {
public class VoidType extends Type<Void> implements TypeConverter<Void>{
public VoidType() {
super(Void.class);
}
@ -17,4 +18,9 @@ public class VoidType extends Type<Void> {
public void write(ByteBuf buffer, Void object) {
}
@Override
public Void from(Object o) {
return null;
}
}

View File

@ -22,7 +22,7 @@ public class ItemArrayType extends Type<Item[]> {
@Override
public void write(ByteBuf buffer, Item[] object) throws Exception {
Type.VAR_INT.write(buffer, object.length);
Type.SHORT.write(buffer, (short) object.length);
for (Item o : object) {
Type.ITEM.write(buffer, o);
}

View File

@ -13,6 +13,7 @@ public class ItemType extends Type<Item> {
public Item read(ByteBuf buffer) throws Exception {
short id = buffer.readShort();
if (id < 0) {
System.out.println("null item");
return null;
} else {
Item item = new Item();
@ -20,6 +21,7 @@ public class ItemType extends Type<Item> {
item.setAmount(buffer.readByte());
item.setData(buffer.readShort());
item.setTag(Type.NBT.read(buffer));
System.out.println("item tag: " + item.getTag());
return item;
}
}
@ -28,6 +30,7 @@ public class ItemType extends Type<Item> {
public void write(ByteBuf buffer, Item object) throws Exception {
if (object == null) {
buffer.writeShort(-1);
System.out.println("writing -1");
} else {
buffer.writeShort(object.getId());
buffer.writeByte(object.getAmount());

View File

@ -0,0 +1,31 @@
package us.myles.ViaVersion2.api.type.types.minecraft;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion2.api.type.Type;
import java.util.UUID;
public class OptUUIDType extends Type<UUID> {
public OptUUIDType() {
super(UUID.class);
}
@Override
public UUID read(ByteBuf buffer) {
boolean present = buffer.readBoolean();
if(!present) return null;
return new UUID(buffer.readLong(), buffer.readLong());
}
@Override
public void write(ByteBuf buffer, UUID object) {
if(object == null){
buffer.writeBoolean(false);
return;
}else{
buffer.writeBoolean(true);
buffer.writeLong(object.getMostSignificantBits());
buffer.writeLong(object.getLeastSignificantBits());
}
}
}