3
0
Mirror von https://github.com/ViaVersion/ViaVersion.git synchronisiert 2024-12-26 16:12:42 +01:00

Merge pull request #509 from MylesIsCool/modular

Merge modular into 1.11
Dieser Commit ist enthalten in:
Mats 2016-10-04 19:57:24 +02:00 committet von GitHub
Commit 8ae2842e5f
274 geänderte Dateien mit 8513 neuen und 3019 gelöschten Zeilen

Datei anzeigen

@ -1,7 +1,7 @@
sudo: false
language: java
jdk: oraclejdk7
jdk: oraclejdk8
cache:
directories:

64
bukkit/pom.xml Normale Datei
Datei anzeigen

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>viaversion-parent</artifactId>
<groupId>us.myles</groupId>
<version>1.0.0-ALPHA-modules</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>viaversion-bukkit</artifactId>
<properties>
<!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.8.8-R0.1-SNAPSHOT</bukkitVersion>
</properties>
<build>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<!-- Common Module -->
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion-common</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<!-- Bukkit API, http://www.spigotmc.org/ or http://bukkit.org/ -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkitVersion}</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
<exclusion>
<artifactId>gson</artifactId>
<groupId>com.google.code.gson</groupId>
</exclusion>
<exclusion>
<artifactId>persistence-api</artifactId>
<groupId>javax.persistence</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

Datei anzeigen

