Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-25 15:50:10 +01:00
Merge branch 'pr/1045'
Dieser Commit ist enthalten in:
Commit
73dccbaf24
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform {
|
||||
private boolean lateBind = false;
|
||||
private boolean protocolSupport = false;
|
||||
@Getter
|
||||
private BukkitConfigAPI conf;
|
||||
private BukkitViaConfig conf;
|
||||
@Getter
|
||||
private ViaAPI<Player> api = new BukkitViaAPI(this);
|
||||
private List<Runnable> queuedTasks = new ArrayList<>();
|
||||
@ -51,7 +51,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform {
|
||||
.loader(new BukkitViaLoader(this))
|
||||
.build());
|
||||
// Config magic
|
||||
conf = new BukkitConfigAPI();
|
||||
conf = new BukkitViaConfig();
|
||||
// For compatibility
|
||||
ViaVersion.setInstance(this);
|
||||
|
||||
|
@ -11,10 +11,10 @@ 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 class BukkitViaConfig extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers", "velocity-ping-interval", "velocity-ping-save", "velocity-servers");
|
||||
|
||||
public BukkitConfigAPI() {
|
||||
public BukkitViaConfig() {
|
||||
super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml"));
|
||||
// Load config
|
||||
reloadConfig();
|
||||
@ -192,7 +192,7 @@ public class BukkitConfigAPI extends Config implements ViaVersionConfig {
|
||||
|
||||
@Override
|
||||
public URL getDefaultConfigURL() {
|
||||
return BukkitConfigAPI.class.getClassLoader().getResource("assets/viaversion/config.yml");
|
||||
return BukkitViaConfig.class.getClassLoader().getResource("assets/viaversion/config.yml");
|
||||
}
|
||||
|
||||
@Override
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -31,13 +31,13 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeePlugin extends Plugin implements ViaPlatform, Listener {
|
||||
private BungeeViaAPI api;
|
||||
private BungeeConfigAPI config;
|
||||
private BungeeViaConfig config;
|
||||
private BungeeCommandHandler commandHandler;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
api = new BungeeViaAPI();
|
||||
config = new BungeeConfigAPI(getDataFolder());
|
||||
config = new BungeeViaConfig(getDataFolder());
|
||||
commandHandler = new BungeeCommandHandler();
|
||||
ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler));
|
||||
// Init platform
|
||||
@ -134,7 +134,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BungeeConfigAPI getConf() {
|
||||
public BungeeViaConfig getConf() {
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ 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.platform.BungeeViaConfig;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
|
||||
public class ProbeSubCmd extends ViaSubCommand {
|
||||
@ -15,7 +15,7 @@ public class ProbeSubCmd extends ViaSubCommand {
|
||||
@Override
|
||||
public String description() {
|
||||
return "Forces ViaVersion to scan server protocol versions " +
|
||||
(((BungeeConfigAPI) Via.getConfig()).getBungeePingInterval() == -1 ?
|
||||
(((BungeeViaConfig) Via.getConfig()).getBungeePingInterval() == -1 ?
|
||||
"" : "(Also happens at an interval)");
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ import java.io.File;
|
||||
import java.net.URL;
|
||||
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", "quick-move-action-fix");
|
||||
public class BungeeViaConfig extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch", "quick-move-action-fix", "velocity-ping-interval", "velocity-ping-save", "velocity-servers");
|
||||
|
||||
public BungeeConfigAPI(File configFile) {
|
||||
public BungeeViaConfig(File configFile) {
|
||||
super(new File(configFile, "config.yml"));
|
||||
// Load config
|
||||
reloadConfig();
|
||||
@ -20,7 +20,7 @@ public class BungeeConfigAPI extends Config implements ViaVersionConfig {
|
||||
|
||||
@Override
|
||||
public URL getDefaultConfigURL() {
|
||||
return BungeeConfigAPI.class.getClassLoader().getResource("assets/viaversion/config.yml");
|
||||
return BungeeViaConfig.class.getClassLoader().getResource("assets/viaversion/config.yml");
|
||||
}
|
||||
|
||||
@Override
|
@ -6,7 +6,7 @@ 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.platform.BungeeViaConfig;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -26,7 +26,7 @@ public class ProtocolDetectorService implements Runnable {
|
||||
|
||||
public static Integer getProtocolId(String serverName) {
|
||||
// Step 1. Check Config
|
||||
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
|
||||
Map<String, Integer> servers = ((BungeeViaConfig) Via.getConfig()).getBungeeServerProtocols();
|
||||
Integer protocol = servers.get(serverName);
|
||||
if (protocol != null) {
|
||||
return protocol;
|
||||
@ -61,8 +61,8 @@ public class ProtocolDetectorService implements Runnable {
|
||||
// Ensure protocol is positive, some services will return -1
|
||||
if (serverPing.getVersion().getProtocol() > 0) {
|
||||
detectedProtocolIds.put(key, serverPing.getVersion().getProtocol());
|
||||
if (((BungeeConfigAPI) Via.getConfig()).isBungeePingSave()) {
|
||||
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
|
||||
if (((BungeeViaConfig) Via.getConfig()).isBungeePingSave()) {
|
||||
Map<String, Integer> servers = ((BungeeViaConfig) Via.getConfig()).getBungeeServerProtocols();
|
||||
Integer protocol = servers.get(key);
|
||||
if (protocol != null && protocol == serverPing.getVersion().getProtocol()) {
|
||||
return;
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@ -17,7 +17,7 @@
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.18</version>
|
||||
<scope>provided</scope>
|
||||
<scope>compile</scope> <!-- Velocity doesn't have snakeyaml -->
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -18,6 +18,8 @@ import us.myles.ViaVersion.util.PipelineUtil;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@Data
|
||||
public class UserConnection {
|
||||
@ -36,7 +38,7 @@ public class UserConnection {
|
||||
// Used for handling warnings (over time)
|
||||
private int secondsObserved = 0;
|
||||
private int warnings = 0;
|
||||
|
||||
private ReadWriteLock velocityLock = new ReentrantReadWriteLock();
|
||||
|
||||
public UserConnection(Channel channel) {
|
||||
this.channel = channel;
|
||||
@ -108,7 +110,8 @@ public class UserConnection {
|
||||
*/
|
||||
public ChannelFuture sendRawPacketFuture(final ByteBuf packet) {
|
||||
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
||||
return channel.pipeline().context(handler).writeAndFlush(packet);
|
||||
ChannelFuture future = channel.pipeline().context(handler).writeAndFlush(packet);
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,7 +221,8 @@ public class UserConnection {
|
||||
}
|
||||
buf.writeBytes(packet);
|
||||
packet.release();
|
||||
final ChannelHandlerContext context = PipelineUtil.getPreviousContext(Via.getManager().getInjector().getDecoderName(), getChannel().pipeline());
|
||||
final ChannelHandlerContext context = PipelineUtil
|
||||
.getPreviousContext(Via.getManager().getInjector().getDecoderName(), getChannel().pipeline());
|
||||
if (currentThread) {
|
||||
if (context != null) {
|
||||
context.fireChannelRead(buf);
|
||||
|
@ -74,7 +74,7 @@ public abstract class ViaCommandHandler implements ViaVersionCommand {
|
||||
|
||||
//SubCommands tabcomplete
|
||||
if (args.length == 1) {
|
||||
if (!args[0].equals("")) {
|
||||
if (!args[0].isEmpty()) {
|
||||
for (ViaSubCommand sub : allowed)
|
||||
if (sub.name().toLowerCase().startsWith(args[0].toLowerCase()))
|
||||
output.add(sub.name());
|
||||
|
@ -5,6 +5,8 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@ -14,6 +16,7 @@ import java.util.List;
|
||||
public class PipelineUtil {
|
||||
private static Method DECODE_METHOD;
|
||||
private static Method ENCODE_METHOD;
|
||||
private static Method MTM_DECODE;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -28,6 +31,12 @@ public class PipelineUtil {
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
MTM_DECODE = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
|
||||
MTM_DECODE.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,6 +75,16 @@ public class PipelineUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Object> callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, Object msg) throws InvocationTargetException {
|
||||
List<Object> output = new ArrayList<>();
|
||||
try {
|
||||
MTM_DECODE.invoke(decoder, ctx, msg, output);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a stack trace contains a certain exception
|
||||
*
|
||||
|
@ -46,6 +46,28 @@ bungee-ping-save: true
|
||||
bungee-servers: {}
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# VELOCITY OPTIONS #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
# Velocity allows you to have different server versions inside.
|
||||
# Instead of you entering all the versions of these servers, we can ping them.
|
||||
#
|
||||
# What interval would you like us to ping at? (in seconds)
|
||||
# Use -1 to disable.
|
||||
velocity-ping-interval: 60
|
||||
# If the above is enabled, should we save the info to the config (in the section below)
|
||||
velocity-ping-save: true
|
||||
# To get a servers protocol, ViaVersion will do the following:
|
||||
# Look for the server in the following section, then look for the last ping if velocity-ping is enabled
|
||||
# otherwise use default.
|
||||
#
|
||||
# The format for the following is:
|
||||
# servername: protocolversion
|
||||
# You can find protocol ids on http://wiki.vg/Protocol_version_numbers
|
||||
# It will fallback to the default option if none found.
|
||||
velocity-servers: {}
|
||||
#
|
||||
#----------------------------------------------------------#
|
||||
# GLOBAL PACKET LIMITER #
|
||||
#----------------------------------------------------------#
|
||||
#
|
||||
|
11
jar/pom.xml
11
jar/pom.xml
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<name>viaversion-jar</name>
|
||||
@ -57,6 +57,10 @@
|
||||
<pattern>org.javassist</pattern>
|
||||
<shadedPattern>us.myles.viaversion.libs.javassist</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.yaml.snakeyaml</pattern>
|
||||
<shadedPattern>us.myles.viaversion.libs.snakeyaml</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
@ -92,6 +96,11 @@
|
||||
<artifactId>viaversion-sponge</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-velocity</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
3
pom.xml
3
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>viaversion-parent</name>
|
||||
@ -21,6 +21,7 @@
|
||||
<module>bungee</module>
|
||||
<module>sponge</module>
|
||||
<module>sponge-legacy</module>
|
||||
<module>velocity</module>
|
||||
<module>jar</module>
|
||||
</modules>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.6.1-SNAPSHOT</version>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -17,7 +17,6 @@ import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.scheduler.Task;
|
||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||
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.platform.TaskId;
|
||||
@ -32,10 +31,8 @@ import us.myles.ViaVersion.util.GsonUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Plugin(id = "viaversion",
|
||||
@ -58,7 +55,7 @@ public class SpongePlugin implements ViaPlatform {
|
||||
@Getter
|
||||
private SpongeViaAPI api = new SpongeViaAPI();
|
||||
@Getter
|
||||
private SpongeConfigAPI conf;
|
||||
private SpongeViaConfig conf;
|
||||
|
||||
@Getter
|
||||
private Logger logger;
|
||||
@ -68,7 +65,7 @@ public class SpongePlugin implements ViaPlatform {
|
||||
// Setup Logger
|
||||
logger = new LoggerWrapper(container.getLogger());
|
||||
// Setup Plugin
|
||||
conf = new SpongeConfigAPI(container, defaultConfig.getParentFile());
|
||||
conf = new SpongeViaConfig(container, defaultConfig.getParentFile());
|
||||
SpongeCommandHandler commandHandler = new SpongeCommandHandler();
|
||||
game.getCommandManager().register(this, commandHandler, "viaversion", "viaver", "vvsponge");
|
||||
getLogger().info("ViaVersion " + getPluginVersion() + " is now loaded!");
|
||||
|
@ -12,11 +12,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class SpongeConfigAPI extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("anti-xray-patch", "bungee-ping-interval", "bungee-ping-save", "bungee-servers", "quick-move-action-fix");
|
||||
public class SpongeViaConfig extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("anti-xray-patch", "bungee-ping-interval", "bungee-ping-save", "bungee-servers", "velocity-ping-interval", "velocity-ping-save", "velocity-servers", "quick-move-action-fix");
|
||||
private final PluginContainer pluginContainer;
|
||||
|
||||
public SpongeConfigAPI(PluginContainer pluginContainer, File configFile) {
|
||||
public SpongeViaConfig(PluginContainer pluginContainer, File configFile) {
|
||||
super(new File(configFile, "config.yml"));
|
||||
this.pluginContainer = pluginContainer;
|
||||
// Load config
|
62
velocity/pom.xml
Normale Datei
62
velocity/pom.xml
Normale Datei
@ -0,0 +1,62 @@
|
||||
<?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>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>viaversion-velocity</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>velocity</id>
|
||||
<url>https://repo.velocitypowered.com/snapshots</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>templating-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>filter-src</id>
|
||||
<goals>
|
||||
<goal>filter-sources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Common Module -->
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Velocity API 1.0 -->
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,5 @@
|
||||
package us.myles.ViaVersion.velocity;
|
||||
|
||||
public class VersionInfo {
|
||||
public static final String VERSION = "${project.version}";
|
||||
}
|
206
velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java
Normale Datei
206
velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java
Normale Datei
@ -0,0 +1,206 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import lombok.Getter;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import org.slf4j.Logger;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
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.dump.PluginInfo;
|
||||
import us.myles.ViaVersion.util.GsonUtil;
|
||||
import us.myles.ViaVersion.velocity.VersionInfo;
|
||||
import us.myles.ViaVersion.velocity.command.VelocityCommandHandler;
|
||||
import us.myles.ViaVersion.velocity.command.VelocityCommandSender;
|
||||
import us.myles.ViaVersion.velocity.platform.*;
|
||||
import us.myles.ViaVersion.velocity.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.velocity.util.LoggerWrapper;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Plugin(
|
||||
id = "viaversion",
|
||||
name = "ViaVersion",
|
||||
version = VersionInfo.VERSION,
|
||||
authors = {"_MylesC", "Matsv"},
|
||||
description = "Allow newer Minecraft versions to connect to an older server version.",
|
||||
url = "https://viaversion.com"
|
||||
)
|
||||
@Getter
|
||||
public class VelocityPlugin implements ViaPlatform<Player> {
|
||||
@Inject
|
||||
private ProxyServer proxy;
|
||||
@Inject
|
||||
public static ProxyServer PROXY;
|
||||
@Inject
|
||||
private Logger loggerslf4j;
|
||||
private java.util.logging.Logger logger;
|
||||
@Inject
|
||||
@DataDirectory
|
||||
private Path configDir;
|
||||
private VelocityViaAPI api;
|
||||
private VelocityViaConfig conf;
|
||||
|
||||
@Subscribe
|
||||
public void onProxyInit(ProxyInitializeEvent e) {
|
||||
PROXY = proxy;
|
||||
VelocityCommandHandler commandHandler = new VelocityCommandHandler();
|
||||
PROXY.getCommandManager().register(commandHandler, "viaver", "vvvelocity", "viaversion");
|
||||
api = new VelocityViaAPI();
|
||||
conf = new VelocityViaConfig(configDir.toFile());
|
||||
logger = new LoggerWrapper(loggerslf4j);
|
||||
Via.init(ViaManager.builder()
|
||||
.platform(this)
|
||||
.commandHandler(commandHandler)
|
||||
.loader(new VelocityViaLoader())
|
||||
.injector(new VelocityViaInjector()).build());
|
||||
Via.getManager().init();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onQuit(DisconnectEvent e) {
|
||||
UserConnection userConnection = Via.getManager().getPortedPlayers().get(e.getPlayer().getUniqueId());
|
||||
if (userConnection != null) {
|
||||
// Only remove if the connection is disconnected (eg. relogin)
|
||||
if (userConnection.getChannel() == null || !userConnection.getChannel().isOpen()) {
|
||||
Via.getManager().removePortedClient(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
String proxyImpl = ProxyServer.class.getPackage().getImplementationTitle();
|
||||
return (proxyImpl != null) ? proxyImpl : "Velocity";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
String version = ProxyServer.class.getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "Unknown";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return VersionInfo.VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runAsync(Runnable runnable) {
|
||||
return runSync(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runSync(Runnable runnable) {
|
||||
return runSync(runnable, 0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runSync(Runnable runnable, Long ticks) {
|
||||
return new VelocityTaskId(
|
||||
PROXY.getScheduler()
|
||||
.buildTask(this, runnable)
|
||||
.delay(ticks * 50, TimeUnit.MILLISECONDS).schedule()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runRepeatingSync(Runnable runnable, Long ticks) {
|
||||
return new VelocityTaskId(
|
||||
PROXY.getScheduler()
|
||||
.buildTask(this, runnable)
|
||||
.repeat(ticks * 50, TimeUnit.MILLISECONDS).schedule()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTask(TaskId taskId) {
|
||||
if (taskId instanceof VelocityTaskId) {
|
||||
((VelocityTaskId) taskId).getObject().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaCommandSender[] getOnlinePlayers() {
|
||||
return PROXY.getAllPlayers().stream()
|
||||
.map(VelocityCommandSender::new)
|
||||
.toArray(ViaCommandSender[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(UUID uuid, String message) {
|
||||
PROXY.getPlayer(uuid).ifPresent(it -> it.sendMessage(
|
||||
ComponentSerializers.JSON.deserialize(
|
||||
ComponentSerializer.toString(TextComponent.fromLegacyText(message)) // Fixes links
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean kickPlayer(UUID uuid, String message) {
|
||||
return PROXY.getPlayer(uuid).map(it -> {
|
||||
it.disconnect(
|
||||
ComponentSerializers.JSON.deserialize(
|
||||
ComponentSerializer.toString(TextComponent.fromLegacyText(message)) // ComponentSerializers.LEGACY is deprecated
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationProvider getConfigurationProvider() {
|
||||
return conf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getDump() {
|
||||
JsonObject extra = new JsonObject();
|
||||
List<PluginInfo> plugins = new ArrayList<>();
|
||||
for (PluginContainer p : PROXY.getPluginManager().getPlugins()) {
|
||||
plugins.add(new PluginInfo(
|
||||
true,
|
||||
p.getDescription().getName().orElse(p.getDescription().getId()),
|
||||
p.getDescription().getVersion().orElse("Unknown Version"),
|
||||
p.getInstance().isPresent() ? p.getInstance().get().getClass().getCanonicalName() : "Unknown",
|
||||
p.getDescription().getAuthors()
|
||||
));
|
||||
}
|
||||
extra.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
|
||||
extra.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getDetectedIds()));
|
||||
return extra;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldClientsAllowed() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package us.myles.ViaVersion.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.Command;
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
import us.myles.ViaVersion.velocity.command.subs.ProbeSubCmd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class VelocityCommandHandler extends ViaCommandHandler implements Command {
|
||||
public VelocityCommandHandler() {
|
||||
try {
|
||||
registerSubCommand(new ProbeSubCmd());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull CommandSource source, String[] args) {
|
||||
onCommand(new VelocityCommandSender(source), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> suggest(@NonNull CommandSource source, String[] currentArgs) {
|
||||
return onTabComplete(new VelocityCommandSender(source), currentArgs);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package us.myles.ViaVersion.velocity.command;
|
||||
|
||||
import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.kyori.text.serializer.ComponentSerializers;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class VelocityCommandSender implements ViaCommandSender {
|
||||
private CommandSource source;
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return source.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
source.sendMessage(
|
||||
ComponentSerializers.JSON.deserialize(
|
||||
ComponentSerializer.toString(TextComponent.fromLegacyText(msg)) // Fixes links
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
if (source instanceof Player) {
|
||||
return ((Player) source).getUniqueId();
|
||||
}
|
||||
return UUID.fromString(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (source instanceof Player) {
|
||||
return ((Player) source).getUsername();
|
||||
}
|
||||
return "?"; // :(
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package us.myles.ViaVersion.velocity.command.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.velocity.platform.VelocityViaConfig;
|
||||
import us.myles.ViaVersion.velocity.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 " +
|
||||
(((VelocityViaConfig) Via.getConfig()).getVelocityPingInterval() == -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,38 @@
|
||||
package us.myles.ViaVersion.velocity.handlers;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class VelocityChannelInitializer extends ChannelInitializer {
|
||||
@NonNull
|
||||
private ChannelInitializer original;
|
||||
private Method initChannel;
|
||||
|
||||
{
|
||||
try {
|
||||
initChannel = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
initChannel.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
initChannel.invoke(original, channel);
|
||||
|
||||
UserConnection user = new UserConnection(channel);
|
||||
new ProtocolPipeline(user);
|
||||
|
||||
// We need to add a separated handler because Velocity uses pipeline().get(MINECRAFT_DECODER)
|
||||
channel.pipeline().addBefore("minecraft-encoder", "via-encoder", new VelocityEncodeHandler(user));
|
||||
channel.pipeline().addBefore("minecraft-decoder", "via-decoder", new VelocityDecodeHandler(user));
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package us.myles.ViaVersion.velocity.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import lombok.AllArgsConstructor;
|
||||
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
|
||||
@AllArgsConstructor
|
||||
public class VelocityDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
private final UserConnection info;
|
||||
|
||||
@Override
|
||||
protected void decode(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;
|
||||
}
|
||||
info.getVelocityLock().readLock().lock();
|
||||
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();
|
||||
info.getVelocityLock().readLock().unlock();
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
bytebuf.retain();
|
||||
}
|
||||
info.getVelocityLock().readLock().unlock();
|
||||
|
||||
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,90 @@
|
||||
package us.myles.ViaVersion.velocity.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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
|
||||
@RequiredArgsConstructor
|
||||
public class VelocityEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
||||
@NonNull
|
||||
private final UserConnection info;
|
||||
private boolean handledCompression = false;
|
||||
|
||||
@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
|
||||
&& ctx.pipeline().names().indexOf("compression-encoder") > ctx.pipeline().names().indexOf("via-encoder")) {
|
||||
// Need to decompress this packet due to bad order
|
||||
bytebuf = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder) ctx.pipeline().get("compression-decoder"), ctx, bytebuf).get(0);
|
||||
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
|
||||
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
|
||||
ctx.pipeline().remove(encoder);
|
||||
ctx.pipeline().remove(decoder);
|
||||
ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder);
|
||||
ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder);
|
||||
needsCompress = true;
|
||||
handledCompression = true;
|
||||
} else {
|
||||
bytebuf.retain();
|
||||
}
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
|
||||
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf newPacket = bytebuf.alloc().buffer();
|
||||
try {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
|
||||
wrapper.writeToBuffer(newPacket);
|
||||
|
||||
bytebuf.clear();
|
||||
bytebuf.release();
|
||||
bytebuf = newPacket;
|
||||
} catch (Exception e) {
|
||||
bytebuf.clear();
|
||||
bytebuf.release();
|
||||
newPacket.release();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsCompress) {
|
||||
ByteBuf old = bytebuf;
|
||||
bytebuf = ctx.alloc().buffer();
|
||||
PipelineUtil.callEncode((MessageToByteEncoder) ctx.pipeline().get("compression-encoder"), ctx, old, bytebuf);
|
||||
old.release();
|
||||
}
|
||||
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,138 @@
|
||||
package us.myles.ViaVersion.velocity.handlers;
|
||||
|
||||
import com.velocitypowered.api.event.PostOrder;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||
import com.velocitypowered.api.event.player.ServerPreConnectEvent;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
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.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.velocity.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.velocity.storage.VelocityStorage;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class VelocityServerHandler {
|
||||
private static Method setProtocolVersion;
|
||||
private static Method setNextProtocolVersion;
|
||||
|
||||
static {
|
||||
try {
|
||||
setProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection").getDeclaredMethod("setProtocolVersion", int.class);
|
||||
setNextProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection").getDeclaredMethod("setNextProtocolVersion", int.class);
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void preServerConnect(ServerPreConnectEvent e) {
|
||||
try {
|
||||
UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId());
|
||||
if (user == null) return;
|
||||
if (!user.has(VelocityStorage.class)) {
|
||||
user.put(new VelocityStorage(user, e.getPlayer()));
|
||||
}
|
||||
|
||||
int protocolId = ProtocolDetectorService.getProtocolId(e.getOriginalServer().getServerInfo().getName());
|
||||
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId);
|
||||
|
||||
// Check if ViaVersion can support that version
|
||||
Object connection = ReflectionUtil.invoke(e.getPlayer(), "getConnection");
|
||||
setNextProtocolVersion.invoke(connection, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId);
|
||||
|
||||
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(order = PostOrder.LATE)
|
||||
public void connectedEvent(ServerConnectedEvent e) {
|
||||
UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId());
|
||||
try {
|
||||
checkServerChange(e, Via.getManager().getConnection(e.getPlayer().getUniqueId()));
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception {
|
||||
if (user == null) return;
|
||||
// Manually hide ViaVersion-created BossBars if the childserver was version 1.8.x (#666)
|
||||
if (user.has(EntityTracker.class)) {
|
||||
EntityTracker tracker = user.get(EntityTracker.class);
|
||||
|
||||
if (tracker.getBossBarMap() != null)
|
||||
for (BossBar bar : tracker.getBossBarMap().values())
|
||||
bar.hide();
|
||||
}
|
||||
// Handle server/version change
|
||||
if (user.has(VelocityStorage.class)) {
|
||||
// Wait all the scheduled packets be sent
|
||||
Semaphore semaphore = new Semaphore(1);
|
||||
semaphore.acquireUninterruptibly();
|
||||
user.getChannel().eventLoop().submit((Runnable) semaphore::release);
|
||||
semaphore.acquireUninterruptibly();
|
||||
semaphore.release();
|
||||
|
||||
user.getVelocityLock().writeLock().lock();
|
||||
|
||||
VelocityStorage storage = user.get(VelocityStorage.class);
|
||||
|
||||
if (e.getServer() != null) {
|
||||
if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) {
|
||||
String serverName = e.getServer().getServerInfo().getName();
|
||||
|
||||
storage.setCurrentServer(serverName);
|
||||
|
||||
int protocolId = ProtocolDetectorService.getProtocolId(serverName);
|
||||
|
||||
ProtocolInfo info = user.get(ProtocolInfo.class);
|
||||
|
||||
// Refresh the pipes
|
||||
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId);
|
||||
ProtocolPipeline pipeline = user.get(ProtocolInfo.class).getPipeline();
|
||||
user.clearStoredObjects();
|
||||
pipeline.cleanPipes();
|
||||
if (protocols == null) {
|
||||
// TODO Check Bungee Supported Protocols? *shrugs*
|
||||
protocolId = info.getProtocolVersion();
|
||||
} else {
|
||||
for (Pair<Integer, Protocol> prot : protocols) {
|
||||
pipeline.add(prot.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
info.setServerProtocolVersion(protocolId);
|
||||
// Add version-specific base Protocol
|
||||
pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId));
|
||||
|
||||
user.put(info);
|
||||
user.put(storage);
|
||||
|
||||
user.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(user);
|
||||
}
|
||||
|
||||
Object connection = ReflectionUtil.invoke(e.getPlayer(), "getConnection");
|
||||
int version = (int) ReflectionUtil.invoke(connection,"getNextProtocolVersion");
|
||||
setProtocolVersion.invoke(ReflectionUtil.invoke(e.getPlayer(), "getConnection"), version);
|
||||
}
|
||||
}
|
||||
user.getVelocityLock().writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package us.myles.ViaVersion.velocity.listeners;
|
||||
|
||||
import com.velocitypowered.api.event.PostOrder;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.Metadata;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.types.version.Types1_9;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
/*
|
||||
* This patches https://github.com/MylesIsCool/ViaVersion/issues/555
|
||||
*/
|
||||
public class ElytraPatch {
|
||||
|
||||
@Subscribe(order = PostOrder.LAST)
|
||||
public void onServerConnected(ServerConnectedEvent event) {
|
||||
UserConnection user = Via.getManager().getConnection(event.getPlayer().getUniqueId());
|
||||
if (user == null) return;
|
||||
|
||||
try {
|
||||
if (user.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
|
||||
int entityId = user.get(EntityTracker.class).getProvidedEntityId();
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapper(0x39, null, user);
|
||||
|
||||
wrapper.write(Type.VAR_INT, entityId);
|
||||
wrapper.write(Types1_9.METADATA_LIST, Collections.singletonList(new Metadata(0, MetaType1_9.Byte, (byte) 0)));
|
||||
|
||||
wrapper.send(Protocol1_9TO1_8.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package us.myles.ViaVersion.velocity.listeners;
|
||||
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||
import com.velocitypowered.api.proxy.player.PlayerSettings;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/*
|
||||
This solves the wrong mainhand issue when you join with BungeeCord on a 1.8 server, and switch to a 1.9 or higher.
|
||||
*/
|
||||
public class MainHandPatch {
|
||||
private static Method setSettings;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class clientSettings = Class.forName("com.velocitypowered.proxy.protocol.packet.ClientSettings");
|
||||
setSettings = Class.forName("com.velocitypowered.proxy.connection.client.ConnectedPlayer").getDeclaredMethod("setPlayerSettings", clientSettings);
|
||||
setSettings.setAccessible(true);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onServerConnect(ServerConnectedEvent event) {
|
||||
UserConnection user = Via.getManager().getConnection(event.getPlayer().getUniqueId());
|
||||
if (user == null || setSettings == null) return;
|
||||
|
||||
try {
|
||||
if (user.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
|
||||
PlayerSettings settings = event.getPlayer().getPlayerSettings();
|
||||
if (user.has(EntityTracker.class)) {
|
||||
Object clientSettings = ReflectionUtil.get(settings, "settings", Object.class);
|
||||
ReflectionUtil.set(clientSettings, "mainHand", user.get(EntityTracker.class).getMainHand());
|
||||
setSettings.invoke(event.getPlayer(), clientSettings);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package us.myles.ViaVersion.velocity.listeners;
|
||||
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.PostLoginEvent;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.update.UpdateUtil;
|
||||
|
||||
public class UpdateListener {
|
||||
@Subscribe
|
||||
public void onJoin(PostLoginEvent e) {
|
||||
if (e.getPlayer().hasPermission("viaversion.update")
|
||||
&& Via.getConfig().isCheckForUpdates()) {
|
||||
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
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 VelocityBossBar extends CommonBoss<Player> {
|
||||
public VelocityBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
super(title, health, color, style);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.api.platform.TaskId;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class VelocityTaskId implements TaskId {
|
||||
private ScheduledTask object;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.NonNull;
|
||||
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 VelocityViaAPI implements ViaAPI<Player> {
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull Player 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(Player player, ByteBuf packet) throws IllegalArgumentException {
|
||||
sendRawPacket(player.getUniqueId(), packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
|
||||
return new VelocityBossBar(title, 1F, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
return new VelocityBossBar(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,280 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.util.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
public class VelocityViaConfig extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch", "quick-move-action-fix", "bungee-ping-interval", "bungee-ping-save", "bungee-servers");
|
||||
|
||||
public VelocityViaConfig(File configFile) {
|
||||
super(new File(configFile, "config.yml"));
|
||||
// Load config
|
||||
reloadConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getDefaultConfigURL() {
|
||||
return getClass().getClassLoader().getResource("assets/viaversion/config.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleConfig(Map<String, Object> config) {
|
||||
// Parse servers
|
||||
Map<String, Object> servers;
|
||||
if (!(config.get("velocity-servers") instanceof Map)) {
|
||||
servers = new HashMap<>();
|
||||
} else {
|
||||
servers = (Map) config.get("velocity-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")) {
|
||||
// Side note: This doesn't use ProtocolRegistry as it doesn't know the protocol version at boot.
|
||||
try {
|
||||
servers.put("default", VelocityViaInjector.getLowestSupportedProtocolVersion());
|
||||
} catch (Exception e) {
|
||||
// Something went very wrong
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// Put back
|
||||
config.put("velocity-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 isPistonAnimationPatch() {
|
||||
return getBoolean("piston-animation-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 boolean is1_12NBTArrayFix() {
|
||||
return getBoolean("chat-nbt-fix", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is1_12QuickMoveActionFix() {
|
||||
return 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
|
||||
public boolean isMinimizeCooldown() {
|
||||
return getBoolean("minimize-cooldown", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the interval for checking servers via ping
|
||||
* -1 for disabled
|
||||
*
|
||||
* @return Ping interval in seconds
|
||||
*/
|
||||
public int getVelocityPingInterval() {
|
||||
return getInt("velocity-ping-interval", 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the velocity ping be saved to the config on change.
|
||||
*
|
||||
* @return True if it should save
|
||||
*/
|
||||
public boolean isVelocityPingSave() {
|
||||
return getBoolean("velocity-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> getVelocityServerProtocols() {
|
||||
return get("velocity-servers", Map.class, new HashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is1_13TeamColourFix() {
|
||||
return getBoolean("team-colour-fix", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppress1_13ConversionErrors() {
|
||||
return getBoolean("suppress-1_13-conversion-errors", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisable1_13AutoComplete() {
|
||||
return getBoolean("disable-1_13-auto-complete", false);
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import us.myles.ViaVersion.VelocityPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.velocity.handlers.VelocityChannelInitializer;
|
||||
|
||||
|
||||
public class VelocityViaInjector implements ViaInjector {
|
||||
@Override
|
||||
public void inject() throws Exception {
|
||||
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
|
||||
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer");
|
||||
ChannelInitializer originalIntializer = (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get");
|
||||
channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class)
|
||||
.invoke(channelInitializerHolder, new VelocityChannelInitializer(originalIntializer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninject() {
|
||||
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Velocity without a reboot!");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getServerProtocolVersion() throws Exception {
|
||||
return getLowestSupportedProtocolVersion();
|
||||
}
|
||||
|
||||
public static int getLowestSupportedProtocolVersion() throws Exception {
|
||||
return ReflectionUtil.getStatic(Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants"), "MINIMUM_GENERIC_VERSION", int.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoderName() {
|
||||
return "via-encoder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDecoderName() {
|
||||
return "via-decoder";
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package us.myles.ViaVersion.velocity.platform;
|
||||
|
||||
import com.velocitypowered.api.plugin.PluginContainer;
|
||||
import us.myles.ViaVersion.VelocityPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
|
||||
import us.myles.ViaVersion.protocols.base.VersionProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BossBarProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
import us.myles.ViaVersion.velocity.handlers.VelocityServerHandler;
|
||||
import us.myles.ViaVersion.velocity.listeners.ElytraPatch;
|
||||
import us.myles.ViaVersion.velocity.listeners.MainHandPatch;
|
||||
import us.myles.ViaVersion.velocity.listeners.UpdateListener;
|
||||
import us.myles.ViaVersion.velocity.providers.VelocityBossBarProvider;
|
||||
import us.myles.ViaVersion.velocity.providers.VelocityMovementTransmitter;
|
||||
import us.myles.ViaVersion.velocity.providers.VelocityVersionProvider;
|
||||
import us.myles.ViaVersion.velocity.service.ProtocolDetectorService;
|
||||
|
||||
public class VelocityViaLoader implements ViaPlatformLoader {
|
||||
@Override
|
||||
public void load() {
|
||||
Object plugin = VelocityPlugin.PROXY.getPluginManager()
|
||||
.getPlugin("viaversion").flatMap(PluginContainer::getInstance).get();
|
||||
|
||||
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter());
|
||||
Via.getManager().getProviders().use(BossBarProvider.class, new VelocityBossBarProvider());
|
||||
Via.getManager().getProviders().use(VersionProvider.class, new VelocityVersionProvider());
|
||||
// We probably don't need a EntityIdProvider because velocity sends a Join packet on server change
|
||||
|
||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new UpdateListener());
|
||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new VelocityServerHandler());
|
||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new MainHandPatch());
|
||||
VelocityPlugin.PROXY.getEventManager().register(plugin, new ElytraPatch());
|
||||
|
||||
int pingInterval = ((VelocityViaConfig) Via.getPlatform().getConf()).getVelocityPingInterval();
|
||||
if (pingInterval > 0) {
|
||||
Via.getPlatform().runRepeatingSync(
|
||||
new ProtocolDetectorService(),
|
||||
pingInterval * 20L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
// Probably not useful, there's no ProxyReloadEvent
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package us.myles.ViaVersion.velocity.providers;
|
||||
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BossBarProvider;
|
||||
import us.myles.ViaVersion.velocity.storage.VelocityStorage;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class VelocityBossBarProvider extends BossBarProvider {
|
||||
@Override
|
||||
public void handleAdd(UserConnection user, UUID barUUID) {
|
||||
if (user.has(VelocityStorage.class)) {
|
||||
VelocityStorage storage = user.get(VelocityStorage.class);
|
||||
// Check if bossbars are supported by bungee, static maybe
|
||||
if (storage.getBossbar() != null) {
|
||||
storage.getBossbar().add(barUUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRemove(UserConnection user, UUID barUUID) {
|
||||
if (user.has(VelocityStorage.class)) {
|
||||
VelocityStorage storage = user.get(VelocityStorage.class);
|
||||
if (storage.getBossbar() != null) {
|
||||
storage.getBossbar().remove(barUUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package us.myles.ViaVersion.velocity.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.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
|
||||
public class VelocityMovementTransmitter 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(Protocol1_9TO1_8.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// PlayerPackets will increment idle
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package us.myles.ViaVersion.velocity.providers;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.base.VersionProvider;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class VelocityVersionProvider extends VersionProvider {
|
||||
private static Class<?> ref ;
|
||||
|
||||
static {
|
||||
try {
|
||||
ref = Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants");
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("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)
|
||||
Object list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSIONS", Object.class);
|
||||
List<Integer> sorted = new ArrayList<Integer>((List) ReflectionUtil.invoke(list, "asList"));
|
||||
Collections.sort(sorted);
|
||||
|
||||
ProtocolInfo info = user.get(ProtocolInfo.class);
|
||||
|
||||
// Bungee supports it
|
||||
if (sorted.contains(info.getProtocolVersion()))
|
||||
return info.getProtocolVersion();
|
||||
|
||||
// Older than bungee supports, get the lowest version
|
||||
if (info.getProtocolVersion() < sorted.get(0)) {
|
||||
return getLowestSupportedVersion();
|
||||
}
|
||||
|
||||
// Loop through all protocols to get the closest protocol id that bungee supports (and that viaversion does too)
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
// This is more of a workaround for snapshot support by bungee.
|
||||
for (Integer protocol : Lists.reverse(sorted)) {
|
||||
if (info.getProtocolVersion() > protocol && ProtocolVersion.isRegistered(protocol))
|
||||
return protocol;
|
||||
}
|
||||
|
||||
Via.getPlatform().getLogger().severe("Panic, no protocol id found for " + info.getProtocolVersion());
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
public static int getLowestSupportedVersion() {
|
||||
List<Integer> list;
|
||||
try {
|
||||
return ReflectionUtil.getStatic(
|
||||
Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants"),
|
||||
"MINIMUM_GENERIC_VERSION",
|
||||
int.class);
|
||||
} catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Fallback
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package us.myles.ViaVersion.velocity.service;
|
||||
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.VelocityPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.velocity.platform.VelocityViaConfig;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ProtocolDetectorService implements Runnable {
|
||||
private static final Map<String, Integer> detectedProtocolIds = new ConcurrentHashMap<>();
|
||||
@Getter
|
||||
private static ProtocolDetectorService instance;
|
||||
|
||||
public ProtocolDetectorService() {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static Integer getProtocolId(String serverName) {
|
||||
// Step 1. Check Config
|
||||
Map<String, Integer> servers = ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols();
|
||||
Integer protocol = servers.get(serverName);
|
||||
if (protocol != null) {
|
||||
return protocol;
|
||||
}
|
||||
// Step 2. Check Detected
|
||||
Integer detectedProtocol = detectedProtocolIds.get(serverName);
|
||||
if (detectedProtocol != null) {
|
||||
return detectedProtocol;
|
||||
}
|
||||
// Step 3. Use Default
|
||||
Integer defaultProtocol = servers.get("default");
|
||||
if (defaultProtocol != null) {
|
||||
return defaultProtocol;
|
||||
}
|
||||
// Step 4: Use bungee lowest supported... *cries*
|
||||
try {
|
||||
return Via.getManager().getInjector().getServerProtocolVersion();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return ProtocolVersion.v1_8.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (final RegisteredServer serv : VelocityPlugin.PROXY.getAllServers()) {
|
||||
probeServer(serv);
|
||||
}
|
||||
}
|
||||
|
||||
public static void probeServer(final RegisteredServer serverInfo) {
|
||||
final String key = serverInfo.getServerInfo().getName();
|
||||
serverInfo.ping().thenAccept((serverPing) -> {
|
||||
if (serverPing != null && serverPing.getVersion() != null) {
|
||||
detectedProtocolIds.put(key, serverPing.getVersion().getProtocol());
|
||||
if (((VelocityViaConfig) Via.getConfig()).isVelocityPingSave()) {
|
||||
Map<String, Integer> servers = ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols();
|
||||
Integer protocol = servers.get(key);
|
||||
if (protocol != null && protocol == serverPing.getVersion().getProtocol()) {
|
||||
return;
|
||||
}
|
||||
// Ensure we're the only ones writing to the config
|
||||
synchronized (Via.getPlatform().getConfigurationProvider()) {
|
||||
servers.put(key, serverPing.getVersion().getProtocol());
|
||||
}
|
||||
// Save
|
||||
Via.getPlatform().getConfigurationProvider().saveConfig();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Map<String, Integer> getDetectedIds() {
|
||||
return new HashMap<>(detectedProtocolIds);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package us.myles.ViaVersion.velocity.storage;
|
||||
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import us.myles.ViaVersion.api.data.StoredObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class VelocityStorage extends StoredObject {
|
||||
private Player player;
|
||||
private String currentServer;
|
||||
private Set<UUID> bossbar;
|
||||
|
||||
public VelocityStorage(UserConnection user, Player player) {
|
||||
super(user);
|
||||
this.player = player;
|
||||
this.currentServer = "";
|
||||
|
||||
// Get bossbar list if it's supported
|
||||
try {
|
||||
Object connection = ReflectionUtil.invoke(player, "getConnection");
|
||||
Object sessionHandler = ReflectionUtil.invoke(connection, "getSessionHandler");
|
||||
if (sessionHandler.getClass().getSimpleName().contains("Play")) {
|
||||
bossbar = (Set<UUID>) ReflectionUtil.invoke(sessionHandler, "getServerBossBars");
|
||||
// TODO make this work
|
||||
}
|
||||
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package us.myles.ViaVersion.velocity.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
public class LoggerWrapper extends java.util.logging.Logger {
|
||||
private final Logger base;
|
||||
|
||||
public LoggerWrapper(Logger logger) {
|
||||
super("logger", null);
|
||||
this.base = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(LogRecord record) {
|
||||
log(record.getLevel(), record.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg) {
|
||||
if (level == Level.FINE)
|
||||
base.debug(msg);
|
||||
else if (level == Level.WARNING)
|
||||
base.warn(msg);
|
||||
else if (level == Level.SEVERE)
|
||||
base.error(msg);
|
||||
else if (level == Level.INFO)
|
||||
base.info(msg);
|
||||
else
|
||||
base.trace(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Object param1) {
|
||||
if (level == Level.FINE)
|
||||
base.debug(msg, param1);
|
||||
else if (level == Level.WARNING)
|
||||
base.warn(msg, param1);
|
||||
else if (level == Level.SEVERE)
|
||||
base.error(msg, param1);
|
||||
else if (level == Level.INFO)
|
||||
base.info(msg, param1);
|
||||
else
|
||||
base.trace(msg, param1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Object[] params) {
|
||||
log(level, MessageFormat.format(msg, params)); // workaround not formatting correctly
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Throwable params) {
|
||||
if (level == Level.FINE)
|
||||
base.debug(msg, params);
|
||||
else if (level == Level.WARNING)
|
||||
base.warn(msg, params);
|
||||
else if (level == Level.SEVERE)
|
||||
base.error(msg, params);
|
||||
else if (level == Level.INFO)
|
||||
base.info(msg, params);
|
||||
else
|
||||
base.trace(msg, params);
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren