Compare commits

..
29 Commits
Author SHA1 Message Date
Myles 1c42ae1ee8 Update version to 0.5.4 2016-03-06 13:52:38 +00:00
Myles c5ac3c9b3d Don't freeze current thread when sending chunks 2016-03-06 13:49:33 +00:00
Myles 0ea32b3318 Merge pull request #150 from HugoDaBosss/patch
Fix mob spawners when no EntityId is given
2016-03-06 13:45:56 +00:00
Myles 8afc850ed3 Add new config option "sync-chunks", chunks will now be sent in sync with the MC thread when true, this fixes timings (paper spigot mostly issue) 2016-03-06 13:45:26 +00:00
HugoDaBosss 3c6dcfe5bf Update OutgoingTransformer.java 2016-03-06 14:42:50 +01:00
HugoDaBosss 59d637e0f5 More formatting (stupid eclipse) 2016-03-06 14:42:22 +01:00
HugoDaBosss 923f3088c0 Formatting 2016-03-06 14:40:52 +01:00
HugoDaBosss 4f8aff9c01 Forgot to remove debug message 2016-03-06 14:37:51 +01:00
HugoDaBosss 99ceb9ae79 Fix mob spawners when no EntityId is given 2016-03-06 14:32:57 +01:00
Myles 6e0554f4a4 Fix enchanting tooltips 2016-03-06 13:22:56 +00:00
Myles 36879f8d02 Fix small issue with updater 2016-03-06 13:02:54 +00:00
Myles fe77df1434 Fix brewing #141 2016-03-06 12:25:54 +00:00
Myles 713361f973 Merge pull request #148 from StamBoom/master
Fix commandblock minecarts
2016-03-06 11:20:50 +00:00
Mats a314b86f57 Fix commandblock minecarts 2016-03-06 12:18:18 +01:00
Myles 840c90f871 Don't use GSON >.> 2016-03-06 11:03:41 +00:00
Myles 2a247595c8 Handle invalid version numbers 2016-03-06 10:49:21 +00:00
Myles 4124c3454e Change it so when there is no connection we don't bug them. Also change it to use http instead of https, as https requires certain certificate info by linux. 2016-03-06 10:46:38 +00:00
HugoDaBosss c4185e3056 Merge pull request #147 from fillefilip8/patch-4
Made the config use the default bukkit config methods insteed.
2016-03-06 10:56:07 +01:00
fillefilip8 d6403d495d Opps :) Github likes me :D Removed the new api methods from this branch :D 2016-03-06 10:42:26 +01:00
fillefilip8 d7f54048ff Made the config use the default bukkit config methods insteed. 2016-03-06 10:39:58 +01:00
Myles e487eeb395 Update to 0.5.3, add inventory title tracking so we're working towards some of the inventory bugs with new ones. 2016-03-06 00:25:24 +00:00
Myles 0d0e1c16ea Fix issue with formatting :) (fixes quotes) 2016-03-05 23:24:23 +00:00
Myles f462ff9e8a Fix weird closedchannel bug 2016-03-05 22:16:43 +00:00
Myles 5582556d8a Fix issue with biomes on chunks, #125 2016-03-05 22:05:17 +00:00
Myles ef6214a442 Fix getHandItem across reloads, though half the things will still break on reload :( 2016-03-05 21:23:14 +00:00
Myles 369710333c Change updating so it doesn't tell you on current version up to date but warns if you're on a newer version than expected / older one in console. 2016-03-05 21:15:51 +00:00
Myles 30c4fea044 Add new /viaversion dontbugme, change method if the version looks like it's custom / debug (not compiled by maven) 2016-03-05 20:54:35 +00:00
Myles eccc5091b5 Merge pull request #139 from HugoDaBosss/master
Added proper update message (based on checkplys)
2016-03-05 20:40:48 +00:00
HugoDaBosss 65770d7c5b Added proper update message 2016-03-05 21:37:12 +01:00
18 changed files with 461 additions and 73 deletions

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
# ViaVersion 0.5.2
# ViaVersion 0.5.4
**Allows the connection of 1.9 clients to 1.8**
This plugin modifies netty to allow connection of 1.9 clients to 1.8,
+1 -1
View File
@@ -5,7 +5,7 @@
<groupId>us.myles</groupId>
<artifactId>ViaVersion</artifactId>
<version>0.5.2</version>
<version>0.5.4</version>
<build>
<finalName>ViaVersion-${project.version}</finalName>
<plugins>
@@ -30,7 +30,7 @@ public class NetUtil {
}
}
if(fullChunk) {
if(fullChunk && column.getBiomeData() != null) {
out.writeBytes(column.getBiomeData());
}
@@ -103,7 +103,8 @@ public class NetUtil {
}
byte biomeData[] = null;
if(isFullChunk) {
if(isFullChunk && (pos + 256 <= input.length)) {
biomeData = new byte[256];
System.arraycopy(input, pos, biomeData, 0, biomeData.length);
}
@@ -1,4 +1,4 @@
package us.myles.ViaVersion;
public class CancelException extends Exception{
public class CancelException extends Exception {
}
@@ -14,6 +14,7 @@ public class ConnectionInfo {
private Object lastPacket;
private java.util.UUID UUID;
private State state = State.HANDSHAKE;
private String openWindow;
private int protocol = 0;
private int compression = 0;
private boolean active = true;
@@ -87,4 +88,16 @@ public class ConnectionInfo {
}
});
}
public String getOpenWindow() {
return openWindow;
}
public void setOpenWindow(String openWindow) {
this.openWindow = openWindow;
}
public void closeWindow() {
this.openWindow = null;
}
}
@@ -19,6 +19,8 @@ import us.myles.ViaVersion.armor.ArmorListener;
import us.myles.ViaVersion.commands.ViaVersionCommand;
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
import us.myles.ViaVersion.listeners.CommandBlockListener;
import us.myles.ViaVersion.update.UpdateListener;
import us.myles.ViaVersion.update.UpdateUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Field;
@@ -27,6 +29,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
@@ -37,8 +40,10 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
@Override
public void onEnable() {
ViaVersion.setInstance(this);
saveDefaultConfig();
if (System.getProperty("ViaVersion") != null) {
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
getLogger().severe("Some features may not work.");
return;
}
@@ -50,6 +55,10 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
getLogger().severe("Unable to inject handlers, are you on 1.8? ");
e.printStackTrace();
}
if (getConfig().getBoolean("checkforupdates")) {
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
UpdateUtil.sendUpdateMessage(this);
}
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
@@ -115,6 +124,11 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
return this.debug;
}
@Override
public boolean isSyncedChunks() {
return getConfig().getBoolean("sync-chunks", true);
}
public void setDebug(boolean value) {
this.debug = value;
}
@@ -129,7 +143,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
public static ItemStack getHandItem(final ConnectionInfo info) {
try {
return Bukkit.getScheduler().callSyncMethod(getPlugin(ViaVersionPlugin.class), new Callable<ItemStack>() {
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<ItemStack>() {
@Override
public ItemStack call() throws Exception {
if (info.getPlayer() != null) {
@@ -144,4 +158,22 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
return null;
}
}
public void run(final Runnable runnable, boolean wait) {
try {
Future f = Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
runnable.run();
return true;
}
});
if(wait){
f.get(10, TimeUnit.SECONDS);
}
} catch (Exception e) {
System.out.println("Failed to run task.");
e.printStackTrace();
}
}
}
@@ -30,4 +30,10 @@ public interface ViaVersionAPI {
* @return true if debug is enabled
*/
boolean isDebug();
/**
* Obtains if syncing chunks is on
* @return true if it is
*/
boolean isSyncedChunks();
}
@@ -28,6 +28,7 @@ public class ViaVersionCommand implements CommandExecutor {
sender.sendMessage(color("&aViaVersion &c" + ViaVersion.getInstance().getVersion()));
sender.sendMessage(color("&6Commands:"));
sender.sendMessage(color("&2/viaversion list &7- &6Shows lists of all 1.9 clients and 1.8 clients."));
sender.sendMessage(color("&2/viaversion dontbugme &7- &6Toggle checking for updates."));
} else if (args.length == 1) {
if (args[0].equalsIgnoreCase("list")) {
List<String> portedPlayers = new ArrayList<String>();
@@ -47,6 +48,12 @@ public class ViaVersionCommand implements CommandExecutor {
plugin.setDebug(!plugin.isDebug());
sender.sendMessage(color("&6Debug mode is now " + (plugin.isDebug() ? "&aenabled" : "&cdisabled")));
}
if (args[0].equalsIgnoreCase("dontbugme")) {
boolean newValue = !plugin.getConfig().getBoolean("checkforupdates", true);
plugin.getConfig().set("checkforupdates", newValue);
plugin.saveConfig();
sender.sendMessage(color("&6We will " + (newValue ? "&anotify you about updates." : "&cnot tell you about updates.")));
}
}
}
@@ -5,11 +5,14 @@ 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.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ViaEncodeHandler extends MessageToByteEncoder {
private final ConnectionInfo info;
@@ -24,25 +27,50 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext ctx, Object o, ByteBuf bytebuf) throws Exception {
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
// handle the packet type
if (!(o instanceof ByteBuf)) {
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()) {
int[] locX = ReflectionUtil.get(o, "a", int[].class);
int[] locZ = ReflectionUtil.get(o, "b", int[].class);
final int[] locX = ReflectionUtil.get(o, "a", int[].class);
final int[] locZ = ReflectionUtil.get(o, "b", int[].class);
Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
final Object world = ReflectionUtil.get(o, "world", ReflectionUtil.nms("World"));
Class<?> mapChunk = ReflectionUtil.nms("PacketPlayOutMapChunk");
Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
ctx.pipeline().writeAndFlush(packet);
final Constructor constructor = mapChunk.getDeclaredConstructor(ReflectionUtil.nms("Chunk"), boolean.class, int.class);
Runnable chunks = new Runnable() {
@Override
public void run() {
for (int i = 0; i < locX.length; i++) {
int x = locX[i];
int z = locZ[i];
// world invoke function
try {
Object chunk = ReflectionUtil.nms("World").getDeclaredMethod("getChunkAt", int.class, int.class).invoke(world, x, z);
Object packet = constructor.newInstance(chunk, true, 65535);
ctx.pipeline().writeAndFlush(packet);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
};
// Synced allows timings to work properly.
if (ViaVersion.getInstance().isSyncedChunks()) {
((ViaVersionPlugin) ViaVersion.getInstance()).run(chunks, false);
} else {
chunks.run();
}
bytebuf.readBytes(bytebuf.readableBytes());
throw new CancelException();
@@ -1,7 +1,6 @@
package us.myles.ViaVersion.metadata;
import org.bukkit.entity.*;
import org.bukkit.entity.minecart.CommandMinecart;
public enum MetaIndex {
@@ -107,8 +106,8 @@ public enum MetaIndex {
MINECART_BLOCK_Y(Minecart.class, 21, Type.Int, 9, NewType.VarInt),
MINECART_SHOWBLOCK(Minecart.class, 22, Type.Byte, 10, NewType.Boolean),
// Command minecart (they are still broken)
MINECART_COMMANDBLOCK_COMMAND(CommandMinecart.class,23,Type.String,11,NewType.String),
MINECART_COMMANDBLOCK_OUTPUT(CommandMinecart.class,24,Type.String,12,NewType.Chat),
MINECART_COMMANDBLOCK_COMMAND(Minecart.class, 23, Type.String, 11, NewType.String),
MINECART_COMMANDBLOCK_OUTPUT(Minecart.class, 24, Type.String, 12, NewType.Chat),
// furnace cart
FURNACECART_ISPOWERED(org.bukkit.entity.minecart.PoweredMinecart.class, 16, Type.Byte, 11, NewType.Boolean),
// item drop
@@ -167,14 +166,14 @@ public enum MetaIndex {
public static MetaIndex getIndex(EntityType type, int index) {
Class<? extends org.bukkit.entity.Entity> entityClass = type.getEntityClass();
if(entityClass == null){
if (entityClass == null) {
System.out.println("Could not get entity class for " + type);
return null;
}
for (MetaIndex mi : MetaIndex.values()) {
if (mi.getIndex() == index) {
// To fix issue with armour stands colliding with new values
if(mi.getApplicableClass().equals(LivingEntity.class)) continue;
if (mi.getApplicableClass().equals(LivingEntity.class)) continue;
if ((mi.getApplicableClass().isAssignableFrom(entityClass) ||
mi.getApplicableClass().equals(entityClass))) {
@@ -1,20 +1,19 @@
package us.myles.ViaVersion.metadata;
import io.netty.buffer.ByteBuf;
import org.bukkit.entity.EntityType;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import us.myles.ViaVersion.slot.ItemSlotRewriter;
import us.myles.ViaVersion.slot.ItemSlotRewriter.ItemStack;
import us.myles.ViaVersion.transformers.OutgoingTransformer;
import us.myles.ViaVersion.util.PacketUtil;
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.slot.ItemSlotRewriter;
import us.myles.ViaVersion.slot.ItemSlotRewriter.ItemStack;
import us.myles.ViaVersion.util.PacketUtil;
public class MetadataRewriter {
public static void writeMetadata1_9(EntityType type, List<Entry> list, ByteBuf output) {
@@ -88,7 +87,7 @@ public class MetadataRewriter {
PacketUtil.writeString((String) value, output);
break;
case Boolean:
if(metaIndex == MetaIndex.AGEABLE_AGE)
if (metaIndex == MetaIndex.AGEABLE_AGE)
output.writeBoolean(((Byte) value).byteValue() < 0);
else
output.writeBoolean(((Byte) value).byteValue() != 0);
@@ -110,6 +109,9 @@ public class MetadataRewriter {
output.writeFloat((float) angle.getY());
output.writeFloat((float) angle.getZ());
break;
case Chat:
PacketUtil.writeString(OutgoingTransformer.fixJson((String) value), output);
break;
default:
System.out.println("[Out] Unhandled MetaDataType: " + metaIndex.getNewType());
break;
@@ -159,7 +161,7 @@ public class MetadataRewriter {
e.printStackTrace();
}
}
break;
break;
case Position: {
int x = buf.readInt();
int y = buf.readInt();
@@ -12,11 +12,8 @@ import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.slot.ItemSlotRewriter;
import us.myles.ViaVersion.util.PacketUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class IncomingTransformer {
private final ConnectionInfo info;
@@ -105,28 +102,32 @@ public class IncomingTransformer {
byte button = input.readByte();
short action = input.readShort();
byte mode = input.readByte();
// if the action is on an elytra armour slot
if (slot == 45 && windowID == 0) {
try {
Class<?> setSlot = ReflectionUtil.nms("PacketPlayOutSetSlot");
Constructor setSlotConstruct = setSlot.getDeclaredConstructor(int.class, int.class, ReflectionUtil.nms("ItemStack"));
// properly construct
Object setSlotPacket = setSlotConstruct.newInstance(windowID, slot, null);
info.getChannel().pipeline().writeAndFlush(setSlotPacket); // slot is empty
slot = -999; // we're evil, they'll throw item on the ground
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
int mode = input.readByte();
// if the action is on an elytra armour slot
boolean throwItem = (slot == 45 && windowID == 0);
if (info.getOpenWindow() != null && windowID > 0) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
if (slot == 4) {
// throw
throwItem = true;
}
if (slot > 4)
slot = (short) (slot - 1);
}
}
if (throwItem) {
ByteBuf buf = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_SET_SLOT.getNewPacketID(), buf);
buf.writeByte(windowID);
buf.writeShort(slot);
buf.writeShort(-1); // empty
info.sendRawPacket(buf);
// Continue the packet simulating throw
mode = 0;
button = 0;
slot = -999;
}
output.writeByte(windowID);
output.writeShort(slot);
@@ -136,6 +137,9 @@ public class IncomingTransformer {
ItemSlotRewriter.rewrite1_9To1_8(input, output);
return;
}
if (packet == PacketType.PLAY_CLOSE_WINDOW_REQUEST) {
info.closeWindow();
}
if (packet == PacketType.PLAY_CLIENT_SETTINGS) {
String locale = PacketUtil.readString(input);
PacketUtil.writeString(locale, output);
@@ -213,6 +217,11 @@ public class IncomingTransformer {
PacketUtil.writeString(command, output);
output.writeBoolean(flag);
return;
} else if (name.equals("MC|AdvCmd")) {
output.clear();
PacketUtil.writeVarInt(PacketType.PLAY_PLUGIN_MESSAGE_REQUEST.getPacketID(), output);
PacketUtil.writeString("MC|AdvCdm", output);
output.writeBytes(b);
}
output.writeBytes(b);
}
@@ -408,22 +408,65 @@ public class OutgoingTransformer {
return;
}
if (packet == PacketType.PLAY_WINDOW_PROPERTY) {
int windowId = input.readUnsignedByte();
output.writeByte(windowId);
short property = input.readShort();
short value = input.readShort();
if (info.getOpenWindow() != null) {
if (info.getOpenWindow().equalsIgnoreCase("minecraft:enchanting_table")) {
if (property > 3 && property < 7) {
short level = (short) (value >> 8);
short enchantID = (short) (value & 0xFF);
// Property 1
ByteBuf buf1 = info.getChannel().alloc().buffer();
PacketUtil.writeVarInt(PacketType.PLAY_WINDOW_PROPERTY.getNewPacketID(), buf1);
buf1.writeByte(windowId);
buf1.writeShort(property);
buf1.writeShort(enchantID);
info.sendRawPacket(buf1);
property = (short) (property + 3);
value = level;
}
}
}
output.writeShort(property);
output.writeShort(value);
}
if (packet == PacketType.PLAY_OPEN_WINDOW) {
int windowId = input.readUnsignedByte();
String type = readString(input);
info.setOpenWindow(type);
String windowTitle = readString(input);
output.writeByte(windowId);
writeString(type, output);
writeString(fixJson(windowTitle), output);
int slots = input.readUnsignedByte();
if (type.equals("minecraft:brewing_stand")) {
slots = slots + 1; // new slot
}
output.writeByte(slots);
output.writeBytes(input);
return;
}
if (packet == PacketType.PLAY_CLOSE_WINDOW) {
info.closeWindow();
}
if (packet == PacketType.PLAY_SET_SLOT) {
int windowId = input.readUnsignedByte();
output.writeByte(windowId);
short slot = input.readShort();
if (info.getOpenWindow() != null) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
if (slot >= 4)
slot = (short) (slot + 1);
}
}
output.writeShort(slot);
ItemSlotRewriter.rewrite1_8To1_9(input, output);
return;
@@ -433,10 +476,22 @@ public class OutgoingTransformer {
output.writeByte(windowId);
short count = input.readShort();
output.writeShort(count);
boolean brewing = false;
if (info.getOpenWindow() != null && windowId > 0) {
if (info.getOpenWindow().equals("minecraft:brewing_stand")) {
brewing = true;
}
}
output.writeShort(brewing ? (count + 1) : count);
for (int i = 0; i < count; i++) {
ItemSlotRewriter.rewrite1_8To1_9(input, output);
// write "fuel" slot
if (brewing && i == 3) {
output.writeShort(-1); // empty slot
}
}
return;
}
@@ -569,14 +624,28 @@ public class OutgoingTransformer {
output.writeByte(action);
if (action == 1) { // update spawner
try {
int index = input.readerIndex();
DataInputStream stream = new DataInputStream(new ByteBufInputStream(input));
CompoundTag tag = (CompoundTag) NBTIO.readTag(stream);
String entity = (String) tag.get("EntityId").getValue();
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", entity));
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
if(tag != null && tag.contains("EntityId")) {
String entity = (String) tag.get("EntityId").getValue();
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", entity));
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
}
else if(tag != null) { // EntityID does not exist
CompoundTag spawn = new CompoundTag("SpawnData");
spawn.put(new StringTag("id", "AreaEffectCloud")); //Make spawners show up as empty when no EntityId is given.
tag.put(spawn);
DataOutputStream out = new DataOutputStream(new ByteBufOutputStream(output));
NBTIO.writeTag(out, tag);
}
else { //There doesn't exist any NBT tag
input.readerIndex(index);
output.writeBytes(input, input.readableBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
@@ -656,10 +725,14 @@ public class OutgoingTransformer {
if (line == null || line.equalsIgnoreCase("null")) {
line = "{\"text\":\"\"}";
} else {
if (!line.startsWith("\"") && !line.startsWith("{"))
line = "\"" + line + "\"";
if (line.startsWith("\""))
if (!line.startsWith("\"") && !line.startsWith("{")) {
JSONObject obj = new JSONObject();
obj.put("text", line);
line = obj.toJSONString();
}
if (line.startsWith("\"")) {
line = "{\"text\":" + line + "}";
}
}
try {
new JSONParser().parse(line);
@@ -0,0 +1,24 @@
package us.myles.ViaVersion.update;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
public class UpdateListener implements Listener {
private Plugin plugin;
public UpdateListener(Plugin plugin) {
this.plugin = plugin;
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
if(e.getPlayer().hasPermission("viaversion.update")
&& plugin.getConfig().getBoolean("checkforupdates", true)) {
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId(), plugin);
}
}
}
@@ -0,0 +1,125 @@
package us.myles.ViaVersion.update;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import us.myles.ViaVersion.api.ViaVersion;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
public class UpdateUtil {
private final static String URL = "http://api.spiget.org/v1/resources/";
private final static int PLUGIN = 19254;
public final static String PREFIX = ChatColor.GREEN + "" + ChatColor.BOLD + "[ViaVersion] " + ChatColor.GREEN;
public static void sendUpdateMessage(final UUID uuid, final Plugin plugin) {
new BukkitRunnable() {
@Override
public void run() {
final String message = getUpdateMessage(false);
if (message != null) {
new BukkitRunnable() {
@Override
public void run() {
Player p = Bukkit.getPlayer(uuid);
if (p != null) {
p.sendMessage(PREFIX + message);
}
}
}.runTask(plugin);
}
}
}.runTaskAsynchronously(plugin);
}
public static void sendUpdateMessage(final Plugin plugin) {
new BukkitRunnable() {
@Override
public void run() {
final String message = getUpdateMessage(true);
if (message != null) {
new BukkitRunnable() {
@Override
public void run() {
plugin.getLogger().warning(message);
}
}.runTask(plugin);
}
}
}.runTaskAsynchronously(plugin);
}
private static String getUpdateMessage(boolean console) {
if (ViaVersion.getInstance().getVersion().equals("${project.version}")) {
return "You are using a debug/custom version, consider updating.";
}
String newestString = getNewestVersion();
if (newestString == null) {
if (console) {
return "Could not check for updates, check your connection.";
} else {
return null;
}
}
Version current;
try {
current = new Version(ViaVersion.getInstance().getVersion());
} catch (IllegalArgumentException e) {
return "You are using a debug/custom version, consider updating.";
}
Version newest = new Version(newestString);
if (current.compareTo(newest) < 0)
return "There is a newer version available: " + newest.toString();
else if (console && current.compareTo(newest) != 0) {
return "You are running a newer version than is released!";
}
return null;
}
private static String getNewestVersion() {
try {
URL url = new URL(URL + PLUGIN + "?" + System.currentTimeMillis());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(true);
connection.addRequestProperty("User-Agent", "Mozilla/4.76");
connection.setDoOutput(true);
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String input;
String content = "";
while ((input = br.readLine()) != null) {
content = content + input;
}
br.close();
JSONParser parser = new JSONParser();
JSONObject statistics;
try {
statistics = (JSONObject) parser.parse(content);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
return (String) statistics.get("version");
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
}
}
}
@@ -0,0 +1,65 @@
package us.myles.ViaVersion.update;
import org.apache.commons.lang.StringUtils;
public class Version implements Comparable<Version> {
private int[] parts;
public Version(String value) {
if (value == null)
throw new IllegalArgumentException("Version can not be null");
if (value.matches("^[0-9]+(\\.[0-9]+)*$") == false)
throw new IllegalArgumentException("Invalid version format");
String[] split = value.split("\\.");
parts = new int[split.length];
for (int i = 0; i < split.length; i += 1)
parts[i] = Integer.parseInt(split[i]);
}
@Override
public String toString() {
String[] split = new String[parts.length];
for (int i = 0; i < parts.length; i += 1)
split[i] = String.valueOf(parts[i]);
return StringUtils.join(split, ".");
}
public static int compare(Version verA, Version verB) {
if (verA == verB) return 0;
if (verA == null) return -1;
if (verB == null) return 1;
int max = Math.max(verA.parts.length, verB.parts.length);
for (int i = 0; i < max; i += 1) {
int partA = i < verA.parts.length ? verA.parts[i] : 0;
int partB = i < verB.parts.length ? verB.parts[i] : 0;
if (partA < partB) return -1;
if (partA > partB) return 1;
}
return 0;
}
@Override
public int compareTo(Version that) {
return compare(this, that);
}
public static boolean equals(Version verA, Version verB) {
if (verA == verB) return true;
if (verA == null) return false;
if (verB == null) return false;
return compare(verA, verB) == 0;
}
@Override
public boolean equals(Object that) {
return that instanceof Version && equals(this, (Version) that);
}
}
@@ -8,6 +8,8 @@ import io.netty.buffer.ByteBufOutputStream;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import org.spacehq.opennbt.NBTIO;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import us.myles.ViaVersion.chunks.MagicBitSet;
import us.myles.ViaVersion.chunks.PacketChunk;
import us.myles.ViaVersion.chunks.PacketChunkData;
@@ -26,9 +28,6 @@ import java.util.BitSet;
import java.util.List;
import java.util.UUID;
import org.spacehq.opennbt.NBTIO;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
public class PacketUtil {
private static Method DECODE_METHOD;
private static Method ENCODE_METHOD;
@@ -406,7 +405,8 @@ public class PacketUtil {
public static boolean containsCause(Throwable t, Class<? extends Throwable> c) {
while (t != null) {
t = t.getCause();
if (c.isAssignableFrom(t.getClass())) return true;
if (t != null)
if (c.isAssignableFrom(t.getClass())) return true;
}
return false;
}
+4
View File
@@ -0,0 +1,4 @@
# Should ViaVersion check for updates?
checkforupdates: true
# Should we send any bulk chunks, in sync (may be slower but fixes timings)
sync-chunks: true