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:
Commit
8ae2842e5f
@ -1,7 +1,7 @@
|
||||
sudo: false
|
||||
|
||||
language: java
|
||||
jdk: oraclejdk7
|
||||
jdk: oraclejdk8
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
64
bukkit/pom.xml
Normale Datei
64
bukkit/pom.xml
Normale Datei
@ -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>
|
251
bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java
Normale Datei
251
bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
34
bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java
Normale Datei
34
bukkit/src/main/java/us/myles/ViaVersion/boss/ViaBossBar.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
@ -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;
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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));
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
@ -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);
|
@ -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);
|
@ -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));
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
20
bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/NMSUtil.java
Normale Datei
20
bukkit/src/main/java/us/myles/ViaVersion/bukkit/util/NMSUtil.java
Normale Datei
@ -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);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
package us.myles.ViaVersion.bukkit.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -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
43
bungee/pom.xml
Normale Datei
@ -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>
|
191
bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java
Normale Datei
191
bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java
Normale Datei
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<>());
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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 = "";
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
4
bungee/src/main/resources/bungee.yml
Normale Datei
4
bungee/src/main/resources/bungee.yml
Normale Datei
@ -0,0 +1,4 @@
|
||||
name: ViaVersion
|
||||
main: us.myles.ViaVersion.BungeePlugin
|
||||
author: _MylesC, Matsv
|
||||
version: ${project.version}
|
24
common/pom.xml
Normale Datei
24
common/pom.xml
Normale Datei
@ -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>
|
117
common/src/main/java/us/myles/ViaVersion/ViaManager.java
Normale Datei
117
common/src/main/java/us/myles/ViaVersion/ViaManager.java
Normale Datei
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
45
common/src/main/java/us/myles/ViaVersion/api/Via.java
Normale Datei
45
common/src/main/java/us/myles/ViaVersion/api/Via.java
Normale Datei
@ -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();
|
||||
}
|
||||
}
|
99
common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java
Normale Datei
99
common/src/main/java/us/myles/ViaVersion/api/ViaAPI.java
Normale Datei
@ -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();
|
||||
}
|
43
common/src/main/java/us/myles/ViaVersion/api/ViaListener.java
Normale Datei
43
common/src/main/java/us/myles/ViaVersion/api/ViaListener.java
Normale Datei
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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();
|
||||
}
|
@ -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() {
|
||||
Via.getPlatform().runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Via.getPlatform().kickPlayer(uuid, ChatColor.translateAlternateColorCodes('&', reason))) {
|
||||
getChannel().close(); // =)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
12
common/src/main/java/us/myles/ViaVersion/api/minecraft/Vector.java
Normale Datei
12
common/src/main/java/us/myles/ViaVersion/api/minecraft/Vector.java
Normale Datei
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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];
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
||||
|
11
common/src/main/java/us/myles/ViaVersion/api/platform/TaskId.java
Normale Datei
11
common/src/main/java/us/myles/ViaVersion/api/platform/TaskId.java
Normale Datei
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
136
common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java
Normale Datei
136
common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java
Normale Datei
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package us.myles.ViaVersion.api.platform.providers;
|
||||
|
||||
public interface Provider {
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
@ -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
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren