Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-11-20 06:50:08 +01:00
Merge pull request #50 from Mystalion/awesome-metadata
Rewrite Metadata system to read the data from the bytebuf instead of
Dieser Commit ist enthalten in:
Commit
e9b61a8e91
183
src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java
Normale Datei
183
src/main/java/us/myles/ViaVersion/metadata/MetadataRewriter.java
Normale Datei
@ -0,0 +1,183 @@
|
|||||||
|
package us.myles.ViaVersion.metadata;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.util.EulerAngle;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
import us.myles.ViaVersion.util.PacketUtil;
|
||||||
|
|
||||||
|
public class MetadataRewriter {
|
||||||
|
|
||||||
|
public static void writeMetadata1_9(EntityType type, List<Entry> list, ByteBuf output) {
|
||||||
|
short id = -1;
|
||||||
|
int data = -1;
|
||||||
|
Iterator<Entry> iterator = list.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Entry entry = iterator.next(); //
|
||||||
|
MetaIndex metaIndex = entry.index;
|
||||||
|
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
|
||||||
|
output.writeByte(metaIndex.getNewIndex());
|
||||||
|
output.writeByte(metaIndex.getNewType().getTypeID());
|
||||||
|
}
|
||||||
|
Object value = entry.value;
|
||||||
|
switch (metaIndex.getNewType()) {
|
||||||
|
case Byte:
|
||||||
|
// convert from int, byte
|
||||||
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
|
output.writeByte(((Byte) value).byteValue());
|
||||||
|
}
|
||||||
|
if (metaIndex.getOldType() == Type.Int) {
|
||||||
|
output.writeByte(((Integer) value).byteValue());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OptUUID:
|
||||||
|
String owner = (String) value;
|
||||||
|
UUID toWrite = null;
|
||||||
|
if (owner.length() != 0) {
|
||||||
|
try {
|
||||||
|
toWrite = UUID.fromString(owner);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.writeBoolean(toWrite != null);
|
||||||
|
if (toWrite != null)
|
||||||
|
PacketUtil.writeUUID((UUID) toWrite, output);
|
||||||
|
break;
|
||||||
|
case BlockID:
|
||||||
|
// if we have both sources :))
|
||||||
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
|
data = ((Byte) value).byteValue();
|
||||||
|
}
|
||||||
|
if (metaIndex.getOldType() == Type.Short) {
|
||||||
|
id = ((Short) value).shortValue();
|
||||||
|
}
|
||||||
|
if (id != -1 && data != -1) {
|
||||||
|
int combined = id << 4 | data;
|
||||||
|
data = -1;
|
||||||
|
id = -1;
|
||||||
|
PacketUtil.writeVarInt(combined, output);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VarInt:
|
||||||
|
// convert from int, short, byte
|
||||||
|
if (metaIndex.getOldType() == Type.Byte) {
|
||||||
|
PacketUtil.writeVarInt(((Byte) value).intValue(), output);
|
||||||
|
}
|
||||||
|
if (metaIndex.getOldType() == Type.Short) {
|
||||||
|
PacketUtil.writeVarInt(((Short) value).intValue(), output);
|
||||||
|
}
|
||||||
|
if (metaIndex.getOldType() == Type.Int) {
|
||||||
|
PacketUtil.writeVarInt(((Integer) value).intValue(), output);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Float:
|
||||||
|
output.writeFloat(((Float) value).floatValue());
|
||||||
|
break;
|
||||||
|
case String:
|
||||||
|
PacketUtil.writeString((String) value, output);
|
||||||
|
break;
|
||||||
|
case Boolean:
|
||||||
|
output.writeBoolean(((Byte) value).byteValue() != 0);
|
||||||
|
break;
|
||||||
|
case Slot:
|
||||||
|
PacketUtil.writeItem(value, output);
|
||||||
|
break;
|
||||||
|
case Position:
|
||||||
|
Vector vector = (Vector) value;
|
||||||
|
output.writeInt((int) vector.getX());
|
||||||
|
output.writeInt((int) vector.getY());
|
||||||
|
output.writeInt((int) vector.getZ());
|
||||||
|
break;
|
||||||
|
case Vector3F:
|
||||||
|
EulerAngle angle = (EulerAngle) value;
|
||||||
|
output.writeFloat((float) angle.getX());
|
||||||
|
output.writeFloat((float) angle.getY());
|
||||||
|
output.writeFloat((float) angle.getZ());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.out.println("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (type != null) {
|
||||||
|
System.out.println("An error occurred with entity meta data for " + type);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.writeByte(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Entry> readMetadata1_8(EntityType entityType, ByteBuf buf) {
|
||||||
|
List<Entry> entries = new ArrayList<>();
|
||||||
|
byte item;
|
||||||
|
while ((item = buf.readByte()) != 127) {
|
||||||
|
Type type = Type.byId((item & 0xE0) >> 5);
|
||||||
|
int id = item & 0x1F;
|
||||||
|
MetaIndex index = MetaIndex.getIndex(entityType, id);
|
||||||
|
switch (type) {
|
||||||
|
case Byte:
|
||||||
|
entries.add(new Entry(index, buf.readByte()));
|
||||||
|
break;
|
||||||
|
case Short:
|
||||||
|
entries.add(new Entry(index, buf.readShort()));
|
||||||
|
break;
|
||||||
|
case Int:
|
||||||
|
entries.add(new Entry(index, buf.readInt()));
|
||||||
|
break;
|
||||||
|
case Float:
|
||||||
|
entries.add(new Entry(index, buf.readFloat()));
|
||||||
|
break;
|
||||||
|
case String:
|
||||||
|
entries.add(new Entry(index, PacketUtil.readString(buf)));
|
||||||
|
break;
|
||||||
|
case Slot:
|
||||||
|
entries.add(new Entry(index, PacketUtil.readItem(buf)));
|
||||||
|
break;
|
||||||
|
case Position: {
|
||||||
|
int x = buf.readInt();
|
||||||
|
int y = buf.readInt();
|
||||||
|
int z = buf.readInt();
|
||||||
|
entries.add(new Entry(index, new Vector(x, y, z)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Rotation: {
|
||||||
|
float x = buf.readFloat();
|
||||||
|
float y = buf.readFloat();
|
||||||
|
float z = buf.readFloat();
|
||||||
|
entries.add(new Entry(index, new EulerAngle(x, y, z)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
System.out.println("[Out] Unhandled MetaDataType: " + type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Entry {
|
||||||
|
|
||||||
|
private MetaIndex index;
|
||||||
|
private Object value;
|
||||||
|
|
||||||
|
private Entry(MetaIndex index, Object value) {
|
||||||
|
this.index = index;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,4 +18,8 @@ public enum Type {
|
|||||||
public int getTypeID() {
|
public int getTypeID() {
|
||||||
return typeID;
|
return typeID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Type byId(int id) {
|
||||||
|
return values()[id];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,7 @@ import us.myles.ViaVersion.CancelException;
|
|||||||
import us.myles.ViaVersion.ConnectionInfo;
|
import us.myles.ViaVersion.ConnectionInfo;
|
||||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||||
import us.myles.ViaVersion.api.ViaVersion;
|
import us.myles.ViaVersion.api.ViaVersion;
|
||||||
import us.myles.ViaVersion.metadata.MetaIndex;
|
import us.myles.ViaVersion.metadata.MetadataRewriter;
|
||||||
import us.myles.ViaVersion.metadata.NewType;
|
|
||||||
import us.myles.ViaVersion.metadata.Type;
|
|
||||||
import us.myles.ViaVersion.packets.PacketType;
|
import us.myles.ViaVersion.packets.PacketType;
|
||||||
import us.myles.ViaVersion.packets.State;
|
import us.myles.ViaVersion.packets.State;
|
||||||
import us.myles.ViaVersion.sounds.SoundEffect;
|
import us.myles.ViaVersion.sounds.SoundEffect;
|
||||||
@ -21,7 +19,6 @@ import us.myles.ViaVersion.util.PacketUtil;
|
|||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static us.myles.ViaVersion.util.PacketUtil.*;
|
import static us.myles.ViaVersion.util.PacketUtil.*;
|
||||||
@ -211,15 +208,7 @@ public class OutgoingTransformer {
|
|||||||
int id = PacketUtil.readVarInt(input);
|
int id = PacketUtil.readVarInt(input);
|
||||||
PacketUtil.writeVarInt(id, output);
|
PacketUtil.writeVarInt(id, output);
|
||||||
|
|
||||||
try {
|
transformMetadata(id, input, output);
|
||||||
List dw = ReflectionUtil.get(info.getLastPacket(), "b", List.class);
|
|
||||||
// get entity via entityID, not preferred but we need it.
|
|
||||||
transformMetadata(id, dw, output);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,16 +347,8 @@ public class OutgoingTransformer {
|
|||||||
output.writeShort(vY);
|
output.writeShort(vY);
|
||||||
short vZ = input.readShort();
|
short vZ = input.readShort();
|
||||||
output.writeShort(vZ);
|
output.writeShort(vZ);
|
||||||
try {
|
|
||||||
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher"));
|
transformMetadata(id, input, output);
|
||||||
transformMetadata(id, dataWatcher, output);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packet == PacketType.PLAY_UPDATE_SIGN) {
|
if (packet == PacketType.PLAY_UPDATE_SIGN) {
|
||||||
@ -411,16 +392,8 @@ public class OutgoingTransformer {
|
|||||||
output.writeByte(pitch);
|
output.writeByte(pitch);
|
||||||
byte yaw = input.readByte();
|
byte yaw = input.readByte();
|
||||||
output.writeByte(yaw);
|
output.writeByte(yaw);
|
||||||
try {
|
|
||||||
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher"));
|
transformMetadata(id, input, output);
|
||||||
transformMetadata(id, dataWatcher, output);
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -514,150 +487,15 @@ public class OutgoingTransformer {
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformMetadata(int entityID, Object dw, ByteBuf output) throws CancelException {
|
private void transformMetadata(int entityID, ByteBuf input, ByteBuf output) throws CancelException {
|
||||||
// get entity
|
|
||||||
try {
|
|
||||||
transformMetadata(entityID, (List) ReflectionUtil.invoke(dw, "b"), output);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void transformMetadata(int entityID, List dw, ByteBuf output) throws CancelException {
|
|
||||||
EntityType type = clientEntityTypes.get(entityID);
|
EntityType type = clientEntityTypes.get(entityID);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
System.out.println("Unable to get entity for ID: " + entityID);
|
System.out.println("Unable to get entity for ID: " + entityID);
|
||||||
output.writeByte(255);
|
output.writeByte(255);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dw != null) {
|
List<MetadataRewriter.Entry> list = MetadataRewriter.readMetadata1_8(type, input);
|
||||||
short id = -1;
|
MetadataRewriter.writeMetadata1_9(type, list, output);
|
||||||
int data = -1;
|
|
||||||
|
|
||||||
Iterator iterator = dw.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Object watchableObj = iterator.next(); //
|
|
||||||
MetaIndex metaIndex = null;
|
|
||||||
try {
|
|
||||||
metaIndex = MetaIndex.getIndex(type, (int) ReflectionUtil.invoke(watchableObj, "a"));
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (metaIndex == null) {
|
|
||||||
try {
|
|
||||||
System.out.println("Meta Data for " + type + ": Not found, ID: " + (int) ReflectionUtil.invoke(watchableObj, "a"));
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
output.writeByte(metaIndex.getNewIndex());
|
|
||||||
output.writeByte(metaIndex.getNewType().getTypeID());
|
|
||||||
}
|
|
||||||
Object value = ReflectionUtil.invoke(watchableObj, "b");
|
|
||||||
switch (metaIndex.getNewType()) {
|
|
||||||
case Byte:
|
|
||||||
// convert from int, byte
|
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
|
||||||
output.writeByte(((Byte) value).byteValue());
|
|
||||||
}
|
|
||||||
if (metaIndex.getOldType() == Type.Int) {
|
|
||||||
output.writeByte(((Integer) value).byteValue());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OptUUID:
|
|
||||||
String owner = (String) value;
|
|
||||||
UUID toWrite = null;
|
|
||||||
if (owner.length() != 0) {
|
|
||||||
try {
|
|
||||||
toWrite = UUID.fromString(owner);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output.writeBoolean(toWrite != null);
|
|
||||||
if (toWrite != null)
|
|
||||||
PacketUtil.writeUUID((UUID) toWrite, output);
|
|
||||||
break;
|
|
||||||
case BlockID:
|
|
||||||
// if we have both sources :))
|
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
|
||||||
data = ((Byte) value).byteValue();
|
|
||||||
}
|
|
||||||
if (metaIndex.getOldType() == Type.Short) {
|
|
||||||
id = ((Short) value).shortValue();
|
|
||||||
}
|
|
||||||
if (id != -1 && data != -1) {
|
|
||||||
int combined = id << 4 | data;
|
|
||||||
data = -1;
|
|
||||||
id = -1;
|
|
||||||
PacketUtil.writeVarInt(combined, output);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VarInt:
|
|
||||||
// convert from int, short, byte
|
|
||||||
if (metaIndex.getOldType() == Type.Byte) {
|
|
||||||
PacketUtil.writeVarInt(((Byte) value).intValue(), output);
|
|
||||||
}
|
|
||||||
if (metaIndex.getOldType() == Type.Short) {
|
|
||||||
PacketUtil.writeVarInt(((Short) value).intValue(), output);
|
|
||||||
}
|
|
||||||
if (metaIndex.getOldType() == Type.Int) {
|
|
||||||
PacketUtil.writeVarInt(((Integer) value).intValue(), output);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Float:
|
|
||||||
output.writeFloat(((Float) value).floatValue());
|
|
||||||
break;
|
|
||||||
case String:
|
|
||||||
PacketUtil.writeString((String) value, output);
|
|
||||||
break;
|
|
||||||
case Boolean:
|
|
||||||
output.writeBoolean(((Byte) value).byteValue() != 0);
|
|
||||||
break;
|
|
||||||
case Slot:
|
|
||||||
PacketUtil.writeItem(value, output);
|
|
||||||
break;
|
|
||||||
case Position:
|
|
||||||
output.writeInt((int) ReflectionUtil.invoke(value, "getX"));
|
|
||||||
output.writeInt((int) ReflectionUtil.invoke(value, "getY"));
|
|
||||||
output.writeInt((int) ReflectionUtil.invoke(value, "getZ"));
|
|
||||||
break;
|
|
||||||
case Vector3F:
|
|
||||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getX"));
|
|
||||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getY"));
|
|
||||||
output.writeFloat((float) ReflectionUtil.invoke(value, "getZ"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (type != null) {
|
|
||||||
System.out.println("An error occurred with entity meta data for " + type);
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output.writeByte(255);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -373,6 +373,26 @@ public class PacketUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Object readItem(ByteBuf output) {
|
||||||
|
try {
|
||||||
|
Class<?> serializer = ReflectionUtil.nms("PacketDataSerializer");
|
||||||
|
Object init = serializer.getDeclaredConstructor(ByteBuf.class).newInstance(output);
|
||||||
|
Method toCall = init.getClass().getDeclaredMethod("i");
|
||||||
|
return toCall.invoke(init);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static long[] readBlockPosition(ByteBuf buf) {
|
public static long[] readBlockPosition(ByteBuf buf) {
|
||||||
long val = buf.readLong();
|
long val = buf.readLong();
|
||||||
long x = (val >> 38); // signed
|
long x = (val >> 38); // signed
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren