3
0
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:
Myles 2018-11-17 13:15:20 +00:00
Commit 73dccbaf24
44 geänderte Dateien mit 1722 neuen und 39 gelöschten Zeilen

Datei anzeigen

@ -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>

Datei anzeigen

@ -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);

Datei anzeigen

@ -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

Datei anzeigen

@ -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>

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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)");
}

Datei anzeigen

@ -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

Datei anzeigen

@ -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;

Datei anzeigen

@ -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>

Datei anzeigen

@ -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);

Datei anzeigen

@ -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());

Datei anzeigen

@ -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
*

Datei anzeigen

@ -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 #
#----------------------------------------------------------#
#

Datei anzeigen

@ -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>

Datei anzeigen

@ -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>

Datei anzeigen

@ -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>

Datei anzeigen

@ -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>

Datei anzeigen

@ -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!");

Datei anzeigen

@ -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
Datei anzeigen

@ -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>

Datei anzeigen

@ -0,0 +1,5 @@
package us.myles.ViaVersion.velocity;
public class VersionInfo {
public static final String VERSION = "${project.version}";
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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 "?"; // :(
}
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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));
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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();
}
}
}

Datei anzeigen

@ -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();
}
}
}

Datei anzeigen

@ -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();
}
}
}

Datei anzeigen

@ -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());
}
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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;
}

Datei anzeigen

@ -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();
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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";
}
}

Datei anzeigen

@ -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
}
}

Datei anzeigen

@ -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);
}
}
}
}

Datei anzeigen

@ -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
}
}
}

Datei anzeigen

@ -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;
}
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -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();
}
}
}

Datei anzeigen

@ -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);
}
}