Compare commits

..
10 Commits
15 changed files with 314 additions and 93 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
# ViaVersion 0.3.4
# ViaVersion 0.3.5
**Allows the connection of 1.8 clients to 1.9**
This plugin modifies netty to allow connection of 1.9 clients to 1.8,
@@ -1,7 +1,7 @@
package org.spacehq.mc.protocol.data.game.chunk;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.util.PacketUtil;
import java.io.IOException;
import java.util.ArrayList;
@@ -8,18 +8,32 @@ import io.netty.channel.socket.SocketChannel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.ViaVersionAPI;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class Core extends JavaPlugin {
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
private final Set<UUID> portedPlayers = Collections.newSetFromMap(new ConcurrentHashMap<UUID, Boolean>());
@Override
public void onEnable() {
ViaVersion.setInstance(this);
System.out.println("ViaVersion enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
try {
injectPacketHandler();
@@ -30,6 +44,12 @@ public class Core extends JavaPlugin {
System.out.println("Unable to inject handlers, are you on 1.8? ");
e.printStackTrace();
}
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
setPorted(e.getPlayer().getUniqueId(), false);
}
}, this);
}
public void injectPacketHandler() throws Exception {
@@ -51,10 +71,22 @@ public class Core extends JavaPlugin {
}
}
@Override
public boolean isPorted(Player player) {
return portedPlayers.contains(player.getUniqueId());
}
public void setPorted(UUID id, boolean value) {
if (value) {
portedPlayers.add(id);
} else {
portedPlayers.remove(id);
}
}
public static Entity getEntity(final UUID player, final int id) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<Entity>() {
return Bukkit.getScheduler().callSyncMethod(getPlugin(ViaVersionPlugin.class), new Callable<Entity>() {
@Override
public Entity call() throws Exception {
Player p = Bukkit.getPlayer(player);
@@ -76,7 +108,7 @@ public class Core extends JavaPlugin {
public static ItemStack getHandItem(final ConnectionInfo info) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(Core.class), new Callable<ItemStack>() {
return Bukkit.getScheduler().callSyncMethod(getPlugin(ViaVersionPlugin.class), new Callable<ItemStack>() {
@Override
public ItemStack call() throws Exception {
if (info.getPlayer() != null) {
@@ -0,0 +1,17 @@
package us.myles.ViaVersion.api;
public class ViaVersion {
private static ViaVersionAPI INSTANCE;
public static void setInstance(ViaVersionAPI api) {
if (INSTANCE != null) {
throw new IllegalStateException("Instance already set.");
}
INSTANCE = api;
}
public static ViaVersionAPI getInstance() {
return INSTANCE;
}
}
@@ -0,0 +1,8 @@
package us.myles.ViaVersion.api;
import org.bukkit.entity.Player;
public interface ViaVersionAPI {
boolean isPorted(Player player);
}
@@ -7,7 +7,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.transformers.IncomingTransformer;
@ChannelHandler.Sharable
@@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.PacketUtil;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
@ChannelHandler.Sharable
@@ -3,7 +3,7 @@ package us.myles.ViaVersion.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ReflectionUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Constructor;
@@ -72,7 +72,7 @@ public enum MetaIndex {
// creeper
CREEPER_FUSE(Creeper.class, 16, Type.Byte, 11, NewType.VarInt), // -1 idle, 1 is fuse
CREEPER_ISPOWERED(Creeper.class, 17, Type.Byte, 12, NewType.Boolean),
CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean), // TODO: Write on wiki.vg for current prot
CREEPER_ISIGNITED(Creeper.class, 18, Type.Byte, 13, NewType.Boolean),
// ghast
GHAST_ISATTACKING(Ghast.class, 16, Type.Byte, 11, NewType.Boolean),
// slime
@@ -89,7 +89,7 @@ public enum MetaIndex {
WITHER_TARGET3(Wither.class, 19, Type.Int, 13, NewType.VarInt),
WITHER_INVULN_TIME(Wither.class, 20, Type.Int, 14, NewType.VarInt),
// guardian
GUARDIAN_INFO(Guardian.class, 16, Type.Byte, 11, NewType.Byte),
GUARDIAN_INFO(Guardian.class, 16, Type.Int, 11, NewType.Byte),
GUARDIAN_TARGET(Guardian.class, 17, Type.Int, 12, NewType.VarInt),
// boat
BOAT_SINCEHIT(Boat.class, 17, Type.Int, 5, NewType.VarInt),
@@ -159,16 +159,6 @@ public enum MetaIndex {
return this.clazz;
}
public static MetaIndex getIndex(Entity entity, int index) {
EntityType type;
if (entity instanceof Player) {
type = EntityType.PLAYER;
} else {
type = entity.getType();
}
return getIndex(type, index);
}
public static MetaIndex getIndex(EntityType type, int index) {
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
if(entityClass == null){
@@ -7,6 +7,8 @@ import us.myles.ViaVersion.*;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -178,7 +180,7 @@ public class IncomingTransformer {
output.writeByte(face);
int hand = PacketUtil.readVarInt(input);
ItemStack inHand = Core.getHandItem(info);
ItemStack inHand = ViaVersionPlugin.getHandItem(info);
Object item = null;
try {
Method m = ReflectionUtil.obc("inventory.CraftItemStack").getDeclaredMethod("asNMSCopy", ItemStack.class);
@@ -2,38 +2,42 @@ package us.myles.ViaVersion.transformers;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.spacehq.mc.protocol.data.game.chunk.Column;
import org.spacehq.mc.protocol.util.NetUtil;
import us.myles.ViaVersion.*;
import us.myles.ViaVersion.CancelException;
import us.myles.ViaVersion.ConnectionInfo;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.metadata.MetaIndex;
import us.myles.ViaVersion.metadata.NewType;
import us.myles.ViaVersion.sounds.SoundEffect;
import us.myles.ViaVersion.metadata.Type;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.sounds.SoundEffect;
import us.myles.ViaVersion.util.EntityUtil;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import static us.myles.ViaVersion.PacketUtil.*;
import static us.myles.ViaVersion.util.PacketUtil.*;
public class OutgoingTransformer {
private static Gson gson = new Gson();
private final Channel channel;
private final ConnectionInfo info;
private final ViaVersionInitializer init;
private final ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
private boolean cancel = false;
private Map<Integer, UUID> uuidMap = new HashMap<Integer, UUID>();
private Map<Integer, EntityType> clientEntityTypes = new HashMap<Integer, EntityType>();
public OutgoingTransformer(Channel channel, ConnectionInfo info, ViaVersionInitializer init) {
this.channel = channel;
@@ -60,14 +64,13 @@ public class OutgoingTransformer {
// By default no transform
PacketUtil.writeVarInt(packetID, output);
if (packet == PacketType.PLAY_NAMED_SOUND_EFFECT) {
String name = PacketUtil.readString(input);
String name = PacketUtil.readString(input);
SoundEffect effect = SoundEffect.getByName(name);
int catid = 0;
String newname = name;
if(effect != null)
{
catid = effect.getCategory().getId();
newname = effect.getNewName();
if (effect != null) {
catid = effect.getCategory().getId();
newname = effect.getNewName();
}
PacketUtil.writeString(newname, output);
PacketUtil.writeVarInt(catid, output);
@@ -77,22 +80,30 @@ public class OutgoingTransformer {
int passenger = input.readInt();
int vehicle = input.readInt();
boolean lead = input.readBoolean();
if (!lead){
if (!lead) {
output.clear();
writeVarInt(PacketType.PLAY_SET_PASSENGERS.getNewPacketID(),output);
writeVarInt(vehicle,output);
writeVarIntArray(Collections.singletonList(passenger),output);
writeVarInt(PacketType.PLAY_SET_PASSENGERS.getNewPacketID(), output);
writeVarInt(vehicle, output);
writeVarIntArray(Collections.singletonList(passenger), output);
return;
}
output.writeInt(passenger);
output.writeInt(vehicle);
return;
}
if (packet == PacketType.PLAY_DISCONNECT){
if (packet == PacketType.PLAY_DISCONNECT) {
String reason = readString(input);
if (reason.startsWith("\""))
reason = "{\"text\":" + reason + "}";
writeString(reason,output);
writeString(fixJson(reason), output);
return;
}
if (packet == PacketType.PLAY_TITLE) {
int action = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(action, output);
if (action == 0 || action == 1) {
String text = PacketUtil.readString(input);
PacketUtil.writeString(fixJson(text), output);
}
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_ENTITY_TELEPORT) {
@@ -173,7 +184,9 @@ public class OutgoingTransformer {
if (packet == PacketType.LOGIN_SUCCESS) {
String uu = PacketUtil.readString(input);
PacketUtil.writeString(uu, output);
info.setUUID(UUID.fromString(uu));
UUID uniqueId = UUID.fromString(uu);
info.setUUID(uniqueId);
plugin.setPorted(uniqueId, true);
output.writeBytes(input);
return;
}
@@ -201,13 +214,7 @@ public class OutgoingTransformer {
try {
List dw = ReflectionUtil.get(info.getLastPacket(), "b", List.class);
// get entity via entityID, not preferred but we need it.
Entity entity = Core.getEntity(info.getUUID(), id);
if (entity != null) {
transformMetadata(entity, dw, output);
} else {
// Died before we could get to it. rip
throw new CancelException();
}
transformMetadata(id, dw, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -215,13 +222,41 @@ public class OutgoingTransformer {
}
return;
}
if (packet == PacketType.PLAY_SPAWN_OBJECT) {
if (packet == PacketType.PLAY_SPAWN_GLOBAL_ENTITY) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
// only used for lightning
byte type = input.readByte();
clientEntityTypes.put(id, EntityType.LIGHTNING);
output.writeByte(type);
double x = input.readInt();
output.writeDouble(x / 32D);
double y = input.readInt();
output.writeDouble(y / 32D);
double z = input.readInt();
output.writeDouble(z / 32D);
return;
}
if (packet == PacketType.PLAY_DESTROY_ENTITIES) {
int count = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(count, output);
int[] toDestroy = PacketUtil.readVarInts(count, input);
for (int entityID : toDestroy) {
clientEntityTypes.remove(entityID);
PacketUtil.writeVarInt(entityID, output);
}
return;
}
if (packet == PacketType.PLAY_SPAWN_OBJECT) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
PacketUtil.writeUUID(getUUID(id), output);
byte type = input.readByte();
clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, true));
output.writeByte(type);
double x = input.readInt();
@@ -247,8 +282,9 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.PLAY_SPAWN_XP_ORB) { // TODO: Verify
if (packet == PacketType.PLAY_SPAWN_XP_ORB) {
int id = PacketUtil.readVarInt(input);
clientEntityTypes.put(id, EntityType.EXPERIENCE_ORB);
PacketUtil.writeVarInt(id, output);
double x = input.readInt();
@@ -263,17 +299,32 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.PLAY_OPEN_WINDOW){
if (packet == PacketType.PLAY_SPAWN_PAINTING) {
int id = PacketUtil.readVarInt(input);
clientEntityTypes.put(id, EntityType.PAINTING);
PacketUtil.writeVarInt(id, output);
PacketUtil.writeUUID(getUUID(id), output);
String title = PacketUtil.readString(input);
PacketUtil.writeString(title, output);
long[] position = PacketUtil.readBlockPosition(input);
PacketUtil.writeBlockPosition(output, position[0], position[1], position[2]);
byte direction = input.readByte();
output.writeByte(direction);
return;
}
if (packet == PacketType.PLAY_OPEN_WINDOW) {
int windowId = input.readUnsignedByte();
String type = readString(input);
String windowTitle = readString(input);
if (windowTitle.startsWith("\""))
windowTitle = "{\"text\":" + windowTitle + "}";;
output.writeByte(windowId);
writeString(type,output);
writeString(windowTitle,output);
writeString(type, output);
writeString(fixJson(windowTitle), output);
output.writeBytes(input);
return;
}
@@ -283,7 +334,9 @@ public class OutgoingTransformer {
PacketUtil.writeUUID(getUUID(id), output);
short type = input.readUnsignedByte();
clientEntityTypes.put(id, EntityUtil.getTypeFromID(type, false));
output.writeByte(type);
double x = input.readInt();
output.writeDouble(x / 32D);
double y = input.readInt();
@@ -305,7 +358,7 @@ public class OutgoingTransformer {
output.writeShort(vZ);
try {
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "l", ReflectionUtil.nms("DataWatcher"));
transformMetadata(dataWatcher, output);
transformMetadata(id, dataWatcher, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -320,21 +373,20 @@ public class OutgoingTransformer {
output.writeLong(location);
for (int i = 0; i < 4; i++) {
String line = PacketUtil.readString(input);
if (line == null || line.equalsIgnoreCase("null")) {
line = "{\"text\":\"\"}";
} else {
if (!line.startsWith("\"") && !line.startsWith("{"))
line = "\"" + line + "\"";
if (line.startsWith("\""))
line = "{\"text\":" + line + "}";
}
PacketUtil.writeString(line, output);
PacketUtil.writeString(fixJson(line), output);
}
}
if (packet == PacketType.PLAY_JOIN_GAME) {
int id = input.readInt();
clientEntityTypes.put(id, EntityType.PLAYER);
output.writeInt(id);
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_SPAWN_PLAYER) {
int id = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(id, output);
clientEntityTypes.put(id, EntityType.PLAYER);
UUID playerUUID = PacketUtil.readUUID(input);
PacketUtil.writeUUID(playerUUID, output);
@@ -351,7 +403,7 @@ public class OutgoingTransformer {
output.writeByte(yaw);
try {
Object dataWatcher = ReflectionUtil.get(info.getLastPacket(), "i", ReflectionUtil.nms("DataWatcher"));
transformMetadata(dataWatcher, output);
transformMetadata(id, dataWatcher, output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -362,7 +414,7 @@ public class OutgoingTransformer {
return;
}
if(packet == PacketType.PLAY_MAP) {
if (packet == PacketType.PLAY_MAP) {
int damage = PacketUtil.readVarInt(input);
PacketUtil.writeVarInt(damage, output);
byte scale = input.readByte();
@@ -440,30 +492,37 @@ public class OutgoingTransformer {
output.writeBytes(input);
}
private void transformMetadata(Object dw, ByteBuf output) {
private String fixJson(String line) {
if (line == null || line.equalsIgnoreCase("null")) {
line = "{\"text\":\"\"}";
} else {
if (!line.startsWith("\"") && !line.startsWith("{"))
line = "\"" + line + "\"";
if (line.startsWith("\""))
line = "{\"text\":" + line + "}";
}
return line;
}
private void transformMetadata(int entityID, Object dw, ByteBuf output) {
// get entity
try {
Class<?> nmsClass = ReflectionUtil.nms("Entity");
Object nmsEntity = ReflectionUtil.get(dw, "a", nmsClass);
Class<?> craftClass = ReflectionUtil.obc("entity.CraftEntity");
Method bukkitMethod = craftClass.getDeclaredMethod("getEntity", ReflectionUtil.obc("CraftServer"), nmsClass);
Object entity = bukkitMethod.invoke(null, Bukkit.getServer(), nmsEntity);
transformMetadata((Entity) entity, (List) ReflectionUtil.invoke(dw, "b"), output);
} catch (NoSuchFieldException e) {
e.printStackTrace();
transformMetadata(entityID, (List) ReflectionUtil.invoke(dw, "b"), output);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private void transformMetadata(Entity entity, List dw, ByteBuf output) {
private void transformMetadata(int entityID, List dw, ByteBuf output) {
EntityType type = clientEntityTypes.get(entityID);
if (type == null) {
System.out.println("Unable to get entity for ID: " + entityID);
return;
}
if (dw != null) {
short id = -1;
int data = -1;
@@ -473,7 +532,7 @@ public class OutgoingTransformer {
Object watchableObj = iterator.next(); //
MetaIndex metaIndex = null;
try {
metaIndex = MetaIndex.getIndex(entity, (int) ReflectionUtil.invoke(watchableObj, "a"));
metaIndex = MetaIndex.getIndex(type, (int) ReflectionUtil.invoke(watchableObj, "a"));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
@@ -563,8 +622,8 @@ public class OutgoingTransformer {
}
} catch (Exception e) {
if (entity != null) {
System.out.println("An error occurred with entity meta data for " + entity.getType());
if (type != null) {
System.out.println("An error occurred with entity meta data for " + type);
System.out.println("Old ID: " + metaIndex.getIndex() + " New ID: " + metaIndex.getNewIndex());
System.out.println("Old Type: " + metaIndex.getOldType() + " New Type: " + metaIndex.getNewType());
}
@@ -0,0 +1,91 @@
package us.myles.ViaVersion.util;
import org.bukkit.entity.EntityType;
public class EntityUtil {
public static EntityType getTypeFromID(int typeID, boolean isObject) {
if (isObject) {
return getObjectFromID(typeID);
} else {
return EntityType.fromId(typeID);
}
}
// based on http://wiki.vg/index.php?title=Entities
public static EntityType getObjectFromID(int objectID) {
EntityType type;
switch (objectID) {
case 2:
type = EntityType.DROPPED_ITEM;
break;
case 77:
type = EntityType.LEASH_HITCH;
break;
case 60:
type = EntityType.ARROW;
break;
case 61:
type = EntityType.SNOWBALL;
break;
case 63:
type = EntityType.FIREBALL;
break;
case 64:
type = EntityType.SMALL_FIREBALL;
break;
case 65:
type = EntityType.ENDER_PEARL;
break;
case 72:
type = EntityType.ENDER_SIGNAL;
break;
case 75:
type = EntityType.THROWN_EXP_BOTTLE;
break;
case 71:
type = EntityType.ITEM_FRAME;
break;
case 66:
type = EntityType.WITHER_SKULL;
break;
case 50:
type = EntityType.PRIMED_TNT;
break;
case 70:
type = EntityType.FALLING_BLOCK;
break;
case 76:
type = EntityType.FIREWORK;
break;
case 78:
type = EntityType.ARMOR_STAND;
break;
case 1:
type = EntityType.BOAT;
break;
case 10:
type = EntityType.MINECART;
break;
case 51:
type = EntityType.ENDER_CRYSTAL;
break;
case 73:
type = EntityType.SPLASH_POTION;
break;
case 62:
type = EntityType.EGG;
break;
case 90:
type = EntityType.FISHING_HOOK;
break;
default:
type = EntityType.fromId(objectID);
if (type == null) {
System.out.println("Unable to find entity type for " + objectID);
type = EntityType.UNKNOWN;
}
break;
}
return type;
}
}
@@ -1,4 +1,4 @@
package us.myles.ViaVersion;
package us.myles.ViaVersion.util;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
@@ -363,4 +363,26 @@ public class PacketUtil {
e.printStackTrace();
}
}
public static long[] readBlockPosition(ByteBuf buf) {
long val = buf.readLong();
long x = (val >> 38); // signed
long y = (val >> 26) & 0xfff; // unsigned
// this shifting madness is used to preserve sign
long z = (val << 38) >> 38; // signed
return new long[]{x, y, z};
}
public static void writeBlockPosition(ByteBuf buf, long x, long y, long z) {
buf.writeLong(((x & 0x3ffffff) << 38) | ((y & 0xfff) << 26) | (z & 0x3ffffff));
}
public static int[] readVarInts(int amount, ByteBuf input) {
int data[] = new int[amount];
for (int index = 0; index < amount; index++) {
data[index] = PacketUtil.readVarInt(input);
}
return data;
}
}
@@ -1,4 +1,4 @@
package us.myles.ViaVersion;
package us.myles.ViaVersion.util;
import org.bukkit.Bukkit;
+2 -2
View File
@@ -1,4 +1,4 @@
name: ViaVersion
main: us.myles.ViaVersion.Core
main: us.myles.ViaVersion.ViaVersionPlugin
author: _MylesC
version: 0.3.4
version: 0.3.5