@ -0,0 +1,251 @@
package us.myles.ViaVersion;
import com.google.gson.JsonObject;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaAPI;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
import us.myles.ViaVersion.api.platform.TaskId;
import us.myles.ViaVersion.api.platform.ViaPlatform;
import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator;
import us.myles.ViaVersion.bukkit.commands.BukkitCommandHandler;
import us.myles.ViaVersion.bukkit.commands.BukkitCommandSender;
import us.myles.ViaVersion.bukkit.platform.*;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
import us.myles.ViaVersion.dump.PluginInfo;
import us.myles.ViaVersion.util.GsonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform {
private BukkitCommandHandler commandHandler;
private boolean compatSpigotBuild = false;
private boolean spigot = true;
private boolean lateBind = false;
private boolean protocolSupport = false;
@Getter
private BukkitConfigAPI conf;
@Getter
private ViaAPI<Player> api = new BukkitViaAPI(this);
private List<Runnable> queuedTasks = new ArrayList<>();
private List<Runnable> asyncQueuedTasks = new ArrayList<>();
public ViaVersionPlugin() {
// Command handler
commandHandler = new BukkitCommandHandler();
// Init platform
Via.init(ViaManager.builder()
.platform(this)
.commandHandler(commandHandler)
.injector(new BukkitViaInjector())
.loader(new BukkitViaLoader(this))
.build());
// Config magic
conf = new BukkitConfigAPI();
// For compatibility
ViaVersion.setInstance(this);
// Check if we're using protocol support too
protocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
if (protocolSupport) {
getLogger().info("Hooking into ProtocolSupport, to prevent issues!");
try {
BukkitViaInjector.patchLists();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onLoad() {
// Spigot detector
try {
Class.forName("org.spigotmc.SpigotConfig");
} catch (ClassNotFoundException e) {
spigot = false;
}
// Check if it's a spigot build with a protocol mod
try {
compatSpigotBuild = NMSUtil.nms("PacketEncoder").getDeclaredField("version") != null;
} catch (Exception e) {
compatSpigotBuild = false;
}
// Generate classes needed (only works if it's compat or ps)
ClassGenerator.generate();
lateBind = !BukkitViaInjector.isBinded();
getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!"));
if (!lateBind) {
Via.getManager().init();
}
}
@Override
public void onEnable() {
if (lateBind) {
Via.getManager().init();
}
getCommand("viaversion").setExecutor(commandHandler);
getCommand("viaversion").setTabCompleter(commandHandler);
// Warn them if they have anti-xray on and they aren't using spigot
if (conf.isAntiXRay() && !spigot) {
getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!");
}
// Run queued tasks
for (Runnable r : queuedTasks) {
Bukkit.getScheduler().runTask(this, r);
}
queuedTasks.clear();
// Run async queued tasks
for (Runnable r : asyncQueuedTasks) {
Bukkit.getScheduler().runTaskAsynchronously(this, r);
}
asyncQueuedTasks.clear();
}
@Override
public void onDisable() {
Via.getManager().destroy();
}
public boolean isCompatSpigotBuild() {
return compatSpigotBuild;
}
public boolean isSpigot() {
return this.spigot;
}
public boolean isProtocolSupport() {
return protocolSupport;
}
@Override
public String getPlatformName() {
return "Bukkit";
}
@Override
public String getPluginVersion() {
return getDescription().getVersion();
}
@Override
public TaskId runAsync(Runnable runnable) {
if (isPluginEnabled()) {
return new BukkitTaskId(getServer().getScheduler().runTaskAsynchronously(this, runnable).getTaskId());
} else {
asyncQueuedTasks.add(runnable);
return new BukkitTaskId(null);
}
}
@Override
public TaskId runSync(Runnable runnable) {
if (isPluginEnabled()) {
return new BukkitTaskId(getServer().getScheduler().runTask(this, runnable).getTaskId());
} else {
queuedTasks.add(runnable);
return new BukkitTaskId(null);
}
}
@Override
public TaskId runRepeatingSync(Runnable runnable, Long ticks) {
return new BukkitTaskId(getServer().getScheduler().runTaskTimer(this, runnable, ticks, 0).getTaskId());
}
@Override
public void cancelTask(TaskId taskId) {
if (taskId == null) return;
if (taskId.getObject() == null) return;
if (taskId instanceof BukkitTaskId) {
getServer().getScheduler().cancelTask((Integer) taskId.getObject());
}
}
@Override
public ViaCommandSender[] getOnlinePlayers() {
ViaCommandSender[] array = new ViaCommandSender[Bukkit.getOnlinePlayers().size()];
int i = 0;
for (Player player : Bukkit.getOnlinePlayers()) {
array[i++] = new BukkitCommandSender(player);
}
return array;
}
@Override
public void sendMessage(UUID uuid, String message) {
Player player = Bukkit.getPlayer(uuid);
if (player != null) {
player.sendMessage(message);
}
}
@Override
public boolean kickPlayer(UUID uuid, String message) {
Player player = Bukkit.getPlayer(uuid);
if (player != null) {
player.kickPlayer(message);
return true;
} else {
return false;
}
}
@Override
public boolean isPluginEnabled() {
return Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled();
}
@Override
public ConfigurationProvider getConfigurationProvider() {
return conf;
}
@Override
public void onReload() {
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib.");
for (Player player : Bukkit.getOnlinePlayers()) {
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', getConf().getReloadDisconnectMsg()));
}
} else {
getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting.");
}
}
@Override
public JsonObject getDump() {
JsonObject platformSpecific = new JsonObject();
List<PluginInfo> plugins = new ArrayList<>();
for (Plugin p : Bukkit.getPluginManager().getPlugins())
plugins.add(new PluginInfo(p.isEnabled(), p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), p.getDescription().getAuthors()));
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
// TODO more? ProtocolLib things etc?
return platformSpecific;
}
}

Datei anzeigen

@ -4,8 +4,8 @@ import lombok.Getter;
import org.apache.commons.lang.Validate;
import us.myles.ViaVersion.ViaVersionPlugin;
@Deprecated
public class ViaVersion {
@Getter
private static ViaVersionAPI instance;
@Getter
@ -13,7 +13,7 @@ public class ViaVersion {
public static void setInstance(ViaVersionPlugin plugin) {
Validate.isTrue(instance == null, "Instance is already set");
ViaVersion.instance = plugin;
ViaVersion.instance = (ViaVersionAPI) plugin.getApi();
ViaVersion.config = plugin.getConf();
}
}

Datei anzeigen

@ -11,7 +11,8 @@ import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.util.SortedSet;
import java.util.UUID;
public interface ViaVersionAPI {
@Deprecated
public interface ViaVersionAPI extends ViaAPI<Player> {
/**
* Is the player connection modified by ViaVersion?
*
@ -79,7 +80,7 @@ public interface ViaVersionAPI {
* @param title The title
* @param color The color
* @param style The style
* @return Bossbar instance
* @return BossBar instance
*/
BossBar createBossBar(String title, BossColor color, BossStyle style);
@ -90,7 +91,7 @@ public interface ViaVersionAPI {
* @param health Number between 0 and 1
* @param color The color
* @param style The style
* @return Bossbar instance
* @return BossBar instance
*/
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
@ -102,9 +103,9 @@ public interface ViaVersionAPI {
boolean isDebug();
/**
* Get ViaVersions command handler
* Get ViaVersions commands handler
*
* @return command handler
* @return commands handler
*/
ViaVersionCommand getCommandHandler();

Datei anzeigen

@ -0,0 +1,34 @@
package us.myles.ViaVersion.boss;
import lombok.Getter;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
@Getter
public class ViaBossBar extends CommonBoss<Player> {
public ViaBossBar(String title, float health, BossColor color, BossStyle style) {
super(title, health, color, style);
}
@Override
public BossBar addPlayer(Player player) {
addPlayer(player.getUniqueId());
return this;
}
@Override
public BossBar addPlayers(Player... players) {
for (Player p : players)
addPlayer(p);
return this;
}
@Override
public BossBar removePlayer(Player player) {
removePlayer(player.getUniqueId());
return this;
}
}

Datei anzeigen

@ -0,0 +1,19 @@
package us.myles.ViaVersion.bukkit.classgenerator;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler;
import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler;
public class BasicHandlerConstructor implements HandlerConstructor {
@Override
public BukkitEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
return new BukkitEncodeHandler(info, minecraftEncoder);
}
@Override
public BukkitDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
return new BukkitDecodeHandler(info, minecraftDecoder);
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.classgenerator;
package us.myles.ViaVersion.bukkit.classgenerator;
import javassist.*;
import javassist.expr.ConstructorCall;
@ -6,9 +6,9 @@ import javassist.expr.ExprEditor;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler;
import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
public class ClassGenerator {
private static HandlerConstructor constructor = new BasicHandlerConstructor();
@ -27,17 +27,17 @@ public class ClassGenerator {
}
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
Class decodeSuper = NMSUtil.nms("PacketDecoder");
Class encodeSuper = NMSUtil.nms("PacketEncoder");
// Generate the classes
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
addSpigotCompatibility(pool, BukkitDecodeHandler.class, decodeSuper);
addSpigotCompatibility(pool, BukkitEncodeHandler.class, encodeSuper);
} else {
Class decodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedDecoder");
Class encodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedEncoder");
// Generate the classes
addPSCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
addPSCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
addPSCompatibility(pool, BukkitDecodeHandler.class, decodeSuper);
addPSCompatibility(pool, BukkitEncodeHandler.class, encodeSuper);
}
@ -53,10 +53,10 @@ public class ClassGenerator {
pool.importPackage("io.netty.handler.codec");
// Implement Methods
generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" +
" return new ViaEncodeHandler(info, minecraftEncoder);\n" +
" return new BukkitEncodeHandler(info, minecraftEncoder);\n" +
" }", generated));
generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" +
" return new ViaDecodeHandler(info, minecraftDecoder);\n" +
" return new BukkitDecodeHandler(info, minecraftDecoder);\n" +
" }", generated));
constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance();

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.classgenerator;
package us.myles.ViaVersion.bukkit.classgenerator;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;

Datei anzeigen

@ -0,0 +1,21 @@
package us.myles.ViaVersion.bukkit.commands;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import java.util.List;
public class BukkitCommandHandler extends ViaCommandHandler implements CommandExecutor, TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return onCommand(new BukkitCommandSender(sender), args);
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return onTabComplete(new BukkitCommandSender(sender), args);
}
}

Datei anzeigen

@ -0,0 +1,37 @@
package us.myles.ViaVersion.bukkit.commands;
import lombok.AllArgsConstructor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import java.util.UUID;
@AllArgsConstructor
public class BukkitCommandSender implements ViaCommandSender {
private CommandSender sender;
@Override
public boolean hasPermission(String permission) {
return sender.hasPermission(permission);
}
@Override
public void sendMessage(String msg) {
sender.sendMessage(msg);
}
@Override
public UUID getUUID() {
if (sender instanceof Player) {
return ((Player) sender).getUniqueId();
} else {
return UUID.fromString(getName());
}
}
@Override
public String getName() {
return sender.getName();
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.handlers;
package us.myles.ViaVersion.bukkit.handlers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
@ -7,17 +7,17 @@ import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.classgenerator.ClassGenerator;
import us.myles.ViaVersion.classgenerator.HandlerConstructor;
import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator;
import us.myles.ViaVersion.bukkit.classgenerator.HandlerConstructor;
import java.lang.reflect.Method;
public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
public class BukkitChannelInitializer extends ChannelInitializer<SocketChannel> {
private final ChannelInitializer<SocketChannel> original;
private Method method;
public ViaVersionInitializer(ChannelInitializer<SocketChannel> oldInit) {
public BukkitChannelInitializer(ChannelInitializer<SocketChannel> oldInit) {
this.original = oldInit;
try {
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
@ -43,7 +43,7 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
// Add our transformers
MessageToByteEncoder encoder = constructor.newEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
ByteToMessageDecoder decoder = constructor.newDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
ViaPacketHandler chunkHandler = new ViaPacketHandler(info);
BukkitPacketHandler chunkHandler = new BukkitPacketHandler(info);
socketChannel.pipeline().replace("encoder", "encoder", encoder);
socketChannel.pipeline().replace("decoder", "decoder", decoder);

Datei anzeigen

@ -1,11 +1,9 @@
package us.myles.ViaVersion.handlers;
package us.myles.ViaVersion.bukkit.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.exception.CancelException;
@ -16,13 +14,12 @@ import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class ViaDecodeHandler extends ByteToMessageDecoder {
public class BukkitDecodeHandler extends ByteToMessageDecoder {
private final ByteToMessageDecoder minecraftDecoder;
private final UserConnection info;
public static int PASSTHROUGH_ID = 1000;
public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
public BukkitDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
this.info = info;
this.minecraftDecoder = minecraftDecoder;
}
@ -39,7 +36,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
boolean second = info.incrementReceived();
// Check PPS
if (second) {
if (((ViaVersionPlugin) ViaVersion.getInstance()).handlePPS(info))
if (info.handlePPS())
return;
}
@ -49,7 +46,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
if (id == ViaDecodeHandler.PASSTHROUGH_ID) {
if (id == PacketWrapper.PASSTHROUGH_ID) {
newPacket.writeBytes(bytebuf);
} else {
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);

Datei anzeigen

@ -1,10 +1,11 @@
package us.myles.ViaVersion.handlers;
package us.myles.ViaVersion.bukkit.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.exception.CancelException;
@ -15,11 +16,11 @@ import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class ViaEncodeHandler extends MessageToByteEncoder {
public class BukkitEncodeHandler extends MessageToByteEncoder {
private final UserConnection info;
private final MessageToByteEncoder minecraftEncoder;
public ViaEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
public BukkitEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
this.info = info;
this.minecraftEncoder = minecraftEncoder;
}
@ -27,7 +28,7 @@ public class ViaEncodeHandler extends MessageToByteEncoder {
@Override
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
if (((ViaVersionPlugin) Via.getPlatform()).isCompatSpigotBuild()) {
Field ver = minecraftEncoder.getClass().getDeclaredField("version");
ver.setAccessible(true);
ver.set(minecraftEncoder, ver.get(this));

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.handlers;
package us.myles.ViaVersion.bukkit.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
@ -8,10 +8,10 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.List;
public class ViaPacketHandler extends MessageToMessageEncoder {
public class BukkitPacketHandler extends MessageToMessageEncoder {
private final UserConnection info;
public ViaPacketHandler(UserConnection info) {
public BukkitPacketHandler(UserConnection info) {
this.info = info;
}

Datei anzeigen

@ -1,23 +1,18 @@
package us.myles.ViaVersion.update;
package us.myles.ViaVersion.bukkit.listeners;
import lombok.RequiredArgsConstructor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.update.UpdateUtil;
@RequiredArgsConstructor
public class UpdateListener implements Listener {
private final ViaVersionPlugin plugin;
@EventHandler
public void onJoin(PlayerJoinEvent e) {
if (e.getPlayer().hasPermission("viaversion.update")
&& ViaVersion.getConfig().isCheckForUpdates()) {
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId(), plugin);
&& Via.getConfig().isCheckForUpdates()) {
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
}
}
}

Datei anzeigen

@ -0,0 +1,53 @@
package us.myles.ViaVersion.bukkit.listeners;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol;
@Getter(AccessLevel.PROTECTED)
public class ViaBukkitListener extends ViaListener implements Listener {
private final Plugin plugin;
public ViaBukkitListener(ViaVersionPlugin plugin, Class<? extends Protocol> requiredPipeline) {
super(requiredPipeline);
this.plugin = plugin;
}
/**
* Get the UserConnection from a player
*
* @param player Player object
* @return The UserConnection
*/
protected UserConnection getUserConnection(@NonNull Player player) {
return getUserConnection(player.getUniqueId());
}
/**
* Checks if the player is on the selected pipe
*
* @param player Player Object
* @return True if on pipe
*/
protected boolean isOnPipe(Player player) {
return isOnPipe(player.getUniqueId());
}
/**
* Register as Bukkit event
*/
@Override
public void register() {
if (isRegistered()) return;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
setRegistered(true);
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
@ -12,16 +12,18 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.ItemStack;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import java.util.UUID;
public class ArmorListener extends ViaListener {
public class ArmorListener extends ViaBukkitListener {
private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150");
@ -33,7 +35,11 @@ public class ArmorListener extends ViaListener {
// Ensure that the player is on our pipe
if (!isOnPipe(player)) return;
int armor = ArmorType.calculateArmorPoints(player.getInventory().getArmorContents());
int armor = 0;
for (ItemStack stack : player.getInventory().getArmorContents()) {
armor += ArmorType.findById(stack.getTypeId()).getArmorPoints();
}
PacketWrapper wrapper = new PacketWrapper(0x4B, null, getUserConnection(player));
try {
@ -58,7 +64,7 @@ public class ArmorListener extends ViaListener {
if (human instanceof Player && e.getInventory() instanceof CraftingInventory) {
final Player player = (Player) human;
if (e.getCurrentItem() != null) {
if (ArmorType.isArmor(e.getCurrentItem().getType())) {
if (ArmorType.isArmor(e.getCurrentItem().getTypeId())) {
sendDelayedArmorUpdate(player);
return;
}
@ -102,7 +108,7 @@ public class ArmorListener extends ViaListener {
public void sendDelayedArmorUpdate(final Player player) {
if (!isOnPipe(player)) return; // Don't start a task if the player is not on the pipe
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() {
Via.getPlatform().runSync(new Runnable() {
@Override
public void run() {
sendArmorUpdate(player);

Datei anzeigen

@ -1,16 +1,16 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
public class BlockListener extends ViaListener {
public class BlockListener extends ViaBukkitListener {
public BlockListener(ViaVersionPlugin plugin) {
super(plugin, Protocol1_9TO1_8.class);

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
@ -18,10 +18,11 @@ import org.spacehq.opennbt.tag.builtin.ByteTag;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.Position;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion.util.ReflectionUtil;
@ -29,7 +30,7 @@ import java.io.DataOutput;
import java.io.DataOutputStream;
import java.lang.reflect.Method;
public class CommandBlockListener extends ViaListener {
public class CommandBlockListener extends ViaBukkitListener {
public CommandBlockListener(ViaVersionPlugin plugin) {
super(plugin, Protocol1_9TO1_8.class);
@ -88,7 +89,7 @@ public class CommandBlockListener extends ViaListener {
return;
CommandBlock cmd = (CommandBlock) b.getState();
Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", ReflectionUtil.nms("TileEntityCommand"));
Object tileEntityCommand = ReflectionUtil.get(cmd, "commandBlock", NMSUtil.nms("TileEntityCommand"));
Object updatePacket = ReflectionUtil.invoke(tileEntityCommand, "getUpdatePacket");
PacketWrapper wrapper = generatePacket(updatePacket, getUserConnection(player));
@ -98,12 +99,12 @@ public class CommandBlockListener extends ViaListener {
private PacketWrapper generatePacket(Object updatePacket, UserConnection usr) throws Exception {
PacketWrapper wrapper = new PacketWrapper(0x09, null, usr); // Update block entity
long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", ReflectionUtil.nms("BlockPosition")));
long[] pos = getPosition(ReflectionUtil.get(updatePacket, "a", NMSUtil.nms("BlockPosition")));
wrapper.write(Type.POSITION, new Position(pos[0], pos[1], pos[2])); //Block position
wrapper.write(Type.BYTE, (byte) 2); // Action id always 2
CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", ReflectionUtil.nms("NBTTagCompound")));
CompoundTag nbt = getNBT(ReflectionUtil.get(updatePacket, "c", NMSUtil.nms("NBTTagCompound")));
if (nbt == null) {
wrapper.write(Type.BYTE, (byte) 0); //If nbt is null. Use 0 as nbt
return wrapper;
@ -125,12 +126,12 @@ public class CommandBlockListener extends ViaListener {
}
private boolean isR1() {
return ReflectionUtil.getVersion().equals("v1_8_R1");
return NMSUtil.getVersion().equals("v1_8_R1");
}
private CompoundTag getNBT(Object obj) throws Exception {
ByteBuf buf = Unpooled.buffer();
Method m = ReflectionUtil.nms("NBTCompressedStreamTools").getMethod("a", ReflectionUtil.nms("NBTTagCompound"), DataOutput.class);
Method m = NMSUtil.nms("NBTCompressedStreamTools").getMethod("a", NMSUtil.nms("NBTTagCompound"), DataOutput.class);
m.invoke(null, obj, new DataOutputStream(new ByteBufOutputStream(buf)));
try {
return Type.NBT.read(buf);

Datei anzeigen

@ -1,6 +1,5 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -8,12 +7,13 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.PlayerDeathEvent;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
public class DeathListener extends ViaListener {
public class DeathListener extends ViaBukkitListener {
public DeathListener(ViaVersionPlugin plugin) {
super(plugin, Protocol1_9TO1_8.class);
}
@ -34,7 +34,7 @@ public class DeathListener extends ViaListener {
}
private void sendPacket(final Player p, final String msg) {
Bukkit.getScheduler().runTask(getPlugin(), new Runnable() {
Via.getPlatform().runSync(new Runnable() {
@Override
public void run() {
PacketWrapper wrapper = new PacketWrapper(0x2C, null, getUserConnection(p));

Datei anzeigen

@ -1,7 +1,8 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import us.myles.ViaVersion.api.minecraft.item.Item;
@ -25,7 +26,7 @@ public class HandItemCache extends BukkitRunnable {
List<UUID> players = new ArrayList<>(handCache.keySet());
for (Player p : Bukkit.getOnlinePlayers()) {
handCache.put(p.getUniqueId(), Item.getItem(p.getItemInHand()));
handCache.put(p.getUniqueId(), convert(p.getItemInHand()));
players.remove(p.getUniqueId());
}
// Remove offline players
@ -33,4 +34,9 @@ public class HandItemCache extends BukkitRunnable {
handCache.remove(uuid);
}
}
public static Item convert(ItemStack itemInHand) {
if (itemInHand == null) return new Item((short) 0, (byte) 0, (short) 0, null);
return new Item((short) itemInHand.getTypeId(), (byte) itemInHand.getAmount(), itemInHand.getDurability(), null);
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
import org.bukkit.Location;
import org.bukkit.Material;
@ -6,10 +6,10 @@ import org.bukkit.block.BlockFace;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockPlaceEvent;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.ViaListener;
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
public class PaperPatch extends ViaListener {
public class PaperPatch extends ViaBukkitListener {
public PaperPatch(ViaVersionPlugin plugin) {
super(plugin, Protocol1_9TO1_8.class);

Datei anzeigen

@ -0,0 +1,179 @@
package us.myles.ViaVersion.bukkit.platform;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.util.Config;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class BukkitConfigAPI extends Config implements ViaVersionConfig {
private static List<String> UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers");
public BukkitConfigAPI() {
super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml"));
}
@Override
public boolean isCheckForUpdates() {
return getBoolean("checkforupdates", true);
}
@Override
public boolean isPreventCollision() {
return getBoolean("prevent-collision", true);
}
@Override
public boolean isNewEffectIndicator() {
return getBoolean("use-new-effect-indicator", true);
}
@Override
public boolean isShowNewDeathMessages() {
return getBoolean("use-new-deathmessages", true);
}
@Override
public boolean isSuppressMetadataErrors() {
return getBoolean("suppress-metadata-errors", false);
}
@Override
public boolean isShieldBlocking() {
return getBoolean("shield-blocking", true);
}
@Override
public boolean isHologramPatch() {
return getBoolean("hologram-patch", false);
}
@Override
public boolean isBossbarPatch() {
return getBoolean("bossbar-patch", true);
}
@Override
public boolean isBossbarAntiflicker() {
return getBoolean("bossbar-anti-flicker", false);
}
@Override
public boolean isUnknownEntitiesSuppressed() {
return false;
}
@Override
public double getHologramYOffset() {
return getDouble("hologram-y", -0.96D);
}
@Override
public boolean isBlockBreakPatch() {
return false;
}
@Override
public int getMaxPPS() {
return getInt("max-pps", 800);
}
@Override
public String getMaxPPSKickMessage() {
return getString("max-pps-kick-msg", "Sending packets too fast? lag?");
}
@Override
public int getTrackingPeriod() {
return getInt("tracking-period", 6);
}
@Override
public int getWarningPPS() {
return getInt("tracking-warning-pps", 120);
}
@Override
public int getMaxWarnings() {
return getInt("tracking-max-warnings", 3);
}
@Override
public String getMaxWarningsKickMessage() {
return getString("tracking-max-kick-msg", "You are sending too many packets, :(");
}
@Override
public boolean isAntiXRay() {
return getBoolean("anti-xray-patch", true);
}
@Override
public boolean isSendSupportedVersions() {
return getBoolean("send-supported-versions", false);
}
@Override
public boolean isStimulatePlayerTick() {
return getBoolean("simulate-pt", true);
}
@Override
public boolean isItemCache() {
return getBoolean("item-cache", true);
}
@Override
public boolean isNMSPlayerTicking() {
return getBoolean("nms-player-ticking", true);
}
@Override
public boolean isReplacePistons() {
return getBoolean("replace-pistons", false);
}
@Override
public int getPistonReplacementId() {
return getInt("replacement-piston-id", 0);
}
public boolean isAutoTeam() {
// Collision has to be enabled first
return isPreventCollision() && getBoolean("auto-team", true);
}
@Override
public boolean isForceJsonTransform() {
return getBoolean("force-json-transform", false);
}
@Override
public List<Integer> getBlockedProtocols() {
return getIntegerList("block-protocols");
}
@Override
public String getBlockedDisconnectMsg() {
return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
}
@Override
public String getReloadDisconnectMsg() {
return getString("reload-disconnect-msg", "Server reload, please rejoin!");
}
@Override
protected void handleConfig(Map<String, Object> config) {
// Nothing currently
}
@Override
public List<String> getUnsupportedOptions() {
return UNSUPPORTED;
}
}

Datei anzeigen

@ -0,0 +1,11 @@
package us.myles.ViaVersion.bukkit.platform;
import lombok.AllArgsConstructor;
import lombok.Getter;
import us.myles.ViaVersion.api.platform.TaskId;
@Getter
@AllArgsConstructor
public class BukkitTaskId implements TaskId {
private Integer object;
}

Datei anzeigen

@ -0,0 +1,127 @@
package us.myles.ViaVersion.bukkit.platform;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaAPI;
import us.myles.ViaVersion.api.ViaVersionAPI;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.command.ViaVersionCommand;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.boss.ViaBossBar;
import us.myles.ViaVersion.bukkit.util.ProtocolSupportUtil;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
@AllArgsConstructor
public class BukkitViaAPI implements ViaAPI<Player>, ViaVersionAPI {
private ViaVersionPlugin plugin;
@Override
public int getPlayerVersion(@NonNull Player player) {
if (!isPorted(player))
return getExternalVersion(player);
return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
}
@Override
public int getPlayerVersion(@NonNull UUID uuid) {
if (!isPorted(uuid))
return getExternalVersion(Bukkit.getPlayer(uuid));
return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion();
}
private int getExternalVersion(Player player) {
if (!isProtocolSupport()) {
return ProtocolRegistry.SERVER_PROTOCOL;
} else {
return ProtocolSupportUtil.getProtocolVersion(player);
}
}
@Override
public boolean isPorted(Player player) {
return isPorted(player.getUniqueId());
}
@Override
public boolean isPorted(UUID playerUUID) {
return getPortedPlayers().containsKey(playerUUID);
}
@Override
public String getVersion() {
return plugin.getDescription().getVersion();
}
@Override
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!");
UserConnection ci = getPortedPlayers().get(uuid);
ci.sendRawPacket(packet);
}
@Override
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
sendRawPacket(player.getUniqueId(), packet);
}
@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);
}
@Override
public boolean isDebug() {
return Via.getManager().isDebug();
}
@Override
public ViaVersionCommand getCommandHandler() {
return Via.getManager().getCommandHandler();
}
@Override
public SortedSet<Integer> getSupportedVersions() {
SortedSet<Integer> outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions());
outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols());
return outputSet;
}
@Override
public boolean isCompatSpigotBuild() {
return plugin.isCompatSpigotBuild();
}
@Override
public boolean isSpigot() {
return plugin.isSpigot();
}
@Override
public boolean isProtocolSupport() {
return plugin.isProtocolSupport();
}
public Map<UUID, UserConnection> getPortedPlayers() {
return Via.getManager().getPortedPlayers();
}
}

Datei anzeigen

@ -0,0 +1,247 @@
package us.myles.ViaVersion.bukkit.platform;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import org.bukkit.plugin.PluginDescriptionFile;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.platform.ViaInjector;
import us.myles.ViaVersion.bukkit.handlers.BukkitChannelInitializer;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
import us.myles.ViaVersion.util.ConcurrentList;
import us.myles.ViaVersion.util.ListWrapper;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class BukkitViaInjector implements ViaInjector {
private List<ChannelFuture> injectedFutures = new ArrayList<>();
private List<Pair<Field, Object>> injectedLists = new ArrayList<>();
@Override
public void inject() throws Exception {
try {
Object connection = getServerConnection();
if (connection == null) {
throw new Exception("We failed to find the core component 'ServerConnection', please file an issue on our GitHub.");
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
// Inject the list
List wrapper = new ListWrapper((List) value) {
@Override
public synchronized void handleAdd(Object o) {
synchronized (this) {
if (o instanceof ChannelFuture) {
try {
injectChannelFuture((ChannelFuture) o);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
injectedLists.add(new Pair<>(field, connection));
field.set(connection, wrapper);
// Iterate through current list
synchronized (wrapper) {
for (Object o : (List) value) {
if (o instanceof ChannelFuture) {
injectChannelFuture((ChannelFuture) o);
} else {
break; // not the right list.
}
}
}
}
}
} catch (Exception e) {
Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version.");
throw e;
}
}
private void injectChannelFuture(ChannelFuture future) throws Exception {
try {
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
ChannelInitializer newInit = new BukkitChannelInitializer(oldInit);
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
injectedFutures.add(future);
} catch (NoSuchFieldException e) {
// let's find who to blame!
ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader();
if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) {
PluginDescriptionFile yaml = ReflectionUtil.get(cl, "description", PluginDescriptionFile.class);
throw new Exception("Unable to inject, due to " + bootstrapAcceptor.getClass().getName() + ", try without the plugin " + yaml.getName() + "?");
} else {
throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName());
}
}
} catch (Exception e) {
Via.getPlatform().getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?");
throw e;
}
}
@Override
public void uninject() {
// TODO: Uninject from players currently online to prevent protocol lib issues.
for (ChannelFuture future : injectedFutures) {
ChannelHandler bootstrapAcceptor = future.channel().pipeline().first();
try {
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
if (oldInit instanceof BukkitChannelInitializer) {
ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((BukkitChannelInitializer) oldInit).getOriginal());
}
} catch (Exception e) {
System.out.println("Failed to remove injection handler, reload won't work with connections, please reboot!");
}
}
injectedFutures.clear();
for (Pair<Field, Object> pair : injectedLists) {
try {
Object o = pair.getKey().get(pair.getValue());
if (o instanceof ListWrapper) {
pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList());
}
} catch (IllegalAccessException e) {
System.out.println("Failed to remove injection, reload won't work with connections, please reboot!");
}
}
injectedLists.clear();
}
@Override
public int getServerProtocolVersion() throws Exception {
try {
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
Class<?> pingClazz = NMSUtil.nms("ServerPing");
Object ping = null;
// Search for ping method
for (Field f : serverClazz.getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType().getSimpleName().equals("ServerPing")) {
f.setAccessible(true);
ping = f.get(server);
}
}
}
if (ping != null) {
Object serverData = null;
for (Field f : pingClazz.getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType().getSimpleName().endsWith("ServerData")) {
f.setAccessible(true);
serverData = f.get(ping);
}
}
}
if (serverData != null) {
int protocolVersion = -1;
for (Field f : serverData.getClass().getDeclaredFields()) {
if (f.getType() != null) {
if (f.getType() == int.class) {
f.setAccessible(true);
protocolVersion = (int) f.get(serverData);
}
}
}
if (protocolVersion != -1) {
return protocolVersion;
}
}
}
} catch (Exception e) {
throw new Exception("Failed to get server", e);
}
throw new Exception("Failed to get server");
}
@Override
public String getEncoderName() {
return "encoder";
}
@Override
public String getDecoderName() {
return "decoder";
}
public static Object getServerConnection() throws Exception {
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
Object connection = null;
for (Method m : serverClazz.getDeclaredMethods()) {
if (m.getReturnType() != null) {
if (m.getReturnType().getSimpleName().equals("ServerConnection")) {
if (m.getParameterTypes().length == 0) {
connection = m.invoke(server);
}
}
}
}
return connection;
}
public static void patchLists() throws Exception {
Object connection = getServerConnection();
if (connection == null) {
Via.getPlatform().getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub.");
return;
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
if (!(value instanceof ConcurrentList)) {
ConcurrentList list = new ConcurrentList();
list.addAll((List) value);
field.set(connection, list);
}
}
}
}
public static boolean isBinded() {
try {
Object connection = getServerConnection();
if (connection == null) {
return false;
}
for (Field field : connection.getClass().getDeclaredFields()) {
field.setAccessible(true);
final Object value = field.get(connection);
if (value instanceof List) {
// Inject the list
synchronized (value) {
for (Object o : (List) value) {
if (o instanceof ChannelFuture) {
return true;
} else {
break; // not the right list.
}
}
}
}
}
} catch (Exception e) {
}
return false;
}
}

Datei anzeigen

@ -0,0 +1,92 @@
package us.myles.ViaVersion.bukkit.platform;
import lombok.AllArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.minecraft.item.Item;
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
import us.myles.ViaVersion.bukkit.listeners.UpdateListener;
import us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8.*;
import us.myles.ViaVersion.bukkit.providers.BukkitViaBulkChunkTranslator;
import us.myles.ViaVersion.bukkit.providers.BukkitViaMovementTransmitter;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class BukkitViaLoader implements ViaPlatformLoader {
private ViaVersionPlugin plugin;
@Override
public void load() {
// Update Listener
Bukkit.getPluginManager().registerEvents(new UpdateListener(), plugin);
/* Base Protocol */
final ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion");
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent e) {
Via.getManager().removePortedClient(e.getPlayer().getUniqueId());
}
}, plugin);
/* 1.9 client to 1.8 server */
new ArmorListener(plugin).register();
new CommandBlockListener(plugin).register();
new DeathListener(plugin).register();
new BlockListener(plugin).register();
if (Bukkit.getVersion().toLowerCase().contains("paper") || Bukkit.getVersion().toLowerCase().contains("taco")) {
plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement.");
new PaperPatch(plugin).register();
}
if (plugin.getConf().isItemCache()) {
new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :)
HandItemCache.CACHE = true;
}
/* Providers */
Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new BukkitViaBulkChunkTranslator());
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BukkitViaMovementTransmitter());
Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() {
@Override
public Item getHandItem(final UserConnection info) {
if (HandItemCache.CACHE) {
return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid());
} else {
try {
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Item>() {
@Override
public Item call() throws Exception {
UUID playerUUID = info.get(ProtocolInfo.class).getUuid();
if (Bukkit.getPlayer(playerUUID) != null) {
return HandItemCache.convert(Bukkit.getPlayer(playerUUID).getItemInHand());
}
return null;
}
}).get(10, TimeUnit.SECONDS);
} catch (Exception e) {
System.out.println("Error fetching hand item: " + e.getClass().getName());
if (Via.getManager().isDebug())
e.printStackTrace();
return null;
}
}
}
});
}
}

Datei anzeigen

@ -1,59 +1,46 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage;
package us.myles.ViaVersion.bukkit.providers;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Getter;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@Getter
public class ClientChunks extends StoredObject {
public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider {
// Reflection
private static ReflectionUtil.ClassReflection mapChunkBulkRef;
private static ReflectionUtil.ClassReflection mapChunkRef;
private static Method obfuscateRef;
private static Class<?> worldRef;
static {
try {
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
if (ViaVersion.getInstance().isSpigot()) {
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World"));
worldRef = ReflectionUtil.nms("World");
mapChunkBulkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunkBulk"));
mapChunkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunk"));
if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) {
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, NMSUtil.nms("World"));
}
} catch (ClassNotFoundException e) {
// Ignore as server is probably 1.9+
} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e);
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e);
}
}
private final Set<Long> loadedChunks = Sets.newConcurrentHashSet();
private final Set<Long> bulkChunks = Sets.newConcurrentHashSet();
public ClientChunks(UserConnection user) {
super(user);
}
private static long toLong(int msw, int lsw) {
return ((long) msw << 32) + lsw - -2147483648L;
}
public List<Object> transformMapChunkBulk(Object packet) {
@Override
public List<Object> transformMapChunkBulk(Object packet, ClientChunks clientChunks) {
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);
if (ViaVersion.getConfig().isAntiXRay() && ViaVersion.getInstance().isSpigot()) { //Spigot anti-xray patch
if (Via.getConfig().isAntiXRay() && ((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { //Spigot anti-xray patch
try {
Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class);
@ -79,12 +66,22 @@ public class ClientChunks extends StoredObject {
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
clientChunks.getBulkChunks().add(ClientChunks.toLong(x, z)); // Store for later
list.add(chunkPacket);
}
} catch (Exception e) {
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e);
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e);
}
return list;
}
@Override
public boolean isFiltered(Class<?> packetClass) {
return packetClass.getName().endsWith("PacketPlayOutMapChunkBulk");
}
@Override
public boolean isPacketLevel() {
return false;
}
}

Datei anzeigen

@ -0,0 +1,103 @@
package us.myles.ViaVersion.bukkit.providers;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.bukkit.util.NMSUtil;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
private static boolean USE_NMS = true;
// Used for packet mode
private Object idlePacket;
private Object idlePacket2;
// Use for nms
private Method getHandle;
private Field connection;
private Method handleFlying;
public BukkitViaMovementTransmitter() {
USE_NMS = Via.getConfig().isNMSPlayerTicking();
Class<?> idlePacketClass;
try {
idlePacketClass = NMSUtil.nms("PacketPlayInFlying");
} catch (ClassNotFoundException e) {
return; // We'll hope this is 1.9.4+
}
try {
idlePacket = idlePacketClass.newInstance();
idlePacket2 = idlePacketClass.newInstance();
Field flying = idlePacketClass.getDeclaredField("f");
flying.setAccessible(true);
flying.set(idlePacket2, true);
} catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("Couldn't make player idle packet, help!", e);
}
if (USE_NMS) {
try {
getHandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new RuntimeException("Couldn't find CraftPlayer", e);
}
try {
connection = NMSUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
} catch (NoSuchFieldException | ClassNotFoundException e) {
throw new RuntimeException("Couldn't find Player Connection", e);
}
try {
handleFlying = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
} catch (NoSuchMethodException | ClassNotFoundException e) {
throw new RuntimeException("Couldn't find CraftPlayer", e);
}
}
}
@Override
public Object getFlyingPacket() {
if (idlePacket == null)
throw new NullPointerException("Could not locate flying packet");
return idlePacket2;
}
@Override
public Object getGroundPacket() {
if (idlePacket == null)
throw new NullPointerException("Could not locate flying packet");
return idlePacket;
}
@Override
public void sendPlayer(UserConnection info) {
if (USE_NMS) {
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
if (player != null) {
try {
// Tick player
Object entityPlayer = getHandle.invoke(player);
Object pc = connection.get(entityPlayer);
if (pc != null) {
handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket));
// Tick world
info.get(MovementTracker.class).incrementIdlePacket();
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
} else {
super.sendPlayer(info);
}
}
}

Datei anzeigen

@ -0,0 +1,20 @@
package us.myles.ViaVersion.bukkit.util;
import org.bukkit.Bukkit;
public class NMSUtil {
private static String BASE = Bukkit.getServer().getClass().getPackage().getName();
private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server");
public static Class<?> nms(String className) throws ClassNotFoundException {
return Class.forName(NMS + "." + className);
}
public static Class<?> obc(String className) throws ClassNotFoundException {
return Class.forName(BASE + "." + className);
}
public static String getVersion() {
return BASE.substring(BASE.lastIndexOf('.') + 1);
}
}

Datei anzeigen

@ -1,4 +1,4 @@
package us.myles.ViaVersion.util;
package us.myles.ViaVersion.bukkit.util;
import org.bukkit.entity.Player;

Datei anzeigen

@ -2,10 +2,11 @@ name: ViaVersion
main: us.myles.ViaVersion.ViaVersionPlugin
authors: [_MylesC, Matsv]
version: ${project.version}
description: Allow newer Minecraft versions to connect to an older server version.
load: postworld
loadbefore: [ProtocolLib, ProxyPipe, SpigotLib, SkinRestorer]
softdepend: [ProtocolSupport, PacketListenerApi]
commands:
viaversion:
description: Shows ViaVersion Version and more.
aliases: [viaver]
aliases: [viaver, vvbukkit]

43
bungee/pom.xml Normale Datei
Datei anzeigen

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>viaversion-parent</artifactId>
<groupId>us.myles</groupId>
<version>1.0.0-ALPHA-modules</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>viaversion-bungee</artifactId>
<build>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<!-- BungeeCord API -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.10-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- Common Module -->
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion-common</artifactId>
<version>1.0.0-ALPHA-modules</version>
</dependency>
</dependencies>
</project>

Datei anzeigen

@ -0,0 +1,191 @@
package us.myles.ViaVersion;
import com.google.gson.JsonObject;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaAPI;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.TaskId;
import us.myles.ViaVersion.api.platform.ViaPlatform;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.bungee.commands.BungeeCommand;
import us.myles.ViaVersion.bungee.commands.BungeeCommandHandler;
import us.myles.ViaVersion.bungee.commands.BungeeCommandSender;
import us.myles.ViaVersion.bungee.platform.*;
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
import us.myles.ViaVersion.bungee.storage.BungeeStorage;
import us.myles.ViaVersion.dump.PluginInfo;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.GsonUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class BungeePlugin extends Plugin implements ViaPlatform, Listener {
private BungeeViaAPI api;
private BungeeConfigAPI config;
private BungeeCommandHandler commandHandler;
@Override
public void onLoad() {
api = new BungeeViaAPI();
config = new BungeeConfigAPI(getDataFolder());
commandHandler = new BungeeCommandHandler();
ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler));
// Init platform
Via.init(ViaManager.builder()
.platform(this)
.injector(new BungeeViaInjector())
.loader(new BungeeViaLoader(this))
.commandHandler(commandHandler)
.build());
}
@Override
public void onEnable() {
// Inject
Via.getManager().init();
}
@Override
public String getPlatformName() {
return "BungeeCord";
}
@Override
public String getPluginVersion() {
return getDescription().getVersion();
}
@Override
public TaskId runAsync(Runnable runnable) {
return new BungeeTaskId(getProxy().getScheduler().runAsync(this, runnable).getId());
}
@Override
public TaskId runSync(Runnable runnable) {
return runAsync(runnable);
}
@Override
public TaskId runRepeatingSync(Runnable runnable, Long ticks) {
return new BungeeTaskId(getProxy().getScheduler().schedule(this, runnable, 0, ticks * 50, TimeUnit.MILLISECONDS).getId());
}
@Override
public void cancelTask(TaskId taskId) {
if (taskId == null) return;
if (taskId.getObject() == null) return;
if (taskId instanceof BungeeTaskId) {
getProxy().getScheduler().cancel((Integer) taskId.getObject());
}
}
@Override
public ViaCommandSender[] getOnlinePlayers() {
ViaCommandSender[] array = new ViaCommandSender[getProxy().getPlayers().size()];
int i = 0;
for (ProxiedPlayer player : getProxy().getPlayers()) {
array[i++] = new BungeeCommandSender(player);
}
return array;
}
@Override
public void sendMessage(UUID uuid, String message) {
getProxy().getPlayer(uuid).sendMessage(TextComponent.fromLegacyText(message));
}
@Override
public boolean kickPlayer(UUID uuid, String message) {
if (getProxy().getPlayer(uuid) != null) {
getProxy().getPlayer(uuid).disconnect(TextComponent.fromLegacyText(message));
return true;
}
return false;
}
@Override
public boolean isPluginEnabled() {
return true;
}
@Override
public ViaAPI getApi() {
return api;
}
@Override
public BungeeConfigAPI getConf() {
return config;
}
@Override
public ConfigurationProvider getConfigurationProvider() {
return config;
}
@Override
public void onReload() {
// Injector prints a message <3
}
@Override
public JsonObject getDump() {
JsonObject platformSpecific = new JsonObject();
List<PluginInfo> plugins = new ArrayList<>();
for (Plugin p : ProxyServer.getInstance().getPluginManager().getPlugins())
plugins.add(new PluginInfo(true, p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), Arrays.asList(p.getDescription().getAuthor())));
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
platformSpecific.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getDetectedIds()));
return platformSpecific;
}
@EventHandler
public void onQuit(PlayerDisconnectEvent e) {
Via.getManager().removePortedClient(e.getPlayer().getUniqueId());
}
// Set the handshake version every time someone connects to any server
@EventHandler
public void onServerConnect(ServerConnectEvent e) throws NoSuchFieldException, IllegalAccessException {
UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId());
if (!user.has(BungeeStorage.class)) {
user.put(new BungeeStorage(user, e.getPlayer()));
}
int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName());
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId);
// Check if ViaVersion can support that version
try {
Object pendingConnection = ReflectionUtil.invoke(e.getPlayer(), "getPendingConnection");
Object handshake = ReflectionUtil.invoke(pendingConnection, "getHandshake");
Method setProtocol = handshake.getClass().getDeclaredMethod("setProtocolVersion", int.class);
setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId);
} catch (NoSuchMethodException | InvocationTargetException e1) {
e1.printStackTrace();
}
}
}

Datei anzeigen

@ -0,0 +1,24 @@
package us.myles.ViaVersion.bungee.commands;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.TabExecutor;
public class BungeeCommand extends Command implements TabExecutor{
private final BungeeCommandHandler handler;
public BungeeCommand(BungeeCommandHandler handler) {
super("viaversion", "", "viaver", "vvbungee"); // The CommandHandler will handle the permission
this.handler = handler;
}
@Override
public void execute(CommandSender commandSender, String[] strings) {
handler.onCommand(new BungeeCommandSender(commandSender), strings);
}
@Override
public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) {
return handler.onTabComplete(new BungeeCommandSender(commandSender), strings);
}
}

Datei anzeigen

@ -0,0 +1,15 @@
package us.myles.ViaVersion.bungee.commands;
import us.myles.ViaVersion.bungee.commands.subs.ProbeSubCmd;
import us.myles.ViaVersion.commands.ViaCommandHandler;
public class BungeeCommandHandler extends ViaCommandHandler {
public BungeeCommandHandler() {
try {
registerSubCommand(new ProbeSubCmd());
} catch (Exception e) {
System.out.println("Failed to register Bungee subcommands");
e.printStackTrace();
}
}
}

Datei anzeigen

@ -0,0 +1,38 @@
package us.myles.ViaVersion.bungee.commands;
import lombok.AllArgsConstructor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import java.util.UUID;
@AllArgsConstructor
public class BungeeCommandSender implements ViaCommandSender {
private CommandSender sender;
@Override
public boolean hasPermission(String permission) {
return sender.hasPermission(permission);
}
@Override
public void sendMessage(String msg) {
sender.sendMessage(new TextComponent(msg));
}
@Override
public UUID getUUID() {
if (sender instanceof ProxiedPlayer) {
return ((ProxiedPlayer) sender).getUniqueId();
} else {
return UUID.fromString(getName());
}
}
@Override
public String getName() {
return sender.getName();
}
}

Datei anzeigen

@ -0,0 +1,28 @@
package us.myles.ViaVersion.bungee.commands.subs;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import us.myles.ViaVersion.api.command.ViaSubCommand;
import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI;
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
public class ProbeSubCmd extends ViaSubCommand {
@Override
public String name() {
return "probe";
}
@Override
public String description() {
return "Forces ViaVersion to scan server protocol versions " +
(((BungeeConfigAPI) Via.getConfig()).getBungeePingInterval() == -1 ?
"" : "(Also happens at an interval)");
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
ProtocolDetectorService.getInstance().run();
sendMessage(sender, "&6Started searching for protocol versions");
return true;
}
}

Datei anzeigen

@ -0,0 +1,41 @@
package us.myles.ViaVersion.bungee.handlers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import java.lang.reflect.Method;
public class BungeeChannelInitializer extends ChannelInitializer<SocketChannel> {
private final ChannelInitializer<Channel> original;
private Method method;
public BungeeChannelInitializer(ChannelInitializer<Channel> oldInit) {
this.original = oldInit;
try {
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
this.method.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
UserConnection info = new UserConnection(socketChannel);
// init protocol
new ProtocolPipeline(info);
// Add originals
this.method.invoke(this.original, socketChannel);
// Add our transformers
BungeeEncodeHandler encoder = new BungeeEncodeHandler(info);
BungeeDecodeHandler decoder = new BungeeDecodeHandler(info);
socketChannel.pipeline().addBefore("packet-encoder", "via-encoder", encoder);
socketChannel.pipeline().addBefore("packet-decoder", "via-decoder", decoder);
}
}

Datei anzeigen

@ -0,0 +1,79 @@
package us.myles.ViaVersion.bungee.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.exception.CancelException;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import java.util.List;
@ChannelHandler.Sharable
public class BungeeDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
private final UserConnection info;
public BungeeDecodeHandler(UserConnection info) {
this.info = info;
}
@Override
protected void decode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
// use transformers
if (bytebuf.readableBytes() > 0) {
// Ignore if pending disconnect
if (info.isPendingDisconnect()) {
return;
}
// Increment received
boolean second = info.incrementReceived();
// Check PPS
if (second) {
if (info.handlePPS())
return;
}
if (info.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(bytebuf);
// Transform
ByteBuf newPacket = ctx.alloc().buffer();
try {
if (id == PacketWrapper.PASSTHROUGH_ID) {
newPacket.writeBytes(bytebuf);
} else {
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper);
wrapper.writeToBuffer(newPacket);
}
bytebuf.clear();
bytebuf = newPacket;
} catch (Exception e) {
// Clear Buffer
bytebuf.clear();
// Release Packet, be free!
newPacket.release();
throw e;
}
} else {
bytebuf.retain();
}
out.add(bytebuf);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
super.exceptionCaught(ctx, cause);
}
}

Datei anzeigen

@ -0,0 +1,140 @@
package us.myles.ViaVersion.bungee.handlers;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
import us.myles.ViaVersion.bungee.storage.BungeeStorage;
import us.myles.ViaVersion.bungee.util.BungeePipelineUtil;
import us.myles.ViaVersion.exception.CancelException;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.List;
@ChannelHandler.Sharable
public class BungeeEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
private final UserConnection info;
private boolean handledCompression = false;
public BungeeEncodeHandler(UserConnection info) {
this.info = info;
}
@Override
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
if (bytebuf.readableBytes() == 0) {
throw new CancelException();
}
boolean needsCompress = false;
if (!handledCompression) {
if (ctx.pipeline().names().indexOf("compress") > ctx.pipeline().names().indexOf("via-encoder")) {
// Need to decompress this packet due to bad order
bytebuf = BungeePipelineUtil.decompress(ctx, bytebuf);
ChannelHandler encoder = ctx.pipeline().get("via-decoder");
ChannelHandler decoder = ctx.pipeline().get("via-encoder");
ctx.pipeline().remove(encoder);
ctx.pipeline().remove(decoder);
ctx.pipeline().addAfter("decompress", "via-decoder", encoder);
ctx.pipeline().addAfter("compress", "via-encoder", decoder);
needsCompress = true;
handledCompression = true;
}
}
// Increment sent
info.incrementSent();
if (info.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(bytebuf);
// Transform
ByteBuf oldPacket = bytebuf.copy();
bytebuf.clear();
try {
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;
} finally {
oldPacket.release();
}
}
if (needsCompress) {
bytebuf = BungeePipelineUtil.compress(ctx, bytebuf);
}
out.add(bytebuf.retain());
checkServerChange();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
super.exceptionCaught(ctx, cause);
}
public void checkServerChange() throws Exception {
if (info.has(BungeeStorage.class)) {
BungeeStorage storage = info.get(BungeeStorage.class);
ProxiedPlayer player = storage.getPlayer();
if (player.getServer() != null) {
if (player.getServer() != null && !player.getServer().getInfo().getName().equals(storage.getCurrentServer())) {
String serverName = player.getServer().getInfo().getName();
storage.setCurrentServer(serverName);
int protocolId = ProtocolDetectorService.getProtocolId(serverName);
UserConnection viaConnection = Via.getManager().getConnection(player.getUniqueId());
ProtocolInfo info = viaConnection.get(ProtocolInfo.class);
// Refresh the pipes
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId);
ProtocolPipeline pipeline = viaConnection.get(ProtocolInfo.class).getPipeline();
viaConnection.clearStoredObjects();
pipeline.cleanPipes();
if (protocols != null)
for (Pair<Integer, Protocol> prot : protocols) {
pipeline.add(prot.getValue());
}
viaConnection.put(info);
viaConnection.put(storage);
viaConnection.setActive(protocols != null);
// Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist.
for (Protocol protocol : pipeline.pipes()) {
protocol.init(viaConnection);
}
Object wrapper = ReflectionUtil.get(player, "ch", Object.class);
wrapper.getClass().getDeclaredMethod("setVersion", int.class).invoke(wrapper, protocolId);
Object entityMap = Class.forName("net.md_5.bungee.entitymap.EntityMap").getDeclaredMethod("getEntityMap", int.class).invoke(null, protocolId);
ReflectionUtil.set(player, "entityRewrite", entityMap);
}
}
}
}
}

Datei anzeigen

@ -0,0 +1,18 @@
package us.myles.ViaVersion.bungee.listeners;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.update.UpdateUtil;
public class UpdateListener implements Listener {
@EventHandler
public void onJoin(PostLoginEvent e) {
if (e.getPlayer().hasPermission("viaversion.update")
&& Via.getConfig().isCheckForUpdates()) {
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
}
}
}

Datei anzeigen

@ -0,0 +1,34 @@
package us.myles.ViaVersion.bungee.platform;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.boss.CommonBoss;
public class BungeeBossBar extends CommonBoss<ProxiedPlayer> {
public BungeeBossBar(String title, float health, BossColor color, BossStyle style) {
super(title, health, color, style);
}
@Override
public BossBar addPlayer(ProxiedPlayer player) {
addPlayer(player.getUniqueId());
return this;
}
@Override
public BossBar addPlayers(ProxiedPlayer... players) {
for (ProxiedPlayer p : players)
addPlayer(p);
return this;
}
@Override
public BossBar removePlayer(ProxiedPlayer player) {
removePlayer(player.getUniqueId());
return this;
}
}

Datei anzeigen

@ -0,0 +1,232 @@
package us.myles.ViaVersion.bungee.platform;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
import us.myles.ViaVersion.util.Config;
import java.io.File;
import java.util.*;
public class BungeeConfigAPI extends Config implements ViaVersionConfig {
private static List<String> UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch");
public BungeeConfigAPI(File configFile) {
super(new File(configFile, "config.yml"));
}
@Override
protected void handleConfig(Map<String, Object> config) {
// Parse servers
Map<String, Object> servers;
if (!(config.get("bungee-servers") instanceof Map)) {
servers = new HashMap<>();
} else {
servers = (Map) config.get("bungee-servers");
}
// Convert any bad Protocol Ids
for (Map.Entry<String, Object> entry : new HashSet<>(servers.entrySet())) {
if (!(entry.getValue() instanceof Integer)) {
if (entry.getValue() instanceof String) {
ProtocolVersion found = ProtocolVersion.getClosest((String) entry.getValue());
if (found != null) {
servers.put(entry.getKey(), found.getId());
} else {
servers.remove(entry.getKey()); // Remove!
}
} else {
servers.remove(entry.getKey()); // Remove!
}
}
}
// Ensure default exists
if (!servers.containsKey("default")) {
servers.put("default", BungeeVersionProvider.getLowestSupportedVersion());
}
// Put back
config.put("bungee-servers", servers);
}
@Override
public List<String> getUnsupportedOptions() {
return UNSUPPORTED;
}
public boolean isCheckForUpdates() {
return getBoolean("checkforupdates", true);
}
@Override
public boolean isPreventCollision() {
return getBoolean("prevent-collision", true);
}
@Override
public boolean isNewEffectIndicator() {
return getBoolean("use-new-effect-indicator", true);
}
@Override
public boolean isShowNewDeathMessages() {
return getBoolean("use-new-deathmessages", true);
}
@Override
public boolean isSuppressMetadataErrors() {
return getBoolean("suppress-metadata-errors", false);
}
@Override
public boolean isShieldBlocking() {
return getBoolean("shield-blocking", true);
}
@Override
public boolean isHologramPatch() {
return getBoolean("hologram-patch", false);
}
@Override
public boolean isBossbarPatch() {
return getBoolean("bossbar-patch", true);
}
@Override
public boolean isBossbarAntiflicker() {
return getBoolean("bossbar-anti-flicker", false);
}
@Override
public boolean isUnknownEntitiesSuppressed() {
return false;
}
@Override
public double getHologramYOffset() {
return getDouble("hologram-y", -0.96D);
}
@Override
public boolean isBlockBreakPatch() {
return false;
}
@Override
public int getMaxPPS() {
return getInt("max-pps", 800);
}
@Override
public String getMaxPPSKickMessage() {
return getString("max-pps-kick-msg", "Sending packets too fast? lag?");
}
@Override
public int getTrackingPeriod() {
return getInt("tracking-period", 6);
}
@Override
public int getWarningPPS() {
return getInt("tracking-warning-pps", 120);
}
@Override
public int getMaxWarnings() {
return getInt("tracking-max-warnings", 3);
}
@Override
public String getMaxWarningsKickMessage() {
return getString("tracking-max-kick-msg", "You are sending too many packets, :(");
}
@Override
public boolean isAntiXRay() {
return false;
}
@Override
public boolean isSendSupportedVersions() {
return getBoolean("send-supported-versions", false);
}
@Override
public boolean isStimulatePlayerTick() {
return getBoolean("simulate-pt", true);
}
@Override
public boolean isItemCache() {
return false;
}
@Override
public boolean isNMSPlayerTicking() {
return false;
}
@Override
public boolean isReplacePistons() {
return getBoolean("replace-pistons", false);
}
@Override
public int getPistonReplacementId() {
return getInt("replacement-piston-id", 0);
}
public boolean isAutoTeam() {
// Collision has to be enabled first
return isPreventCollision() && getBoolean("auto-team", true);
}
@Override
public boolean isForceJsonTransform() {
return getBoolean("force-json-transform", false);
}
@Override
public List<Integer> getBlockedProtocols() {
return getIntegerList("block-protocols");
}
@Override
public String getBlockedDisconnectMsg() {
return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
}
@Override
public String getReloadDisconnectMsg() {
return getString("reload-disconnect-msg", "Server reload, please rejoin!");
}
/**
* What is the interval for checking servers via ping
* -1 for disabled
*
* @return Ping interval in seconds
*/
public int getBungeePingInterval() {
return getInt("bungee-ping-interval", 60);
}
/**
* Should the bungee ping be saved to the config on change.
*
* @return True if it should save
*/
public boolean isBungeePingSave() {
return getBoolean("bungee-ping-save", true);
}
/**
* Get the listed server protocols in the config.
* default will be listed as default.
*
* @return Map of String, Integer
*/
public Map<String, Integer> getBungeeServerProtocols() {
return get("bungee-servers", Map.class, new HashMap<>());
}
}

Datei anzeigen

@ -0,0 +1,11 @@
package us.myles.ViaVersion.bungee.platform;
import lombok.AllArgsConstructor;
import lombok.Getter;
import us.myles.ViaVersion.api.platform.TaskId;
@Getter
@AllArgsConstructor
public class BungeeTaskId implements TaskId {
private Integer object;
}

Datei anzeigen

@ -0,0 +1,78 @@
package us.myles.ViaVersion.bungee.platform;
import io.netty.buffer.ByteBuf;
import lombok.NonNull;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaAPI;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
public class BungeeViaAPI implements ViaAPI<ProxiedPlayer> {
@Override
public int getPlayerVersion(@NonNull ProxiedPlayer player) {
if (!isPorted(player.getUniqueId()))
return ProtocolRegistry.SERVER_PROTOCOL;
return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
}
@Override
public int getPlayerVersion(@NonNull UUID uuid) {
if (!isPorted(uuid))
return ProtocolRegistry.SERVER_PROTOCOL;
return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion();
}
@Override
public boolean isPorted(UUID playerUUID) {
return getPortedPlayers().containsKey(playerUUID);
}
@Override
public String getVersion() {
return Via.getPlatform().getPluginVersion();
}
@Override
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!");
UserConnection ci = getPortedPlayers().get(uuid);
ci.sendRawPacket(packet);
}
@Override
public void sendRawPacket(ProxiedPlayer player, ByteBuf packet) throws IllegalArgumentException {
sendRawPacket(player.getUniqueId(), packet);
}
@Override
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
return new BungeeBossBar(title, 1F, color, style);
}
@Override
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
return new BungeeBossBar(title, health, color, style);
}
@Override
public SortedSet<Integer> getSupportedVersions() {
SortedSet<Integer> outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions());
outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols());
return outputSet;
}
public Map<UUID, UserConnection> getPortedPlayers() {
return Via.getManager().getPortedPlayers();
}
}

Datei anzeigen

@ -0,0 +1,59 @@
package us.myles.ViaVersion.bungee.platform;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.platform.ViaInjector;
import us.myles.ViaVersion.bungee.handlers.BungeeChannelInitializer;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
public class BungeeViaInjector implements ViaInjector {
@Override
public void inject() throws Exception {
try {
try {
Class<?> pipelineUtils = Class.forName("net.md_5.bungee.netty.PipelineUtils");
Field field = pipelineUtils.getDeclaredField("SERVER_CHILD");
field.setAccessible(true);
// Remove any final stuff
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
BungeeChannelInitializer newInit = new BungeeChannelInitializer((ChannelInitializer<Channel>) field.get(null));
field.set(null, newInit);
} catch (NoSuchFieldException e) {
throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: ");
}
} catch (Exception e) {
Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version.");
throw e;
}
}
@Override
public void uninject() {
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!");
}
@Override
public int getServerProtocolVersion() throws Exception {
return (int) ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class).get(0);
}
@Override
public String getEncoderName() {
return "via-encoder";
}
@Override
public String getDecoderName() {
return "via-decoder";
}
}

Datei anzeigen

@ -0,0 +1,34 @@
package us.myles.ViaVersion.bungee.platform;
import lombok.AllArgsConstructor;
import net.md_5.bungee.api.ProxyServer;
import us.myles.ViaVersion.BungeePlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
import us.myles.ViaVersion.bungee.listeners.UpdateListener;
import us.myles.ViaVersion.bungee.providers.BungeeMovementTransmitter;
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
import us.myles.ViaVersion.protocols.base.VersionProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import java.util.concurrent.TimeUnit;
@AllArgsConstructor
public class BungeeViaLoader implements ViaPlatformLoader {
private BungeePlugin plugin;
@Override
public void load() {
// Listeners
ProxyServer.getInstance().getPluginManager().registerListener(plugin, plugin);
ProxyServer.getInstance().getPluginManager().registerListener(plugin, new UpdateListener());
// Providers
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter());
Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider());
if (plugin.getConf().getBungeePingInterval() > 0) {
plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, plugin.getConf().getBungeePingInterval(), TimeUnit.SECONDS);
}
}
}

Datei anzeigen

@ -0,0 +1,34 @@
package us.myles.ViaVersion.bungee.providers;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
public class BungeeMovementTransmitter extends MovementTransmitterProvider {
@Override
public Object getFlyingPacket() {
return null;
}
@Override
public Object getGroundPacket() {
return null;
}
public void sendPlayer(UserConnection userConnection) {
if (userConnection.get(ProtocolInfo.class).getState() == State.PLAY) {
PacketWrapper wrapper = new PacketWrapper(0x03, null, userConnection);
wrapper.write(Type.BOOLEAN, userConnection.get(MovementTracker.class).isGround());
try {
wrapper.sendToServer();
} catch (Exception e) {
e.printStackTrace();
}
// PlayerPackets will increment idle
}
}
}

Datei anzeigen

@ -0,0 +1,65 @@
package us.myles.ViaVersion.bungee.providers;
import com.google.common.collect.Lists;
import net.md_5.bungee.api.ProxyServer;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.base.VersionProvider;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.List;
public class BungeeVersionProvider extends VersionProvider {
private static Class<?> ref;
static {
try {
ref = Class.forName("net.md_5.bungee.protocol.ProtocolConstants");
} catch (Exception e) {
System.out.println("Could not detect the ProtocolConstants class");
e.printStackTrace();
}
}
@Override
public int getServerProtocol(UserConnection user) throws Exception {
if (ref == null)
return super.getServerProtocol(user);
// TODO Have one constant list forever until restart? (Might limit plugins if they change this)
List<Integer> list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class);
ProtocolInfo info = user.get(ProtocolInfo.class);
// Bungee supports it
if (list.contains(info.getProtocolVersion()))
return info.getProtocolVersion();
// Older than bungee supports, get the lowest version
if (info.getProtocolVersion() < list.get(0)) {
return getLowestSupportedVersion();
}
// Loop through all protocols to get the closest protocol id that bungee supports
for (Integer protocol : Lists.reverse(list)) {
if (info.getProtocolVersion() > protocol)
return protocol;
}
System.out.println("Panic, no protocol id found for " + info.getProtocolVersion());
return info.getProtocolVersion();
}
public static int getLowestSupportedVersion() {
List<Integer> list;
try {
list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class);
return list.get(0);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// Fallback
return ProxyServer.getInstance().getProtocolVersion();
}
}

Datei anzeigen

@ -0,0 +1,82 @@
package us.myles.ViaVersion.bungee.service;
import lombok.Getter;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.config.ServerInfo;
import us.myles.ViaVersion.BungeePlugin;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI;
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ProtocolDetectorService implements Runnable {
private static final Map<String, Integer> detectedProtocolIds = new ConcurrentHashMap<>();
private BungeePlugin plugin;
@Getter
private static ProtocolDetectorService instance;
public ProtocolDetectorService(BungeePlugin plugin) {
this.plugin = plugin;
instance = this;
}
public static Integer getProtocolId(String serverName) {
// Step 1. Check Config
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
if (servers.containsKey(serverName)) {
return servers.get(serverName);
}
// Step 2. Check Detected
if (detectedProtocolIds.containsKey(serverName)) {
return detectedProtocolIds.get(serverName);
}
// Step 3. Use Default
if (servers.containsKey("default")) {
return servers.get("default");
}
// Step 4: Use bungee lowest supported... *cries*
return BungeeVersionProvider.getLowestSupportedVersion();
}
@Override
public void run() {
for (final Map.Entry<String, ServerInfo> lists : plugin.getProxy().getServers().entrySet()) {
updateProtocolInfo(lists.getKey(), lists.getValue());
}
}
private void updateProtocolInfo(final String key, ServerInfo value) {
value.ping(new Callback<ServerPing>() {
@Override
public void done(ServerPing serverPing, Throwable throwable) {
if (throwable == null) {
detectedProtocolIds.put(key, serverPing.getVersion().getProtocol());
if (((BungeeConfigAPI) Via.getConfig()).isBungeePingSave()) {
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
if (servers.containsKey(key)) {
if (servers.get(key) == serverPing.getVersion().getProtocol()) {
return;
}
}
// Save Server
servers.put(key, serverPing.getVersion().getProtocol());
// Save
Via.getPlatform().getConfigurationProvider().saveConfig();
}
}
}
});
}
public static Map<String, Integer> getDetectedIds() {
return new HashMap<>(detectedProtocolIds);
}
}

Datei anzeigen

@ -0,0 +1,20 @@
package us.myles.ViaVersion.bungee.storage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection;
@Data
@EqualsAndHashCode(callSuper = true)
public class BungeeStorage extends StoredObject {
private ProxiedPlayer player;
private String currentServer;
public BungeeStorage(UserConnection user, ProxiedPlayer player) {
super(user);
this.player = player;
this.currentServer = "";
}
}

Datei anzeigen

@ -0,0 +1,71 @@
package us.myles.ViaVersion.bungee.util;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class BungeePipelineUtil {
private static Method DECODE_METHOD;
private static Method ENCODE_METHOD;
static {
try {
DECODE_METHOD = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
DECODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
System.out.println("Netty issue?");
}
try {
ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
ENCODE_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
System.out.println("Netty issue?");
}
}
public static List<Object> callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
List<Object> output = new ArrayList<>();
try {
BungeePipelineUtil.DECODE_METHOD.invoke(decoder, ctx, input, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return output;
}
public static ByteBuf callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
ByteBuf output = ctx.alloc().buffer();
try {
BungeePipelineUtil.ENCODE_METHOD.invoke(encoder, ctx, input, output);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return output;
}
public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
try {
return (ByteBuf) callDecode((MessageToMessageDecoder) ctx.pipeline().get("decompress"), ctx.pipeline().context("decompress"), bytebuf).get(0);
} catch (InvocationTargetException e) {
e.printStackTrace();
return ctx.alloc().buffer();
}
}
public static ByteBuf compress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
try {
return callEncode((MessageToByteEncoder) ctx.pipeline().get("compress"), ctx.pipeline().context("compress"), bytebuf);
} catch (InvocationTargetException e) {
e.printStackTrace();
return ctx.alloc().buffer();
}
}
}

Datei anzeigen

@ -0,0 +1,4 @@
name: ViaVersion
main: us.myles.ViaVersion.BungeePlugin
author: _MylesC, Matsv
version: ${project.version}

24
common/pom.xml Normale Datei
Datei anzeigen

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>viaversion-parent</artifactId>
<groupId>us.myles</groupId>
<version>1.0.0-ALPHA-modules</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>viaversion-common</artifactId>
<dependencies>
<!-- Snake YAML -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.18-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

Datei anzeigen

@ -0,0 +1,117 @@
package us.myles.ViaVersion;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.ViaInjector;
import us.myles.ViaVersion.api.platform.ViaPlatform;
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
import us.myles.ViaVersion.api.platform.providers.ViaProviders;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.update.UpdateUtil;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@Getter
public class ViaManager {
private final Map<UUID, UserConnection> portedPlayers = new ConcurrentHashMap<>();
private ViaPlatform platform;
private ViaProviders providers = new ViaProviders();
@Setter
private boolean debug = false;
// Internals
private ViaInjector injector;
private ViaCommandHandler commandHandler;
private ViaPlatformLoader loader;
@Builder
public ViaManager(ViaPlatform platform, ViaInjector injector, ViaCommandHandler commandHandler, ViaPlatformLoader loader) {
this.platform = platform;
this.injector = injector;
this.commandHandler = commandHandler;
this.loader = loader;
}
public void init() {
if (System.getProperty("ViaVersion") != null) {
// Reload?
platform.onReload();
}
// Check for updates
if (platform.getConf().isCheckForUpdates())
UpdateUtil.sendUpdateMessage();
// Inject
try {
injector.inject();
} catch (Exception e) {
getPlatform().getLogger().severe("ViaVersion failed to inject:");
e.printStackTrace();
return;
}
// Mark as injected
System.setProperty("ViaVersion", getPlatform().getPluginVersion());
// If successful
platform.runSync(new Runnable() {
@Override
public void run() {
onServerLoaded();
}
});
}
public void onServerLoaded() {
// Load Server Protocol
try {
ProtocolRegistry.SERVER_PROTOCOL = injector.getServerProtocolVersion();
} catch (Exception e) {
getPlatform().getLogger().severe("ViaVersion failed to get the server protocol!");
e.printStackTrace();
}
// Check if there are any pipes to this version
if (ProtocolRegistry.SERVER_PROTOCOL != -1) {
getPlatform().getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(ProtocolRegistry.SERVER_PROTOCOL));
if (!ProtocolRegistry.isWorkingPipe()) {
getPlatform().getLogger().warning("ViaVersion does not have any compatible versions for this server version, please read our resource page carefully.");
}
}
// Load Listeners / Tasks
ProtocolRegistry.onServerLoaded();
// Load Platform
loader.load();
// Refresh Versions
ProtocolRegistry.refreshVersions();
}
public void destroy() {
// Uninject
getPlatform().getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting.");
try {
injector.uninject();
} catch (Exception e) {
getPlatform().getLogger().severe("ViaVersion failed to uninject:");
e.printStackTrace();
}
}
public void addPortedClient(UserConnection info) {
portedPlayers.put(info.get(ProtocolInfo.class).getUuid(), info);
}
public void removePortedClient(UUID clientID) {
portedPlayers.remove(clientID);
}
public UserConnection getConnection(UUID playerUUID) {
return portedPlayers.get(playerUUID);
}
}

Datei anzeigen

@ -12,11 +12,9 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.api.type.TypeConverter;
import us.myles.ViaVersion.exception.InformativeException;
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.State;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import java.io.IOException;
import java.util.ArrayList;
@ -25,14 +23,16 @@ import java.util.LinkedList;
import java.util.List;
public class PacketWrapper {
public static final int PASSTHROUGH_ID = 1000;
private final ByteBuf inputBuffer;
private final UserConnection userConnection;
private boolean send = true;
@Setter
@Getter
private int id = -1;
private LinkedList<Pair<Type, Object>> readableObjects = new LinkedList<>();
private List<Pair<Type, Object>> packetValues = new ArrayList<>();
private final LinkedList<Pair<Type, Object>> readableObjects = new LinkedList<>();
private final List<Pair<Type, Object>> packetValues = new ArrayList<>();
public PacketWrapper(int packetID, ByteBuf inputBuffer, UserConnection userConnection) {
this.id = packetID;
@ -357,7 +357,7 @@ public class PacketWrapper {
* Be careful not to send packets twice.
* (Sends it after current)
* <br />
* <b>This method is no longer used, it's favoured to use send(Protocol) as it will handle the pipeline properly.</b>
* <b>This method is no longer used, it's favoured to use {@link #send(Class)} as it will handle the pipeline properly.</b>
*
* @throws Exception if it fails to write
*/
@ -403,7 +403,7 @@ public class PacketWrapper {
* @param index The index to start from
* @param pipeline The pipeline
* @return The current packetwrapper
* @throws Exception
* @throws Exception If it fails to transform a packet, exception will be thrown
*/
public PacketWrapper apply(Direction direction, State state, int index, List<Protocol> pipeline) throws Exception {
for (int i = index; i < pipeline.size(); i++) { // Copy to prevent from removal.
@ -454,18 +454,16 @@ public class PacketWrapper {
/**
* Send the current packet to the server.
* (Ensure the ID is suitable for the server version)
* (Ensure the ID is suitable for viaversion)
*
* @throws Exception If it failed to write
*/
public void sendToServer() throws Exception {
if (!isCancelled()) {
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
Type.VAR_INT.write(output, ViaDecodeHandler.PASSTHROUGH_ID); // Pass through
writeToBuffer(output);
PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output);
user().getChannel().pipeline().context(Via.getManager().getInjector().getDecoderName()).fireChannelRead(output);
}
}

Datei anzeigen

@ -0,0 +1,45 @@
package us.myles.ViaVersion.api;
import com.google.common.base.Preconditions;
import lombok.Getter;
import us.myles.ViaVersion.ViaManager;
import us.myles.ViaVersion.api.platform.ViaPlatform;
public class Via {
@Getter
private static ViaPlatform platform;
@Getter
private static ViaManager manager;
/**
* Register the ViaManager associated with the platform.
*
* @param viaManager The ViaManager
*/
public static void init(ViaManager viaManager) {
Preconditions.checkArgument(manager == null, "ViaManager is already set");
Via.platform = viaManager.getPlatform();
Via.manager = viaManager;
}
/**
* Get the API associated with the current platform.
*
* @return API instance
*/
public static ViaAPI getAPI() {
Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform");
return Via.platform.getApi();
}
/**
* Get the config associated with the current platform.
*
* @return Config instance
*/
public static ViaVersionConfig getConfig() {
Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform");
return Via.platform.getConf();
}
}

Datei anzeigen

@ -0,0 +1,99 @@
package us.myles.ViaVersion.api;
import io.netty.buffer.ByteBuf;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.boss.BossColor;
import us.myles.ViaVersion.api.boss.BossStyle;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.util.SortedSet;
import java.util.UUID;
/**
* Represents the ViaAPI
*
* @param <T> The player type for the specific platform, for bukkit it's {@code ViaAPI<Player>}
*/
public interface ViaAPI<T> {
/**
* Get protocol number from a player
* Will also retrieve version from ProtocolSupport if it's being used.
*
* @param player Platform player object, eg. Bukkit this is Player
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
*/
int getPlayerVersion(T player);
/**
* Get protocol number from a player
*
* @param uuid UUID of a player
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
*/
int getPlayerVersion(UUID uuid);
/**
* Is player using 1.9?
*
* @param playerUUID UUID of a player
* @return True if the client is on 1.9
* @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(UUID)}
*/
@Deprecated
boolean isPorted(UUID playerUUID);
/**
* Get the version of the plugin
*
* @return Plugin version
*/
String getVersion();
/**
* Send a raw packet to the player (Use new IDs)
*
* @param player Platform player object, eg. Bukkit this is Player
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(T player, ByteBuf packet) throws IllegalArgumentException;
/**
* Send a raw packet to the player (Use new IDs)
*
* @param uuid The uuid from the player to send packet
* @param packet The packet, you need a VarInt ID then the packet contents.
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
*/
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
/**
* Create a new bossbar instance
*
* @param title The title
* @param color The color
* @param style The style
* @return BossBar instance
*/
BossBar createBossBar(String title, BossColor color, BossStyle style);
/**
* Create a new bossbar instance
*
* @param title The title
* @param health Number between 0 and 1
* @param color The color
* @param style The style
* @return BossBar instance
*/
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
/**
* Get the supported protocol versions
* This method removes any blocked protocol versions.
*
* @return a list of protocol versions
* @see ProtocolRegistry#getSupportedVersions() for full list.
*/
SortedSet<Integer> getSupportedVersions();
}

Datei anzeigen

@ -0,0 +1,43 @@
package us.myles.ViaVersion.api;
import lombok.*;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.UUID;
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@RequiredArgsConstructor
public abstract class ViaListener {
private final Class<? extends Protocol> requiredPipeline;
private boolean registered = false;
/**
* Get the UserConnection from an UUID
*
* @param uuid UUID object
* @return The UserConnection
*/
protected UserConnection getUserConnection(@NonNull UUID uuid) {
return Via.getManager().getConnection(uuid);
}
/**
* Checks if the UUID is on the selected pipe
*
* @param uuid UUID Object
* @return True if on pipe
*/
protected boolean isOnPipe(UUID uuid) {
UserConnection userConnection = getUserConnection(uuid);
return userConnection != null &&
userConnection.get(ProtocolInfo.class).getPipeline().contains(requiredPipeline);
}
/**
* Register the event
*/
public abstract void register();
}

Datei anzeigen

@ -1,17 +1,17 @@
package us.myles.ViaVersion.api.boss;
import org.bukkit.entity.Player;
import us.myles.ViaVersion.api.Via;
import java.util.Set;
import java.util.UUID;
public interface BossBar {
public abstract class BossBar<T> {
/**
* Get the current title
*
* @return the title
*/
String getTitle();
public abstract String getTitle();
/**
* Change the title
@ -19,14 +19,14 @@ public interface BossBar {
* @param title Title can be in either JSON or just text
* @return The BossBar object
*/
BossBar setTitle(String title);
public abstract BossBar setTitle(String title);
/**
* Get the health
*
* @return float between 0F - 1F
*/
float getHealth();
public abstract float getHealth();
/**
* Change the health
@ -34,14 +34,14 @@ public interface BossBar {
* @param health this float has to be between 0F - 1F
* @return The BossBar object
*/
BossBar setHealth(float health);
public abstract BossBar setHealth(float health);
/**
* Get the bossbar color
*
* @return The colour
*/
BossColor getColor();
public abstract BossColor getColor();
/**
* Yay colors!
@ -49,14 +49,14 @@ public interface BossBar {
* @param color Whatever color you want!
* @return The BossBar object
*/
BossBar setColor(BossColor color);
public abstract BossBar setColor(BossColor color);
/**
* Get the bosbar style
*
* @return BossStyle
*/
BossStyle getStyle();
public abstract BossStyle getStyle();
/**
* Change the bosbar style
@ -64,15 +64,19 @@ public interface BossBar {
* @param style BossStyle
* @return The BossBar object
*/
BossBar setStyle(BossStyle style);
public abstract BossBar setStyle(BossStyle style);
/**
* Show the bossbar to a player.
*
* @param player The player
* @return The BossBar object
* @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)}
*/
BossBar addPlayer(Player player);
@Deprecated
public BossBar addPlayer(T player) {
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
}
/**
* Show the bossbar to a player (uuid)
@ -80,23 +84,39 @@ public interface BossBar {
* @param player uuid of the player
* @return The BossBar object
*/
BossBar addPlayer(UUID player);
public abstract BossBar addPlayer(UUID player);
/**
* add multiple players
*
* @param players list of players
* @return The BossBar object
* @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)}
*/
BossBar addPlayers(Player... players);
@Deprecated
public BossBar addPlayers(T... players) {
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
}
/**
* Remove the bossbar from a player
*
* @param player The player
* @return The BossBar object
* @deprecated Deprecated use UUID's instead of Player objects {@link #removePlayer(UUID)}
*/
BossBar removePlayer(Player player);
@Deprecated
public BossBar removePlayer(T player) {
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
}
/**
* Removes the bossbar from a player
*
* @param uuid The platers YYUD
* @return The BossBar object
*/
public abstract BossBar removePlayer(UUID uuid);
/**
* Add flags
@ -104,7 +124,7 @@ public interface BossBar {
* @param flag The flag to add
* @return The BossBar object
*/
BossBar addFlag(BossFlag flag);
public abstract BossBar addFlag(BossFlag flag);
/**
* Remove flags.
@ -112,39 +132,39 @@ public interface BossBar {
* @param flag The flag to remove
* @return The BossBar object
*/
BossBar removeFlag(BossFlag flag);
public abstract BossBar removeFlag(BossFlag flag);
/**
* @param flag The flag to check against
* @return True if it has the flag
*/
boolean hasFlag(BossFlag flag);
public abstract boolean hasFlag(BossFlag flag);
/**
* Get players
*
* @return UUIDS from players (sorry I lied)
*/
Set<UUID> getPlayers();
public abstract Set<UUID> getPlayers();
/**
* Show the bossbar to everyone (In the getPlayer set)
*
* @return The BossBar object
*/
BossBar show();
public abstract BossBar show();
/**
* Hide the bossbar from everyone (In the getPlayer set)
*
* @return The BossBar object
*/
BossBar hide();
public abstract BossBar hide();
/**
* Is it visible?
*
* @return visibility changable with show() and hide()
*/
boolean isVisible();
public abstract boolean isVisible();
}

Datei anzeigen

@ -0,0 +1,34 @@
package us.myles.ViaVersion.api.command;
import java.util.UUID;
public interface ViaCommandSender {
/**
* Check if the sender has a permission.
*
* @param permission Permission string eg. viaversion.admin
* @return True if the sender has the permission
*/
boolean hasPermission(String permission);
/**
* Send a message to the sender
*
* @param msg The message to send
*/
void sendMessage(String msg);
/**
* Get the senders UUID.
*
* @return The senders UUID
*/
UUID getUUID();
/**
* Get the senders name.
*
* @return The senders name
*/
String getName();
}

Datei anzeigen

@ -1,6 +1,5 @@
package us.myles.ViaVersion.api.command;
import org.bukkit.command.CommandSender;
import us.myles.ViaVersion.commands.ViaCommandHandler;
import java.util.Collections;
@ -10,14 +9,14 @@ public abstract class ViaSubCommand {
/**
* Subcommand name
*
* @return The command name
* @return The commands name
*/
public abstract String name();
/**
* subcommand description, this'll show in /viaversion list
*
* @return The command description
* @return The commands description
*/
public abstract String description();
@ -25,7 +24,7 @@ public abstract class ViaSubCommand {
* Usage example:
* "playerversion [name]"
*
* @return The command usage
* @return The commands usage
*/
public String usage() {
return name();
@ -34,7 +33,7 @@ public abstract class ViaSubCommand {
/**
* Permission, null for everyone
*
* @return The permission required to use the command
* @return The permission required to use the commands
*/
public String permission() {
return "viaversion.admin";
@ -45,9 +44,9 @@ public abstract class ViaSubCommand {
*
* @param sender Command sender
* @param args Arguments
* @return command executed succesfully if false, show usage
* @return commands executed succesfully if false, show usage
*/
public abstract boolean execute(CommandSender sender, String[] args);
public abstract boolean execute(ViaCommandSender sender, String[] args);
/**
* Yay, possibility to implement tab-completion
@ -56,7 +55,7 @@ public abstract class ViaSubCommand {
* @param args args
* @return tab complete possibilities
*/
public List<String> onTabComplete(CommandSender sender, String[] args) {
public List<String> onTabComplete(ViaCommandSender sender, String[] args) {
return Collections.emptyList();
}
@ -67,11 +66,11 @@ public abstract class ViaSubCommand {
/**
* Send message formatted / colored
*
* @param sender command sender
* @param sender commands sender
* @param message string message
* @param args optional objects
*/
public void sendMessage(CommandSender sender, String message, Object... args) {
public void sendMessage(ViaCommandSender sender, String message, Object... args) {
ViaCommandHandler.sendMessage(sender, message, args);
}
}

Datei anzeigen

@ -1,5 +1,7 @@
package us.myles.ViaVersion.api.command;
import java.util.List;
public interface ViaVersionCommand {
/**
* Register your own subcommand inside ViaVersion
@ -24,4 +26,22 @@ public interface ViaVersionCommand {
* @return ViaSubCommand instance
*/
ViaSubCommand getSubCommand(String name);
/**
* Executed when the Command sender executes the commands
*
* @param sender Sender object
* @param args arguments provided
* @return was successful
*/
boolean onCommand(ViaCommandSender sender, String[] args);
/**
* Executed when the Command sender tab-completes
*
* @param sender Sender object
* @param args arguments provided
* @return was successful
*/
List<String> onTabComplete(ViaCommandSender sender, String[] args);
}

Datei anzeigen

@ -0,0 +1,31 @@
package us.myles.ViaVersion.api.configuration;
import java.util.Map;
public interface ConfigurationProvider {
/**
* Sets the specified path to the given value.
*
* @param path Path of the object to set.
* @param value New value to set the path to
*/
void set(String path, Object value);
/**
* Saves the config
*/
void saveConfig();
/**
* Reloads the config
*/
void reloadConfig();
/**
* Get all the configuration values
*
* @return Map with key->values
*/
Map<String, Object> getValues();
}

Datei anzeigen

@ -5,9 +5,9 @@ import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.SocketChannel;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.ChatColor;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import java.util.Map;
@ -66,6 +66,14 @@ public class UserConnection {
storedObjects.put(object.getClass(), object);
}
/**
* Clear all the stored objects
* Used for bungee when switching servers.
*/
public void clearStoredObjects() {
storedObjects.clear();
}
/**
* Send a raw packet to the player
*
@ -73,7 +81,7 @@ public class UserConnection {
* @param currentThread Should it run in the same thread
*/
public void sendRawPacket(final ByteBuf packet, boolean currentThread) {
final ChannelHandler handler = channel.pipeline().get("encoder");
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
if (currentThread) {
channel.pipeline().context(handler).writeAndFlush(packet);
} else {
@ -93,7 +101,7 @@ public class UserConnection {
* @return ChannelFuture of the packet being sent
*/
public ChannelFuture sendRawPacketFuture(final ByteBuf packet) {
final ChannelHandler handler = channel.pipeline().get("encoder");
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
return channel.pipeline().context(handler).writeAndFlush(packet);
}
@ -134,6 +142,37 @@ public class UserConnection {
return false;
}
public boolean handlePPS() {
ViaVersionConfig conf = Via.getConfig();
// Max PPS Checker
if (conf.getMaxPPS() > 0) {
if (getPacketsPerSecond() >= conf.getMaxPPS()) {
disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + ""));
return true; // don't send current packet
}
}
// Tracking PPS Checker
if (conf.getMaxWarnings() > 0 && conf.getTrackingPeriod() > 0) {
if (getSecondsObserved() > conf.getTrackingPeriod()) {
// Reset
setWarnings(0);
setSecondsObserved(1);
} else {
setSecondsObserved(getSecondsObserved() + 1);
if (getPacketsPerSecond() >= conf.getWarningPPS()) {
setWarnings(getWarnings() + 1);
}
if (getWarnings() >= conf.getMaxWarnings()) {
disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + ""));
return true; // don't send current packet
}
}
}
return false;
}
/**
* Disconnect a connection
*
@ -145,18 +184,15 @@ public class UserConnection {
pendingDisconnect = true;
if (get(ProtocolInfo.class).getUuid() != null) {
final UUID uuid = get(ProtocolInfo.class).getUuid();
if (Bukkit.getPlayer(uuid) != null) {
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Runnable() {
@Override
public void run() {
Player player = Bukkit.getPlayer(uuid);
if (player != null)
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason));
Via.getPlatform().runSync(new Runnable() {
@Override
public void run() {
if (!Via.getPlatform().kickPlayer(uuid, ChatColor.translateAlternateColorCodes('&', reason))) {
getChannel().close(); // =)
}
});
return;
}
}
});
}
getChannel().close(); // =)
}
}

Datei anzeigen

@ -0,0 +1,187 @@
package us.myles.ViaVersion.api.entities;
import com.google.common.base.Optional;
import lombok.AllArgsConstructor;
import lombok.Getter;
import us.myles.ViaVersion.api.Via;
// 1.10 Entity / Object ids
public class Entity1_10Types {
public static EntityType getTypeFromId(int typeID, boolean isObject) {
Optional<EntityType> type;
if (isObject)
type = ObjectTypes.getPCEntity(typeID);
else
type = EntityType.findById(typeID);
if (!type.isPresent()) {
Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
return type.get();
}
@AllArgsConstructor
@Getter
public enum EntityType {
ENTITY(-1),
DROPPED_ITEM(1, EntityType.ENTITY),
EXPERIENCE_ORB(2, EntityType.ENTITY),
LEASH_HITCH(8, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
PAINTING(9, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
ARROW(10, EntityType.ENTITY),
SNOWBALL(11, EntityType.ENTITY), // Actually EntityProjectile
FIREBALL(12, EntityType.ENTITY),
SMALL_FIREBALL(13, EntityType.ENTITY),
ENDER_PEARL(14, EntityType.ENTITY), // Actually EntityProjectile
ENDER_SIGNAL(15, EntityType.ENTITY),
THROWN_EXP_BOTTLE(17, EntityType.ENTITY),
ITEM_FRAME(18, EntityType.ENTITY), // Actually EntityHanging
WITHER_SKULL(19, EntityType.ENTITY),
PRIMED_TNT(20, EntityType.ENTITY),
FALLING_BLOCK(21, EntityType.ENTITY),
FIREWORK(22, EntityType.ENTITY),
TIPPED_ARROW(23, EntityType.ARROW),
SPECTRAL_ARROW(24, EntityType.ARROW),
SHULKER_BULLET(25, EntityType.ENTITY),
DRAGON_FIREBALL(26, EntityType.FIREBALL),
ENTITY_LIVING(-1, ENTITY),
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
ENTITY_HUMAN(-1, ENTITY_LIVING),
ARMOR_STAND(30, EntityType.ENTITY_LIVING),
// Vehicles
MINECART_ABSTRACT(-1, ENTITY),
MINECART_COMMAND(40, MINECART_ABSTRACT),
BOAT(41, ENTITY),
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
MINECART_CHEST(43, MINECART_ABSTRACT),
MINECART_FURNACE(44, MINECART_ABSTRACT),
MINECART_TNT(45, MINECART_ABSTRACT),
MINECART_HOPPER(46, MINECART_ABSTRACT),
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
CREEPER(50, ENTITY_INSENTIENT),
SKELETON(51, ENTITY_INSENTIENT),
SPIDER(52, ENTITY_INSENTIENT),
GIANT(53, ENTITY_INSENTIENT),
ZOMBIE(54, ENTITY_INSENTIENT),
SLIME(55, ENTITY_INSENTIENT),
GHAST(56, ENTITY_INSENTIENT),
PIG_ZOMBIE(57, ZOMBIE),
ENDERMAN(58, ENTITY_INSENTIENT),
CAVE_SPIDER(59, SPIDER),
SILVERFISH(60, ENTITY_INSENTIENT),
BLAZE(61, ENTITY_INSENTIENT),
MAGMA_CUBE(62, SLIME),
ENDER_DRAGON(63, ENTITY_INSENTIENT),
WITHER(64, ENTITY_INSENTIENT),
BAT(65, ENTITY_INSENTIENT),
WITCH(66, ENTITY_INSENTIENT),
ENDERMITE(67, ENTITY_INSENTIENT),
GUARDIAN(68, ENTITY_INSENTIENT),
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
SHULKER(69, EntityType.IRON_GOLEM),
PIG(90, ENTITY_AGEABLE),
SHEEP(91, ENTITY_AGEABLE),
COW(92, ENTITY_AGEABLE),
CHICKEN(93, ENTITY_AGEABLE),
SQUID(94, ENTITY_INSENTIENT),
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
MUSHROOM_COW(96, COW),
SNOWMAN(97, EntityType.IRON_GOLEM),
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
HORSE(100, ENTITY_AGEABLE),
RABBIT(101, ENTITY_AGEABLE),
POLAR_BEAR(102, ENTITY_AGEABLE),
VILLAGER(120, ENTITY_AGEABLE),
ENDER_CRYSTAL(200, ENTITY),
SPLASH_POTION(-1, ENTITY),
LINGERING_POTION(-1, SPLASH_POTION),
AREA_EFFECT_CLOUD(-1, ENTITY),
EGG(-1, ENTITY),
FISHING_HOOK(-1, ENTITY),
LIGHTNING(-1, ENTITY),
WEATHER(-1, ENTITY),
PLAYER(-1, ENTITY_HUMAN),
COMPLEX_PART(-1, ENTITY);
private final int id;
private final EntityType parent;
EntityType(int id) {
this.id = id;
this.parent = null;
}
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.absent();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
}
}
@AllArgsConstructor
@Getter
public enum ObjectTypes {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.DROPPED_ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART_ABSTRACT),
TNT_PRIMED(50, EntityType.PRIMED_TNT),
ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL),
TIPPED_ARROW(60, EntityType.TIPPED_ARROW),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME),
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
POTION(73, EntityType.SPLASH_POTION),
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private final int id;
private final EntityType type;
public static Optional<ObjectTypes> findById(int id) {
if (id == -1)
return Optional.absent();
for (ObjectTypes ent : ObjectTypes.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectTypes> output = findById(id);
if (!output.isPresent())
return Optional.absent();
return Optional.of(output.get().getType());
}
}
}

Datei anzeigen

@ -0,0 +1,241 @@
package us.myles.ViaVersion.api.entities;
import com.google.common.base.Optional;
import lombok.AllArgsConstructor;
import lombok.Getter;
import us.myles.ViaVersion.api.Via;
// 1.11 Entity / Object ids TODO maybe in the future instead of copying it, some api.
public class Entity1_11Types {
public static EntityType getTypeFromId(int typeID, boolean isObject) {
Optional<EntityType> type;
if (isObject)
type = ObjectTypes.getPCEntity(typeID);
else
type = EntityType.findById(typeID);
if (!type.isPresent()) {
Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
return EntityType.ENTITY; // Fall back to the basic ENTITY
}
return type.get();
}
@AllArgsConstructor
@Getter
public enum EntityType {
ENTITY(-1),
DROPPED_ITEM(1, ENTITY),
EXPERIENCE_ORB(2, ENTITY),
LEASH_HITCH(8, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
PAINTING(9, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
ARROW(10, ENTITY),
SNOWBALL(11, ENTITY), // Actually EntityProjectile
FIREBALL(12, ENTITY),
SMALL_FIREBALL(13, ENTITY),
ENDER_PEARL(14, ENTITY), // Actually EntityProjectile
ENDER_SIGNAL(15, ENTITY),
THROWN_EXP_BOTTLE(17, ENTITY),
ITEM_FRAME(18, ENTITY), // Actually EntityHanging
WITHER_SKULL(19, ENTITY),
PRIMED_TNT(20, ENTITY),
FALLING_BLOCK(21, ENTITY),
FIREWORK(22, ENTITY),
TIPPED_ARROW(23, ARROW),
SPECTRAL_ARROW(24, ARROW),
SHULKER_BULLET(25, ENTITY),
DRAGON_FIREBALL(26, FIREBALL),
EVOCATION_FANGS(33, ENTITY),
ENTITY_LIVING(-1, ENTITY),
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
ENTITY_HUMAN(-1, ENTITY_LIVING),
ARMOR_STAND(30, ENTITY_LIVING),
EVOCATION_ILLAGER(34, ENTITY_INSENTIENT),
VEX(35, ENTITY_INSENTIENT),
VINDICATION_ILLAGER(36, ENTITY_INSENTIENT),
// Vehicles
MINECART_ABSTRACT(-1, ENTITY),
MINECART_COMMAND(40, MINECART_ABSTRACT),
BOAT(41, ENTITY),
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
MINECART_CHEST(43, MINECART_ABSTRACT),
MINECART_FURNACE(44, MINECART_ABSTRACT),
MINECART_TNT(45, MINECART_ABSTRACT),
MINECART_HOPPER(46, MINECART_ABSTRACT),
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
CREEPER(50, ENTITY_INSENTIENT),
ABSTRACT_SKELETON(-1, ENTITY_INSENTIENT),
SKELETON(51, ABSTRACT_SKELETON),
WITHER_SKELETON(5, ABSTRACT_SKELETON),
STRAY(6, ABSTRACT_SKELETON),
SPIDER(52, ENTITY_INSENTIENT),
GIANT(53, ENTITY_INSENTIENT),
ZOMBIE(54, ENTITY_INSENTIENT),
HUSK(23, ZOMBIE),
ZOMBIE_VILLAGER(27, ZOMBIE),
SLIME(55, ENTITY_INSENTIENT),
GHAST(56, ENTITY_INSENTIENT),
PIG_ZOMBIE(57, ZOMBIE),
ENDERMAN(58, ENTITY_INSENTIENT),
CAVE_SPIDER(59, SPIDER),
SILVERFISH(60, ENTITY_INSENTIENT),
BLAZE(61, ENTITY_INSENTIENT),
MAGMA_CUBE(62, SLIME),
ENDER_DRAGON(63, ENTITY_INSENTIENT),
WITHER(64, ENTITY_INSENTIENT),
BAT(65, ENTITY_INSENTIENT),
WITCH(66, ENTITY_INSENTIENT),
ENDERMITE(67, ENTITY_INSENTIENT),
GUARDIAN(68, ENTITY_INSENTIENT),
ELDER_GUARDIAN(4, EntityType.GUARDIAN), // Moved down to avoid illegal forward reference
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
SHULKER(69, EntityType.IRON_GOLEM),
PIG(90, ENTITY_AGEABLE),
SHEEP(91, ENTITY_AGEABLE),
COW(92, ENTITY_AGEABLE),
CHICKEN(93, ENTITY_AGEABLE),
SQUID(94, ENTITY_INSENTIENT),
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
MUSHROOM_COW(96, COW),
SNOWMAN(97, EntityType.IRON_GOLEM),
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
ABSTRACT_HORSE(-1, ENTITY_AGEABLE),
HORSE(100, ABSTRACT_HORSE),
SKELETON_HORSE(28, ABSTRACT_HORSE),
ZOMBIE_HORSE(29, ABSTRACT_HORSE),
CHESTED_HORSE(-1, ABSTRACT_HORSE),
DONKEY(31, CHESTED_HORSE),
MULE(32, CHESTED_HORSE),
LIAMA(103, CHESTED_HORSE),
RABBIT(101, ENTITY_AGEABLE),
POLAR_BEAR(102, ENTITY_AGEABLE),
VILLAGER(120, ENTITY_AGEABLE),
ENDER_CRYSTAL(200, ENTITY),
SPLASH_POTION(-1, ENTITY),
LINGERING_POTION(-1, SPLASH_POTION),
AREA_EFFECT_CLOUD(-1, ENTITY),
EGG(-1, ENTITY),
FISHING_HOOK(-1, ENTITY),
LIGHTNING(-1, ENTITY),
WEATHER(-1, ENTITY),
PLAYER(-1, ENTITY_HUMAN),
COMPLEX_PART(-1, ENTITY),
LIAMA_SPIT(-1, ENTITY);
private final int id;
private final EntityType parent;
EntityType(int id) {
this.id = id;
this.parent = null;
}
public static Optional<EntityType> findById(int id) {
if (id == -1) // Check if this is called
return Optional.absent();
for (EntityType ent : EntityType.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
}
public boolean is(EntityType... types) {
for (EntityType type : types)
if (is(type))
return true;
return false;
}
public boolean is(EntityType type) {
return this == type;
}
public boolean isOrHasParent(EntityType type) {
EntityType parent = this;
do {
if (parent.equals(type))
return true;
parent = parent.getParent();
} while (parent != null);
return false;
}
}
@AllArgsConstructor
@Getter
public enum ObjectTypes {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.DROPPED_ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART_ABSTRACT),
TNT_PRIMED(50, EntityType.PRIMED_TNT),
ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL),
TIPPED_ARROW(60, EntityType.TIPPED_ARROW),
SNOWBALL(61, EntityType.SNOWBALL),
EGG(62, EntityType.EGG),
FIREBALL(63, EntityType.FIREBALL),
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
ENDER_PEARL(65, EntityType.ENDER_PEARL),
WITHER_SKULL(66, EntityType.WITHER_SKULL),
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
LIAMA_SPIT(68, EntityType.LIAMA_SPIT),
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
ITEM_FRAME(71, EntityType.ITEM_FRAME),
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
POTION(73, EntityType.SPLASH_POTION),
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
FIREWORK(76, EntityType.FIREWORK),
LEASH(77, EntityType.LEASH_HITCH),
ARMOR_STAND(78, EntityType.ARMOR_STAND),
EVOCATION_FANGS(39, EntityType.EVOCATION_FANGS),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private final int id;
private final EntityType type;
public static Optional<ObjectTypes> findById(int id) {
if (id == -1)
return Optional.absent();
for (ObjectTypes ent : ObjectTypes.values())
if (ent.getId() == id)
return Optional.of(ent);
return Optional.absent();
}
public static Optional<EntityType> getPCEntity(int id) {
Optional<ObjectTypes> output = findById(id);
if (!output.isPresent())
return Optional.absent();
return Optional.of(output.get().getType());
}
}
}

Datei anzeigen

@ -0,0 +1,32 @@
package us.myles.ViaVersion.api.minecraft;
import java.util.HashMap;
import java.util.Map;
public enum Environment {
NORMAL(0),
NETHER(-1),
END(1);
private final int id;
private static final Map<Integer, Environment> lookup = new HashMap<>();
static {
for (Environment env : values()) {
lookup.put(env.getId(), env);
}
}
Environment(int id) {
this.id = id;
}
public int getId() {
return id;
}
public static Environment getEnvironmentById(int id) {
return lookup.get(id);
}
}

Datei anzeigen

@ -0,0 +1,12 @@
package us.myles.ViaVersion.api.minecraft;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class EulerAngle {
private float x;
private float y;
private float z;
}

Datei anzeigen

@ -0,0 +1,12 @@
package us.myles.ViaVersion.api.minecraft;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Vector {
private int blockX;
private int blockY;
private int blockZ;
}

Datei anzeigen

@ -0,0 +1,16 @@
package us.myles.ViaVersion.api.minecraft.item;
import lombok.*;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Item {
private short id;
private byte amount;
private short data;
private CompoundTag tag;
}

Datei anzeigen

@ -0,0 +1,20 @@
package us.myles.ViaVersion.api.minecraft.metadata;
import us.myles.ViaVersion.api.type.Type;
public interface MetaType {
/**
* Get the write/read type
*
* @return Type instance
*/
Type getType();
/**
* Get type id from the specific MetaDataType
*
* @return Type id as an integer
*/
int getTypeID();
}

Datei anzeigen

@ -0,0 +1,12 @@
package us.myles.ViaVersion.api.minecraft.metadata;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class Metadata {
private int id;
private MetaType metaType;
private Object value;
}

Datei anzeigen

@ -1,12 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
package us.myles.ViaVersion.api.minecraft.metadata.types;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import us.myles.ViaVersion.api.minecraft.metadata.MetaType;
import us.myles.ViaVersion.api.type.Type;
@RequiredArgsConstructor
@Getter
public enum MetadataTypes {
public enum MetaType1_8 implements MetaType {
Byte(0, Type.BYTE),
Short(1, Type.SHORT),
Int(2, Type.INT),
@ -20,7 +21,7 @@ public enum MetadataTypes {
private final int typeID;
private final Type type;
public static MetadataTypes byId(int id) {
public static MetaType1_8 byId(int id) {
return values()[id];
}
}

Datei anzeigen

@ -1,12 +1,13 @@
package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
package us.myles.ViaVersion.api.minecraft.metadata.types;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import us.myles.ViaVersion.api.minecraft.metadata.MetaType;
import us.myles.ViaVersion.api.type.Type;
@RequiredArgsConstructor
@Getter
public enum NewType {
public enum MetaType1_9 implements MetaType {
Byte(0, Type.BYTE),
VarInt(1, Type.VAR_INT),
Float(2, Type.FLOAT),
@ -25,7 +26,7 @@ public enum NewType {
private final int typeID;
private final Type type;
public static NewType byId(int id) {
public static MetaType1_9 byId(int id) {
return values()[id];
}

Datei anzeigen

@ -0,0 +1,11 @@
package us.myles.ViaVersion.api.platform;
public interface TaskId {
/**
* Returns the actual object represented by this TaskId
* Null if task cannot be cancelled.
*
* @return Platform based Object (don't assume)
*/
Object getObject();
}

Datei anzeigen

@ -0,0 +1,39 @@
package us.myles.ViaVersion.api.platform;
public interface ViaInjector {
/**
* Inject into the current Platform
*
* @throws Exception If there is an error with injecting
*/
void inject() throws Exception;
/**
* Uninject into the current Platform
*
* @throws Exception If there is an error with uninjecting
*/
void uninject() throws Exception;
/**
* Get the server protocol version
*
* @return The server protocol integer
* @throws Exception If there is an error with getting this info, eg. not binded.
*/
int getServerProtocolVersion() throws Exception;
/**
* Get the name of the encoder for then netty pipeline for this platform.
*
* @return The name
*/
String getEncoderName();
/**
* Get the name of the decoder for then netty pipeline for this platform.
*
* @return The name
*/
String getDecoderName();
}

Datei anzeigen

@ -0,0 +1,136 @@
package us.myles.ViaVersion.api.platform;
import com.google.gson.JsonObject;
import us.myles.ViaVersion.api.ViaAPI;
import us.myles.ViaVersion.api.ViaVersionConfig;
import us.myles.ViaVersion.api.command.ViaCommandSender;
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
import java.util.UUID;
import java.util.logging.Logger;
/**
* ViaPlatform represents a platform ViaVersion runs on
*
* @param <T> - The player type for the platform, used for API related methods
*/
public interface ViaPlatform<T> {
/**
* Get the logger for this platform
*
* @return Java Logger (may be a wrapper)
*/
Logger getLogger();
/**
* Get the platform name
*
* @return Platform Name (simply its name)
*/
String getPlatformName();
/**
* Get the plugin version
*
* @return Plugin version as a semver string
*/
String getPluginVersion();
/**
* Run a task Async
*
* @param runnable The task to run
* @return The Task ID
*/
TaskId runAsync(Runnable runnable);
/**
* Run a task Sync
*
* @param runnable The task to run
* @return The Task ID
*/
TaskId runSync(Runnable runnable);
/**
* Run a task at a repeating interval.
* Initial interval is the same as repeat.
*
* @param runnable The task to run
* @param ticks The interval to run it at
* @return The Task ID
*/
TaskId runRepeatingSync(Runnable runnable, Long ticks);
/**
* Cancel a task
*
* @param taskId The task ID to cancel
*/
void cancelTask(TaskId taskId);
/**
* Get the online players
*
* @return Array of ViaCommandSender
*/
ViaCommandSender[] getOnlinePlayers();
/**
* Send a message to a player
*
* @param uuid The player's UUID
* @param message The message to send
*/
void sendMessage(UUID uuid, String message);
/**
* Kick a player for a reason
*
* @param uuid The player's UUID
* @param message The message to kick them with
* @return True if it was successful
*/
boolean kickPlayer(UUID uuid, String message);
/**
* Check if the plugin is enabled.
*
* @return True if it is enabled
*/
boolean isPluginEnabled();
/**
* Get the API for this platform
*
* @return The API for the platform
*/
ViaAPI<T> getApi();
/**
* Get the config API for this platform
*
* @return The config API
*/
ViaVersionConfig getConf();
/**
* Get the backend configuration provider for this platform.
* (On some platforms this returns the same as getConf())
*
* @return The configuration provider
*/
ConfigurationProvider getConfigurationProvider();
/**
* Called when a reload happens
*/
void onReload();
/**
* Get the JSON data required for /viaversion dump
*
* @return The json data
*/
JsonObject getDump();
}

Datei anzeigen

@ -0,0 +1,8 @@
package us.myles.ViaVersion.api.platform;
public interface ViaPlatformLoader {
/**
* Initialise the loading for a platform, eg. registering listeners / providers / events etc.
*/
void load();
}

Datei anzeigen

@ -0,0 +1,4 @@
package us.myles.ViaVersion.api.platform.providers;
public interface Provider {
}

Datei anzeigen

@ -0,0 +1,37 @@
package us.myles.ViaVersion.api.platform.providers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ViaProviders {
private final Map<Class<? extends Provider>, Provider> providers = new HashMap<>();
private final List<Class<? extends Provider>> lonelyProviders = new ArrayList<>();
public void require(Class<? extends Provider> provider) {
lonelyProviders.add(provider);
}
public <T extends Provider> void register(Class<T> provider, T value) {
providers.put(provider, value);
}
public <T extends Provider> void use(Class<T> provider, T value) {
if (lonelyProviders.contains(provider)) {
lonelyProviders.remove(provider);
}
providers.put(provider, value);
}
public <T extends Provider> T get(Class<T> provider) {
if (providers.containsKey(provider)) {
return (T) providers.get(provider);
} else {
if (lonelyProviders.contains(provider)) {
throw new IllegalStateException("There was no provider for " + provider + ", one is required!");
}
return null;
}
}
}

Datei anzeigen

@ -5,6 +5,7 @@ import lombok.Getter;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.providers.ViaProviders;
import us.myles.ViaVersion.api.remapper.PacketRemapper;
import us.myles.ViaVersion.exception.CancelException;
import us.myles.ViaVersion.packets.Direction;
@ -15,8 +16,8 @@ import java.util.List;
import java.util.Map;
public abstract class Protocol {
private Map<Pair<State, Integer>, ProtocolPacket> incoming = new HashMap<>();
private Map<Pair<State, Integer>, ProtocolPacket> outgoing = new HashMap<>();
private final Map<Pair<State, Integer>, ProtocolPacket> incoming = new HashMap<>();
private final Map<Pair<State, Integer>, ProtocolPacket> outgoing = new HashMap<>();
public Protocol() {
registerPackets();
@ -47,11 +48,23 @@ public abstract class Protocol {
/**
* Register listeners for this protocol
*
* @deprecated No longer used as listeners are registered in {@link us.myles.ViaVersion.api.platform.ViaPlatformLoader#load}
*/
@Deprecated
protected void registerListeners() {
}
/**
* Handle protocol registration phase, use this to register providers / tasks.
*
* @param providers The current providers
*/
protected void register(ViaProviders providers) {
}
/**
* Register the packets for this protocol
*/

Datei anzeigen

@ -1,9 +1,9 @@
package us.myles.ViaVersion.api.protocol;
import us.myles.ViaVersion.ViaVersionPlugin;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.ViaVersion;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.platform.ViaPlatform;
import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.packets.PacketType;
import us.myles.ViaVersion.packets.State;
@ -74,7 +74,7 @@ public class ProtocolPipeline extends Protocol {
super.transform(direction, state, packetWrapper);
if (ViaVersion.getInstance().isDebug()) {
if (Via.getManager().isDebug()) {
// Debug packet
String packet = "UNKNOWN";
@ -109,12 +109,12 @@ public class ProtocolPipeline extends Protocol {
}
}
String name = packet + "[" + userConnection.get(ProtocolInfo.class).getProtocolVersion() + "]";
ViaVersionPlugin plugin = (ViaVersionPlugin) ViaVersion.getInstance();
ViaPlatform platform = Via.getPlatform();
String actualUsername = packetWrapper.user().get(ProtocolInfo.class).getUsername();
String username = actualUsername != null ? actualUsername + " " : "";
plugin.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}",
platform.getLogger().log(Level.INFO, "{0}{1}: {2} {3} -> {4} [{5}] Value: {6}",
new Object[]{
username,
direction,
@ -162,4 +162,9 @@ public class ProtocolPipeline extends Protocol {
public List<Protocol> pipes() {
return protocolList;
}
public void cleanPipes() {
pipes().clear();
registerPackets();
}
}

Datei anzeigen

@ -2,8 +2,8 @@ package us.myles.ViaVersion.api.protocol;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.protocols.base.BaseProtocol;
import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4;
import us.myles.ViaVersion.protocols.protocol1_9_1_2to1_9_3_4.Protocol1_9_1_2TO1_9_3_4;
@ -20,20 +20,20 @@ public class ProtocolRegistry {
public static final Protocol BASE_PROTOCOL = new BaseProtocol();
public static int SERVER_PROTOCOL = -1;
// Input Version -> Output Version & Protocol (Allows fast lookup)
private static Map<Integer, Map<Integer, Protocol>> registryMap = new ConcurrentHashMap<>();
private static Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>();
private static List<Protocol> registerList = Lists.newCopyOnWriteArrayList();
private static Set<Integer> supportedVersions = Sets.newConcurrentHashSet();
private static final Map<Integer, Map<Integer, Protocol>> registryMap = new ConcurrentHashMap<>();
private static final Map<Pair<Integer, Integer>, List<Pair<Integer, Protocol>>> pathCache = new ConcurrentHashMap<>();
private static final List<Protocol> registerList = Lists.newCopyOnWriteArrayList();
private static final Set<Integer> supportedVersions = Sets.newConcurrentHashSet();
static {
// Base Protocol
registerProtocol(BASE_PROTOCOL, Arrays.<Integer>asList(), -1);
registerProtocol(BASE_PROTOCOL, Collections.<Integer>emptyList(), -1);
// Register built in protocols
registerProtocol(new Protocol1_9TO1_8(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_8.getId());
registerProtocol(new Protocol1_9_1TO1_9(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9.getId());
registerProtocol(new Protocol1_9_3TO1_9_1_2(), Arrays.asList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId());
registerProtocol(new Protocol1_9_3TO1_9_1_2(), Collections.singletonList(ProtocolVersion.v1_9_3.getId()), ProtocolVersion.v1_9_2.getId());
// Only supported for 1.9.4 server to 1.9 (nothing else)
registerProtocol(new Protocol1_9TO1_9_1(), Arrays.asList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId());
registerProtocol(new Protocol1_9TO1_9_1(), Collections.singletonList(ProtocolVersion.v1_9.getId()), ProtocolVersion.v1_9_2.getId());
registerProtocol(new Protocol1_9_1_2TO1_9_3_4(), Arrays.asList(ProtocolVersion.v1_9_1.getId(), ProtocolVersion.v1_9_2.getId()), ProtocolVersion.v1_9_3.getId());
registerProtocol(new Protocol1_10To1_9_3_4(), Collections.singletonList(ProtocolVersion.v1_10.getId()), ProtocolVersion.v1_9_3.getId());
@ -61,8 +61,9 @@ public class ProtocolRegistry {
registryMap.get(version).put(output, protocol);
}
if (Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled()) {
if (Via.getPlatform().isPluginEnabled()) {
protocol.registerListeners();
protocol.register(Via.getManager().getProviders());
refreshVersions();
} else {
registerList.add(protocol);
@ -106,9 +107,10 @@ public class ProtocolRegistry {
/**
* Called when the server is enabled, to register any non registered listeners.
*/
public static void registerListeners() {
public static void onServerLoaded() {
for (Protocol protocol : registerList) {
protocol.registerListeners();
protocol.register(Via.getManager().getProviders());
}
registerList.clear();
}

Datei anzeigen

@ -51,7 +51,8 @@ public class ProtocolVersion {
register(v1_9_2 = new ProtocolVersion(109, "1.9.2"));
register(v1_9_3 = new ProtocolVersion(110, "1.9.3/4"));
register(v1_10 = new ProtocolVersion(210, "1.10"));
register(vSNAPSHOT = new ProtocolVersion(309, "1.11-SNAPSHOT"));
// Snapshot uses colon as dashes are used other places...
register(vSNAPSHOT = new ProtocolVersion(309, "1.11:SNAPSHOT"));
register(unknown = new ProtocolVersion(-1, "UNKNOWN"));
}
@ -80,6 +81,24 @@ public class ProtocolVersion {
return Collections.unmodifiableList(new ArrayList<>(versions.values()));
}
public static ProtocolVersion getClosest(String protocol) {
for (ProtocolVersion version : versions.values()) {
if (version.getName().equals(protocol))
return version;
if (version.getName().equals(protocol + ".x"))
return version;
String[] parts = version.getName().split("-");
for (String part : parts) {
if (part.equalsIgnoreCase(protocol)) {
return version;
}
if (part.equals(protocol + ".x"))
return version;
}
}
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

Datei anzeigen

@ -9,7 +9,7 @@ import java.util.ArrayList;
import java.util.List;
public abstract class PacketRemapper {
private List<Pair<ValueReader, ValueWriter>> valueRemappers = new ArrayList<>();
private final List<Pair<ValueReader, ValueWriter>> valueRemappers = new ArrayList<>();
public PacketRemapper() {
registerMap();

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen