2016-02-28 23:44:33 +01:00
|
|
|
package us.myles.ViaVersion;
|
|
|
|
|
2016-03-04 20:24:44 +01:00
|
|
|
import io.netty.buffer.ByteBuf;
|
2016-02-28 23:44:33 +01:00
|
|
|
import io.netty.channel.ChannelFuture;
|
|
|
|
import io.netty.channel.ChannelHandler;
|
|
|
|
import io.netty.channel.ChannelInitializer;
|
|
|
|
import io.netty.channel.socket.SocketChannel;
|
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.entity.Player;
|
2016-03-01 22:28:18 +01:00
|
|
|
import org.bukkit.event.EventHandler;
|
|
|
|
import org.bukkit.event.Listener;
|
|
|
|
import org.bukkit.event.player.PlayerQuitEvent;
|
2016-02-29 19:00:56 +01:00
|
|
|
import org.bukkit.inventory.ItemStack;
|
2016-02-28 23:44:33 +01:00
|
|
|
import org.bukkit.plugin.java.JavaPlugin;
|
2016-03-01 22:28:18 +01:00
|
|
|
import us.myles.ViaVersion.api.ViaVersion;
|
|
|
|
import us.myles.ViaVersion.api.ViaVersionAPI;
|
2016-03-06 19:20:39 +01:00
|
|
|
import us.myles.ViaVersion.api.boss.BossBar;
|
|
|
|
import us.myles.ViaVersion.api.boss.BossColor;
|
|
|
|
import us.myles.ViaVersion.api.boss.BossStyle;
|
2016-03-04 21:03:46 +01:00
|
|
|
import us.myles.ViaVersion.armor.ArmorListener;
|
2016-03-06 19:20:39 +01:00
|
|
|
import us.myles.ViaVersion.boss.ViaBossBar;
|
2016-03-03 17:42:38 +01:00
|
|
|
import us.myles.ViaVersion.commands.ViaVersionCommand;
|
2016-02-28 23:44:33 +01:00
|
|
|
import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
2016-03-05 20:36:06 +01:00
|
|
|
import us.myles.ViaVersion.listeners.CommandBlockListener;
|
2016-03-05 20:48:38 +01:00
|
|
|
import us.myles.ViaVersion.update.UpdateListener;
|
|
|
|
import us.myles.ViaVersion.update.UpdateUtil;
|
2016-03-09 01:51:50 +01:00
|
|
|
import us.myles.ViaVersion.util.ListWrapper;
|
2016-03-02 00:09:29 +01:00
|
|
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
2016-02-28 23:44:33 +01:00
|
|
|
|
2016-03-03 19:12:10 +01:00
|
|
|
import java.lang.reflect.Field;
|
2016-03-09 01:51:50 +01:00
|
|
|
import java.lang.reflect.Method;
|
2016-03-06 14:45:26 +01:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.UUID;
|
2016-03-07 16:22:11 +01:00
|
|
|
import java.util.concurrent.Callable;
|
2016-03-01 22:28:18 +01:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2016-03-06 14:49:33 +01:00
|
|
|
import java.util.concurrent.Future;
|
2016-02-28 23:44:33 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
2016-03-01 22:28:18 +01:00
|
|
|
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
|
|
|
|
2016-03-07 15:43:31 +01:00
|
|
|
private final Map<UUID, ConnectionInfo> portedPlayers = new ConcurrentHashMap<>();
|
2016-03-05 00:10:07 +01:00
|
|
|
private boolean debug = false;
|
2016-03-01 22:28:18 +01:00
|
|
|
|
2016-03-07 15:43:31 +01:00
|
|
|
public static ItemStack getHandItem(final ConnectionInfo info) {
|
|
|
|
try {
|
2016-03-07 16:22:11 +01:00
|
|
|
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<ItemStack>() {
|
|
|
|
@Override
|
|
|
|
public ItemStack call() throws Exception {
|
|
|
|
if (info.getPlayer() != null) {
|
|
|
|
return info.getPlayer().getItemInHand();
|
|
|
|
}
|
|
|
|
return null;
|
2016-03-07 15:43:31 +01:00
|
|
|
}
|
|
|
|
}).get(10, TimeUnit.SECONDS);
|
|
|
|
} catch (Exception e) {
|
2016-03-08 22:20:52 +01:00
|
|
|
System.out.println("Error fetching hand item: " + e.getClass().getName());
|
2016-03-09 01:51:50 +01:00
|
|
|
if (ViaVersion.getInstance().isDebug())
|
|
|
|
e.printStackTrace();
|
2016-03-07 15:43:31 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-28 23:44:33 +01:00
|
|
|
@Override
|
|
|
|
public void onEnable() {
|
2016-03-01 22:28:18 +01:00
|
|
|
ViaVersion.setInstance(this);
|
2016-03-06 10:39:58 +01:00
|
|
|
saveDefaultConfig();
|
2016-03-03 19:12:10 +01:00
|
|
|
if (System.getProperty("ViaVersion") != null) {
|
2016-03-02 16:21:07 +01:00
|
|
|
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
|
2016-03-05 22:23:14 +01:00
|
|
|
getLogger().severe("Some features may not work.");
|
2016-03-02 16:21:07 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-03 14:28:26 +01:00
|
|
|
getLogger().info("ViaVersion " + getDescription().getVersion() + " is now enabled, injecting. (Allows 1.8 to be accessed via 1.9)");
|
2016-03-09 01:51:50 +01:00
|
|
|
injectPacketHandler();
|
2016-03-09 22:16:58 +01:00
|
|
|
new ViaIdleThread(portedPlayers).runTaskTimerAsynchronously(this, 1L, 1L); // Updates player's idle status
|
2016-03-09 01:51:50 +01:00
|
|
|
|
2016-03-06 17:16:26 +01:00
|
|
|
if (getConfig().getBoolean("checkforupdates"))
|
2016-03-05 21:54:35 +01:00
|
|
|
UpdateUtil.sendUpdateMessage(this);
|
2016-03-04 21:03:46 +01:00
|
|
|
|
2016-03-01 22:28:18 +01:00
|
|
|
Bukkit.getPluginManager().registerEvents(new Listener() {
|
|
|
|
@EventHandler
|
|
|
|
public void onPlayerQuit(PlayerQuitEvent e) {
|
2016-03-04 20:24:44 +01:00
|
|
|
removePortedClient(e.getPlayer().getUniqueId());
|
2016-03-01 22:28:18 +01:00
|
|
|
}
|
|
|
|
}, this);
|
2016-03-04 21:03:46 +01:00
|
|
|
|
|
|
|
Bukkit.getPluginManager().registerEvents(new ArmorListener(this), this);
|
2016-03-05 20:36:06 +01:00
|
|
|
Bukkit.getPluginManager().registerEvents(new CommandBlockListener(this), this);
|
2016-03-06 15:11:36 +01:00
|
|
|
Bukkit.getPluginManager().registerEvents(new UpdateListener(this), this);
|
2016-03-04 21:03:46 +01:00
|
|
|
|
2016-03-05 00:10:07 +01:00
|
|
|
getCommand("viaversion").setExecutor(new ViaVersionCommand(this));
|
2016-02-28 23:44:33 +01:00
|
|
|
}
|
|
|
|
|
2016-03-09 01:51:50 +01:00
|
|
|
public void injectPacketHandler() {
|
|
|
|
try {
|
|
|
|
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
|
|
|
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
|
|
|
Object connection = serverClazz.getDeclaredMethod("getServerConnection").invoke(server);
|
|
|
|
if (connection == null) {
|
|
|
|
System.out.println("connection is null!!");
|
|
|
|
//try others
|
|
|
|
for (Method m : serverClazz.getDeclaredMethods()) {
|
|
|
|
if (m.getReturnType() != null && !m.getName().equals("getServerConnection")) {
|
|
|
|
if (m.getReturnType().getSimpleName().equals("ServerConnection")) {
|
|
|
|
if (m.getParameterTypes().length == 0) {
|
|
|
|
connection = m.invoke(server);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (connection == null) {
|
|
|
|
getLogger().warning("We failed to find the ServerConnection? :(");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (connection != null) {
|
|
|
|
for (Field field : connection.getClass().getDeclaredFields()) {
|
|
|
|
field.setAccessible(true);
|
2016-03-09 13:08:21 +01:00
|
|
|
final Object value = field.get(connection);
|
2016-03-09 01:51:50 +01:00
|
|
|
if (value instanceof List) {
|
|
|
|
// Inject the list
|
2016-03-09 15:12:50 +01:00
|
|
|
List wrapper = new ListWrapper((List) value) {
|
2016-03-09 01:51:50 +01:00
|
|
|
@Override
|
2016-03-09 15:12:50 +01:00
|
|
|
public synchronized void handleAdd(Object o) {
|
|
|
|
synchronized (this) {
|
2016-03-09 13:08:21 +01:00
|
|
|
if (o instanceof ChannelFuture) {
|
|
|
|
inject((ChannelFuture) o);
|
|
|
|
}
|
2016-03-09 01:51:50 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-09 15:12:50 +01:00
|
|
|
};
|
|
|
|
field.set(connection, wrapper);
|
2016-03-09 01:51:50 +01:00
|
|
|
// Iterate through current list
|
2016-03-09 15:12:50 +01:00
|
|
|
synchronized (wrapper) {
|
2016-03-09 13:08:21 +01:00
|
|
|
for (Object o : (List) value) {
|
|
|
|
if (o instanceof ChannelFuture) {
|
|
|
|
inject((ChannelFuture) o);
|
|
|
|
} else {
|
|
|
|
break; // not the right list.
|
|
|
|
}
|
2016-03-09 01:51:50 +01:00
|
|
|
}
|
2016-03-06 17:16:26 +01:00
|
|
|
}
|
2016-03-03 19:12:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-09 01:51:50 +01:00
|
|
|
System.setProperty("ViaVersion", getDescription().getVersion());
|
|
|
|
} catch (Exception e) {
|
|
|
|
getLogger().severe("Unable to inject handlers, are you on 1.8? ");
|
|
|
|
e.printStackTrace();
|
2016-02-29 13:49:14 +01:00
|
|
|
}
|
2016-03-09 01:51:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void inject(ChannelFuture future) {
|
|
|
|
try {
|
|
|
|
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
|
|
|
|
try {
|
|
|
|
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
|
|
|
ChannelInitializer newInit = new ViaVersionInitializer(oldInit);
|
|
|
|
|
|
|
|
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
|
|
|
|
} catch (NoSuchFieldException e) {
|
|
|
|
// field not found
|
|
|
|
throw new Exception("Unable to find childHandler, blame " + bootstrapAcceptor.getClass().getName());
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
getLogger().severe("Have you got late-bind enabled with something else? (ProtocolLib?)");
|
|
|
|
e.printStackTrace();
|
2016-02-28 23:44:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 22:28:18 +01:00
|
|
|
@Override
|
|
|
|
public boolean isPorted(Player player) {
|
2016-03-06 19:20:39 +01:00
|
|
|
return isPorted(player.getUniqueId());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isPorted(UUID playerUUID) {
|
|
|
|
return portedPlayers.containsKey(playerUUID);
|
2016-03-01 22:28:18 +01:00
|
|
|
}
|
|
|
|
|
2016-03-03 14:57:04 +01:00
|
|
|
@Override
|
|
|
|
public String getVersion() {
|
|
|
|
return getDescription().getVersion();
|
|
|
|
}
|
|
|
|
|
2016-03-04 20:24:44 +01:00
|
|
|
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
|
2016-03-06 19:20:39 +01:00
|
|
|
sendRawPacket(player.getUniqueId(), packet);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
|
|
|
|
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not on 1.9");
|
|
|
|
ConnectionInfo ci = portedPlayers.get(uuid);
|
2016-03-04 20:24:44 +01:00
|
|
|
ci.sendRawPacket(packet);
|
|
|
|
}
|
|
|
|
|
2016-03-06 19:20:39 +01:00
|
|
|
@Override
|
|
|
|
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
|
|
|
|
return new ViaBossBar(title, 1F, color, style);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
|
|
|
|
return new ViaBossBar(title, health, color, style);
|
|
|
|
}
|
|
|
|
|
2016-03-05 00:10:07 +01:00
|
|
|
@Override
|
|
|
|
public boolean isDebug() {
|
|
|
|
return this.debug;
|
|
|
|
}
|
|
|
|
|
2016-03-07 15:43:31 +01:00
|
|
|
public void setDebug(boolean value) {
|
|
|
|
this.debug = value;
|
|
|
|
}
|
|
|
|
|
2016-03-06 14:45:26 +01:00
|
|
|
@Override
|
|
|
|
public boolean isSyncedChunks() {
|
|
|
|
return getConfig().getBoolean("sync-chunks", true);
|
|
|
|
}
|
|
|
|
|
2016-03-07 00:22:45 +01:00
|
|
|
public boolean isPreventCollision() {
|
|
|
|
return getConfig().getBoolean("prevent-collision", true);
|
|
|
|
}
|
2016-03-07 23:55:57 +01:00
|
|
|
|
|
|
|
public boolean isSuppressMetadataErrors() {
|
|
|
|
return getConfig().getBoolean("suppress-metadata-errors", false);
|
|
|
|
}
|
2016-03-07 00:22:45 +01:00
|
|
|
|
2016-03-09 13:08:21 +01:00
|
|
|
public boolean isShieldBlocking() {
|
|
|
|
return getConfig().getBoolean("shield-blocking", true);
|
|
|
|
}
|
|
|
|
|
2016-03-09 22:08:50 +01:00
|
|
|
public boolean isHologramPatch() {
|
|
|
|
return getConfig().getBoolean("hologram-patch", false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public double getHologramYOffset() {
|
|
|
|
return getConfig().getDouble("hologram-y", -1D);
|
|
|
|
}
|
|
|
|
|
2016-03-07 00:22:45 +01:00
|
|
|
public boolean isAutoTeam() {
|
|
|
|
// Collision has to be enabled first
|
2016-03-07 16:22:11 +01:00
|
|
|
if (!isPreventCollision()) return false;
|
2016-03-07 00:22:45 +01:00
|
|
|
return getConfig().getBoolean("auto-team", true);
|
|
|
|
}
|
|
|
|
|
2016-03-04 20:24:44 +01:00
|
|
|
public void addPortedClient(ConnectionInfo info) {
|
|
|
|
portedPlayers.put(info.getUUID(), info);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removePortedClient(UUID clientID) {
|
|
|
|
portedPlayers.remove(clientID);
|
2016-03-01 22:28:18 +01:00
|
|
|
}
|
2016-03-05 21:54:35 +01:00
|
|
|
|
2016-03-06 14:49:33 +01:00
|
|
|
public void run(final Runnable runnable, boolean wait) {
|
2016-03-06 14:45:26 +01:00
|
|
|
try {
|
2016-03-07 16:22:11 +01:00
|
|
|
Future f = Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Boolean>() {
|
|
|
|
@Override
|
|
|
|
public Boolean call() throws Exception {
|
|
|
|
runnable.run();
|
|
|
|
return true;
|
|
|
|
}
|
2016-03-06 14:49:33 +01:00
|
|
|
});
|
2016-03-06 17:16:26 +01:00
|
|
|
if (wait) {
|
2016-03-06 14:49:33 +01:00
|
|
|
f.get(10, TimeUnit.SECONDS);
|
|
|
|
}
|
2016-03-06 14:45:26 +01:00
|
|
|
} catch (Exception e) {
|
2016-03-08 22:23:36 +01:00
|
|
|
System.out.println("Failed to run task: " + e.getClass().getName());
|
2016-03-09 01:51:50 +01:00
|
|
|
if (ViaVersion.getInstance().isDebug())
|
|
|
|
e.printStackTrace();
|
2016-03-06 14:45:26 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-06 10:39:58 +01:00
|
|
|
}
|