Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f256309487 | ||
|
|
462abb1ef9 | ||
|
|
a35408d14f | ||
|
|
81d4deaea7 | ||
|
|
9103f89aff | ||
|
|
8e4c2648a3 | ||
|
|
ad020ec329 | ||
|
|
df3be302af | ||
|
|
8e3b8cb572 | ||
|
|
ff1554556e | ||
|
|
b15c93c416 | ||
|
|
071b42c9e0 | ||
|
|
304f9b34fd | ||
|
|
c817a0e9cb | ||
|
|
744252d492 | ||
|
|
9186361a29 | ||
|
|
bf01c9ea0e | ||
|
|
bee260e2b4 | ||
|
|
21811991f1 | ||
|
|
a2809f8d5c | ||
|
|
95f2b597da | ||
|
|
fa348fbc23 | ||
|
|
d277701caa | ||
|
|
9b7f68a888 | ||
|
|
7e837ef9db | ||
|
|
eb78fe4bfc | ||
|
|
689f0fd5db | ||
|
|
32316cf3ab | ||
|
|
d450c9b4d6 | ||
|
|
622673d1d3 | ||
|
|
1209beb47d | ||
|
|
f4eeb94a2e | ||
|
|
fac7eab59e | ||
|
|
e430bfce06 | ||
|
|
dd55cc3cf2 | ||
|
|
9937a173d1 | ||
|
|
1c584040ca | ||
|
|
10a2df5a7d | ||
|
|
1bec3cf1d0 | ||
|
|
4142797380 | ||
|
|
68fc884d2a | ||
|
|
2872bdd1c3 | ||
|
|
7d29a0c0af | ||
|
|
dd6423de06 | ||
|
|
52bbf1affe | ||
|
|
cfaded6cf8 | ||
|
|
69e444f83d | ||
|
|
c896ed5f63 | ||
|
|
9f8456a336 | ||
|
|
bd11c98e45 | ||
|
|
55fccba711 | ||
|
|
783542401b | ||
|
|
2424057536 | ||
|
|
b6dbe82d16 | ||
|
|
f92b7e5b80 | ||
|
|
8093c424e2 | ||
|
|
839d46f5ed | ||
|
|
de0b9a2a68 | ||
|
|
c3bd45cd58 | ||
|
|
c4bab6c9af | ||
|
|
f33d22531b | ||
|
|
9ccbdb69c5 | ||
|
|
e9008923eb | ||
|
|
301e84d698 | ||
|
|
5aad3306eb | ||
|
|
d30bbcd4a3 | ||
|
|
003197b476 | ||
|
|
a3e15bce4d | ||
|
|
e43026231e | ||
|
|
f100f6e3f0 | ||
|
|
8ae2842e5f | ||
|
|
54be03bf77 | ||
|
|
27fc4dd684 | ||
|
|
2a1f0f812b | ||
|
|
64cde13ea7 | ||
|
|
7d23b12f85 | ||
|
|
4b3f757881 | ||
|
|
d0e7f05d50 | ||
|
|
21c957b8d5 | ||
|
|
3fe25f68b1 | ||
|
|
3354a46283 | ||
|
|
975743c76f | ||
|
|
d3b214965b | ||
|
|
eb8065ad20 | ||
|
|
7d3548956e | ||
|
|
3de961f641 | ||
|
|
59620f7f93 | ||
|
|
ba3aa4566e | ||
|
|
8445a6d9db | ||
|
|
f53c8c67e2 | ||
|
|
b4976bd302 | ||
|
|
ec848d7201 | ||
|
|
8c03a296c2 | ||
|
|
65a6e25f1b | ||
|
|
178b625ca0 | ||
|
|
152993f749 | ||
|
|
ca246f9d95 | ||
|
|
f1d53bb7ac | ||
|
|
30950a7d74 | ||
|
|
305f6b7ce2 | ||
|
|
313b794285 | ||
|
|
7031d431da | ||
|
|
655e14b36e | ||
|
|
f881f3d484 | ||
|
|
4d3302a926 | ||
|
|
b2df970af5 | ||
|
|
b7b322a525 | ||
|
|
771c00b146 | ||
|
|
23f1589c28 | ||
|
|
eb72db9a5f | ||
|
|
10fc8f846d | ||
|
|
31c9332e56 | ||
|
|
b0d64bfebd | ||
|
|
ffbd399993 | ||
|
|
aeec7e5f95 | ||
|
|
36301a595b | ||
|
|
a864bf7c18 | ||
|
|
0454169588 | ||
|
|
8ea3623a79 | ||
|
|
866e494d3c | ||
|
|
d5108061c1 | ||
|
|
396998c7fc | ||
|
|
ff3d76a387 | ||
|
|
51c469882b | ||
|
|
8b9a1750de | ||
|
|
3411c3d144 | ||
|
|
cdab5b3f5b | ||
|
|
42edffb309 | ||
|
|
42efc736c3 | ||
|
|
30bb91fc8a | ||
|
|
14daca5fea | ||
|
|
8396c5a3e3 | ||
|
|
e136d1db94 | ||
|
|
90dabce0d2 | ||
|
|
9a8a6e5b16 | ||
|
|
4840db095c | ||
|
|
b371c14a27 | ||
|
|
a1fbca11f0 | ||
|
|
0fe9ccf4a8 | ||
|
|
08713947b7 | ||
|
|
e56bce2f31 | ||
|
|
573374866b | ||
|
|
32afa2a9a3 | ||
|
|
669cbcd142 | ||
|
|
471076cbe1 | ||
|
|
79d353d458 | ||
|
|
30d477c6d2 | ||
|
|
d3f5ebdba7 | ||
|
|
4b94c8ad02 | ||
|
|
7a7c3f15d8 | ||
|
|
52610f7c66 | ||
|
|
84ee4410a6 | ||
|
|
49d51de263 | ||
|
|
848b0cf113 | ||
|
|
c4ffdc1b7c | ||
|
|
49b602994a | ||
|
|
05930ad791 | ||
|
|
e7ab232b28 | ||
|
|
3f88a16c6c | ||
|
|
1a6b98deca | ||
|
|
598863d43a | ||
|
|
b146257b1a | ||
|
|
dc01fb59b8 | ||
|
|
58ed2c0d9e | ||
|
|
3762a9d3b1 | ||
|
|
5a88963929 | ||
|
|
1b69243326 | ||
|
|
3e2a391348 | ||
|
|
a330d2b148 | ||
|
|
573f769825 | ||
|
|
9de49176fb | ||
|
|
e6220f39e5 | ||
|
|
8f656d9dac | ||
|
|
15bcf3f065 | ||
|
|
536e2e33e0 | ||
|
|
ae58f0c1ab | ||
|
|
7d9cd5bfbf | ||
|
|
25a7915c7f | ||
|
|
822d582074 | ||
|
|
d815c0e682 | ||
|
|
f8a73d5fc2 | ||
|
|
a0ad97947d | ||
|
|
6ea5d0849d | ||
|
|
eba512ef0b | ||
|
|
725ab0f713 | ||
|
|
0f96c24c78 | ||
|
|
f2e4c37cd9 | ||
|
|
f159a2250c | ||
|
|
ed311e4059 | ||
|
|
6aae98a8a9 | ||
|
|
99f9cf3340 | ||
|
|
2074039285 | ||
|
|
b438ff61a2 | ||
|
|
c36e43b573 | ||
|
|
be383a524c | ||
|
|
9c6cd22817 | ||
|
|
85de7c35ea | ||
|
|
0dd8c33aa9 | ||
|
|
8cc2538e6c | ||
|
|
04d87ebba7 | ||
|
|
8c4b5b613c | ||
|
|
6add512fe1 | ||
|
|
73b8a2fc9a | ||
|
|
03cc48c991 | ||
|
|
44544925a1 | ||
|
|
7cadf832f5 | ||
|
|
0f3daa5dc4 | ||
|
|
f258cf8c89 | ||
|
|
ca759c056e | ||
|
|
d715607826 | ||
|
|
afca92d122 | ||
|
|
ae37b34692 | ||
|
|
9e42a368e0 | ||
|
|
27982efd29 | ||
|
|
c3b343fbc8 | ||
|
|
9bedb6c741 | ||
|
|
873f4dd298 | ||
|
|
693990644f | ||
|
|
b2680d76a6 | ||
|
|
db935b454f | ||
|
|
c207a9bfff | ||
|
|
f5bd041c7b | ||
|
|
07d89b24af | ||
|
|
1d0c0c527c | ||
|
|
7a9cb86563 | ||
|
|
87b1919863 | ||
|
|
d164e413c2 |
No files matched your search
@@ -19,9 +19,6 @@ hs_err_pid*
|
||||
# Ignore IDEA directory
|
||||
.idea/*
|
||||
|
||||
# Include the project's code style settings file
|
||||
!.idea/codeStyleSettings.xml
|
||||
|
||||
# Include the project's dictionary
|
||||
!.idea/dictionaries/
|
||||
!.idea/dictionaries/*
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
sudo: false
|
||||
|
||||
language: java
|
||||
jdk: oraclejdk7
|
||||
jdk: oraclejdk8
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
||||
+3
-4
@@ -1,12 +1,11 @@
|
||||
### What version of ViaVersion are you using? Type /ver viaversion
|
||||
### What is the output link of /viaversion dump?
|
||||
|
||||
### What version of Spigot are you using? Type /ver
|
||||
|
||||
### What plugins are you using? Type /plugins
|
||||
|
||||
### Are you using any additional software like BungeeCord? If so, what software and version? (Please list your plugins as well)
|
||||
|
||||
|
||||
### How does this error happen? login? Using an item?
|
||||
|
||||
|
||||
### Is there an error in the console? Use pastebin.com. Is there a kick message?
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
# ViaVersion 0.9.6
|
||||
# ViaVersion 1.0.0 - Spigot, Sponge, BungeeCord
|
||||
[](https://travis-ci.org/MylesIsCool/ViaVersion)
|
||||
[](https://gitter.im/MylesIsCool/ViaVersion)
|
||||
|
||||
IRC: [#viaversion](http://irc.spi.gt/iris/?channels=viaversion) on irc.spi.gt for Support.
|
||||
|
||||
**Allows the connection of higher client versions to lower server versions**
|
||||
|
||||
Allows 1.10, 1.9 on 1.8 server and 1.10 on a 1.9 server.
|
||||
Supported Versions:
|
||||
|
||||
[![Table] (http://i.imgur.com/SVVhFQ4.png)](http://i.imgur.com/SVVhFQ4.png)
|
||||
|
||||
On Bukkit you may also use ProtocolSupport, but ensure you have the right build for your server version.
|
||||
|
||||
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
|
||||
|
||||
@@ -14,40 +20,14 @@ Allows 1.10, 1.9 on 1.8 server and 1.10 on a 1.9 server.
|
||||
|
||||
Sources:
|
||||
--------
|
||||
**wiki.vg** (Used for various information, we also contribute back)
|
||||
|
||||
**wiki.vg** (Protocol info, though I did have to find a lot myself)
|
||||
|
||||
**Burger** We use this tool to get protocol and other useful information for new / undocumented Minecraft versions
|
||||
**Burger** (See [PAaaS](https://github.com/Matsv/Paaas))
|
||||
|
||||
**OpenNBT** (used for slot rewriting)
|
||||
|
||||
|
||||
|
||||
All Time Contributors:
|
||||
--------
|
||||
|
||||
**Myself** (harhar)
|
||||
|
||||
**Matsv**
|
||||
|
||||
**HugoDaBosss**
|
||||
|
||||
**SanderGielisse**
|
||||
|
||||
**Paulomart**
|
||||
|
||||
**gigosaurus**
|
||||
|
||||
**fillefilip8**
|
||||
|
||||
**lenis0012**
|
||||
|
||||
**fuzzy_bot**
|
||||
|
||||
**joserobjr**
|
||||
|
||||
|
||||
|
||||
Releases / Dev Builds:
|
||||
--------
|
||||
You can find official releases here:
|
||||
@@ -70,5 +50,5 @@ License:
|
||||
|
||||
MIT License, see LICENSE for more details.
|
||||
|
||||
Thanks!
|
||||
|
||||
Special thanks to all our [Contributors](https://github.com/MylesIsCool/ViaVersion/graphs/contributors)
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>viaversion-bukkit</artifactId>
|
||||
|
||||
<properties>
|
||||
<!-- Change Bukkit Version HERE! -->
|
||||
<bukkitVersion>1.8.8-R0.1-SNAPSHOT</bukkitVersion>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>.</targetPath>
|
||||
<filtering>true</filtering>
|
||||
<directory>src/main/resources/</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Common Module -->
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Bukkit API, http://www.spigotmc.org/ or http://bukkit.org/ -->
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>${bukkitVersion}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>junit</artifactId>
|
||||
<groupId>junit</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<groupId>javax.persistence</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,256 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaAPI;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
|
||||
import us.myles.ViaVersion.api.platform.TaskId;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatform;
|
||||
import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.bukkit.commands.BukkitCommandHandler;
|
||||
import us.myles.ViaVersion.bukkit.commands.BukkitCommandSender;
|
||||
import us.myles.ViaVersion.bukkit.platform.*;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
import us.myles.ViaVersion.dump.PluginInfo;
|
||||
import us.myles.ViaVersion.util.GsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform {
|
||||
|
||||
private BukkitCommandHandler commandHandler;
|
||||
private boolean compatSpigotBuild = false;
|
||||
private boolean spigot = true;
|
||||
private boolean lateBind = false;
|
||||
private boolean protocolSupport = false;
|
||||
@Getter
|
||||
private BukkitConfigAPI conf;
|
||||
@Getter
|
||||
private ViaAPI<Player> api = new BukkitViaAPI(this);
|
||||
private List<Runnable> queuedTasks = new ArrayList<>();
|
||||
private List<Runnable> asyncQueuedTasks = new ArrayList<>();
|
||||
|
||||
public ViaVersionPlugin() {
|
||||
// Command handler
|
||||
commandHandler = new BukkitCommandHandler();
|
||||
// Init platform
|
||||
Via.init(ViaManager.builder()
|
||||
.platform(this)
|
||||
.commandHandler(commandHandler)
|
||||
.injector(new BukkitViaInjector())
|
||||
.loader(new BukkitViaLoader(this))
|
||||
.build());
|
||||
// Config magic
|
||||
conf = new BukkitConfigAPI();
|
||||
// For compatibility
|
||||
ViaVersion.setInstance(this);
|
||||
|
||||
// Check if we're using protocol support too
|
||||
protocolSupport = Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null;
|
||||
|
||||
if (protocolSupport) {
|
||||
getLogger().info("Hooking into ProtocolSupport, to prevent issues!");
|
||||
try {
|
||||
BukkitViaInjector.patchLists();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Spigot detector
|
||||
try {
|
||||
Class.forName("org.spigotmc.SpigotConfig");
|
||||
} catch (ClassNotFoundException e) {
|
||||
spigot = false;
|
||||
}
|
||||
|
||||
// Check if it's a spigot build with a protocol mod
|
||||
try {
|
||||
compatSpigotBuild = NMSUtil.nms("PacketEncoder").getDeclaredField("version") != null;
|
||||
} catch (Exception e) {
|
||||
compatSpigotBuild = false;
|
||||
}
|
||||
|
||||
// Generate classes needed (only works if it's compat or ps)
|
||||
ClassGenerator.generate();
|
||||
lateBind = !BukkitViaInjector.isBinded();
|
||||
|
||||
getLogger().info("ViaVersion " + getDescription().getVersion() + (compatSpigotBuild ? "compat" : "") + " is now loaded" + (lateBind ? ", waiting for boot. (late-bind)" : ", injecting!"));
|
||||
if (!lateBind) {
|
||||
Via.getManager().init();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (lateBind) {
|
||||
Via.getManager().init();
|
||||
}
|
||||
|
||||
getCommand("viaversion").setExecutor(commandHandler);
|
||||
getCommand("viaversion").setTabCompleter(commandHandler);
|
||||
|
||||
// Warn them if they have anti-xray on and they aren't using spigot
|
||||
if (conf.isAntiXRay() && !spigot) {
|
||||
getLogger().info("You have anti-xray on in your config, since you're not using spigot it won't fix xray!");
|
||||
}
|
||||
|
||||
// Run queued tasks
|
||||
for (Runnable r : queuedTasks) {
|
||||
Bukkit.getScheduler().runTask(this, r);
|
||||
}
|
||||
queuedTasks.clear();
|
||||
|
||||
// Run async queued tasks
|
||||
for (Runnable r : asyncQueuedTasks) {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this, r);
|
||||
}
|
||||
asyncQueuedTasks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
Via.getManager().destroy();
|
||||
}
|
||||
|
||||
public boolean isCompatSpigotBuild() {
|
||||
return compatSpigotBuild;
|
||||
}
|
||||
|
||||
|
||||
public boolean isSpigot() {
|
||||
return this.spigot;
|
||||
}
|
||||
|
||||
public boolean isProtocolSupport() {
|
||||
return protocolSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
return Bukkit.getServer().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return Bukkit.getServer().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runAsync(Runnable runnable) {
|
||||
if (isPluginEnabled()) {
|
||||
return new BukkitTaskId(getServer().getScheduler().runTaskAsynchronously(this, runnable).getTaskId());
|
||||
} else {
|
||||
asyncQueuedTasks.add(runnable);
|
||||
return new BukkitTaskId(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runSync(Runnable runnable) {
|
||||
if (isPluginEnabled()) {
|
||||
return new BukkitTaskId(getServer().getScheduler().runTask(this, runnable).getTaskId());
|
||||
} else {
|
||||
queuedTasks.add(runnable);
|
||||
return new BukkitTaskId(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runRepeatingSync(Runnable runnable, Long ticks) {
|
||||
return new BukkitTaskId(getServer().getScheduler().runTaskTimer(this, runnable, ticks, 0).getTaskId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTask(TaskId taskId) {
|
||||
if (taskId == null) return;
|
||||
if (taskId.getObject() == null) return;
|
||||
if (taskId instanceof BukkitTaskId) {
|
||||
getServer().getScheduler().cancelTask((Integer) taskId.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaCommandSender[] getOnlinePlayers() {
|
||||
ViaCommandSender[] array = new ViaCommandSender[Bukkit.getOnlinePlayers().size()];
|
||||
int i = 0;
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
array[i++] = new BukkitCommandSender(player);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(UUID uuid, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
player.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean kickPlayer(UUID uuid, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null) {
|
||||
player.kickPlayer(message);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEnabled() {
|
||||
return Bukkit.getPluginManager().getPlugin("ViaVersion").isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationProvider getConfigurationProvider() {
|
||||
return conf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
if (Bukkit.getPluginManager().getPlugin("ProtocolLib") != null) {
|
||||
getLogger().severe("ViaVersion is already loaded, we're going to kick all the players... because otherwise we'll crash because of ProtocolLib.");
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', getConf().getReloadDisconnectMsg()));
|
||||
}
|
||||
|
||||
} else {
|
||||
getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getDump() {
|
||||
JsonObject platformSpecific = new JsonObject();
|
||||
|
||||
List<PluginInfo> plugins = new ArrayList<>();
|
||||
for (Plugin p : Bukkit.getPluginManager().getPlugins())
|
||||
plugins.add(new PluginInfo(p.isEnabled(), p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), p.getDescription().getAuthors()));
|
||||
|
||||
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
|
||||
// TODO more? ProtocolLib things etc?
|
||||
|
||||
return platformSpecific;
|
||||
}
|
||||
}
|
||||
+19
-19
@@ -1,19 +1,19 @@
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
|
||||
public class ViaVersion {
|
||||
|
||||
@Getter
|
||||
private static ViaVersionAPI instance;
|
||||
@Getter
|
||||
private static ViaVersionConfig config;
|
||||
|
||||
public static void setInstance(ViaVersionPlugin plugin) {
|
||||
Validate.isTrue(instance == null, "Instance is already set");
|
||||
ViaVersion.instance = plugin;
|
||||
ViaVersion.config = plugin.getConf();
|
||||
}
|
||||
}
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
|
||||
@Deprecated
|
||||
public class ViaVersion {
|
||||
@Getter
|
||||
private static ViaVersionAPI instance;
|
||||
@Getter
|
||||
private static ViaVersionConfig config;
|
||||
|
||||
public static void setInstance(ViaVersionPlugin plugin) {
|
||||
Validate.isTrue(instance == null, "Instance is already set");
|
||||
ViaVersion.instance = (ViaVersionAPI) plugin.getApi();
|
||||
ViaVersion.config = plugin.getConf();
|
||||
}
|
||||
}
|
||||
+144
-140
@@ -1,140 +1,144 @@
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.command.ViaVersionCommand;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ViaVersionAPI {
|
||||
/**
|
||||
* Is the player connection modified by ViaVersion?
|
||||
*
|
||||
* @param player Bukkit player object
|
||||
* @return True if the client is modified (At the moment it also means version 1.9 and higher)
|
||||
*/
|
||||
boolean isPorted(Player player);
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
* Will also retrieve version from ProtocolSupport if it's being used.
|
||||
*
|
||||
* @param player Bukkit player object
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(Player player);
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
*
|
||||
* @param uuid UUID of a player
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(UUID uuid);
|
||||
|
||||
/**
|
||||
* Is player using 1.9?
|
||||
*
|
||||
* @param playerUUID UUID of a player
|
||||
* @return True if the client is on 1.9
|
||||
*/
|
||||
boolean isPorted(UUID playerUUID);
|
||||
|
||||
/**
|
||||
* Get the version of the plugin
|
||||
*
|
||||
* @return Plugin version
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param player The player to send packet
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param uuid The uuid from the player to send packet
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return Bossbar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param health Number between 0 and 1
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return Bossbar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Get if global debug is enabled
|
||||
*
|
||||
* @return true if debug is enabled
|
||||
*/
|
||||
boolean isDebug();
|
||||
|
||||
/**
|
||||
* Get ViaVersions command handler
|
||||
*
|
||||
* @return command handler
|
||||
*/
|
||||
ViaVersionCommand getCommandHandler();
|
||||
|
||||
/**
|
||||
* Get if this version is a compatibility build for spigot.
|
||||
* Eg. 1.9.1 / 1.9.2 allow certain versions to connect
|
||||
*
|
||||
* @return True if it is
|
||||
*/
|
||||
boolean isCompatSpigotBuild();
|
||||
|
||||
/**
|
||||
* Get the supported protocol versions
|
||||
* This method removes any blocked protocol versions.
|
||||
* @see ProtocolRegistry#getSupportedVersions() for full list.
|
||||
*
|
||||
* @return a list of protocol versions
|
||||
*/
|
||||
SortedSet<Integer> getSupportedVersions();
|
||||
|
||||
/**
|
||||
* Gets if the server uses spigot
|
||||
* <p>
|
||||
* Note: Will only work after ViaVersion load
|
||||
*
|
||||
* @return True if spigot
|
||||
*/
|
||||
boolean isSpigot();
|
||||
|
||||
/**
|
||||
* Gets if protocol support is also being used.
|
||||
*
|
||||
* @return True if it is being used.
|
||||
*/
|
||||
boolean isProtocolSupport();
|
||||
}
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.command.ViaVersionCommand;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
public interface ViaVersionAPI extends ViaAPI<Player> {
|
||||
/**
|
||||
* Is the player connection modified by ViaVersion?
|
||||
*
|
||||
* @param player Bukkit player object
|
||||
* @return True if the client is modified (At the moment it also means version 1.9 and higher)
|
||||
* @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(Player)}
|
||||
*/
|
||||
boolean isPorted(Player player);
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
* Will also retrieve version from ProtocolSupport if it's being used.
|
||||
*
|
||||
* @param player Bukkit player object
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(Player player);
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
*
|
||||
* @param uuid UUID of a player
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(UUID uuid);
|
||||
|
||||
/**
|
||||
* Is player using 1.9?
|
||||
*
|
||||
* @param playerUUID UUID of a player
|
||||
* @return True if the client is on 1.9
|
||||
* @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(UUID)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isPorted(UUID playerUUID);
|
||||
|
||||
/**
|
||||
* Get the version of the plugin
|
||||
*
|
||||
* @return Plugin version
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param player The player to send packet
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param uuid The uuid from the player to send packet
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return BossBar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param health Number between 0 and 1
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return BossBar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Get if global debug is enabled
|
||||
*
|
||||
* @return true if debug is enabled
|
||||
*/
|
||||
boolean isDebug();
|
||||
|
||||
/**
|
||||
* Get ViaVersions commands handler
|
||||
*
|
||||
* @return commands handler
|
||||
*/
|
||||
ViaVersionCommand getCommandHandler();
|
||||
|
||||
/**
|
||||
* Get if this version is a compatibility build for spigot.
|
||||
* Eg. 1.9.1 / 1.9.2 allow certain versions to connect
|
||||
*
|
||||
* @return True if it is
|
||||
*/
|
||||
boolean isCompatSpigotBuild();
|
||||
|
||||
/**
|
||||
* Get the supported protocol versions
|
||||
* This method removes any blocked protocol versions.
|
||||
*
|
||||
* @return a list of protocol versions
|
||||
* @see ProtocolRegistry#getSupportedVersions() for full list.
|
||||
*/
|
||||
SortedSet<Integer> getSupportedVersions();
|
||||
|
||||
/**
|
||||
* Gets if the server uses spigot
|
||||
* <p>
|
||||
* Note: Will only work after ViaVersion load
|
||||
*
|
||||
* @return True if spigot
|
||||
*/
|
||||
boolean isSpigot();
|
||||
|
||||
/**
|
||||
* Gets if protocol support is also being used.
|
||||
*
|
||||
* @return True if it is being used.
|
||||
*/
|
||||
boolean isProtocolSupport();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package us.myles.ViaVersion.boss;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
|
||||
@Getter
|
||||
public class ViaBossBar extends CommonBoss<Player> {
|
||||
|
||||
public ViaBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
super(title, health, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addPlayer(Player player) {
|
||||
addPlayer(player.getUniqueId());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addPlayers(Player... players) {
|
||||
for (Player p : players)
|
||||
addPlayer(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar removePlayer(Player player) {
|
||||
removePlayer(player.getUniqueId());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package us.myles.ViaVersion.bukkit.classgenerator;
|
||||
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler;
|
||||
import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler;
|
||||
|
||||
public class BasicHandlerConstructor implements HandlerConstructor {
|
||||
@Override
|
||||
public BukkitEncodeHandler newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
|
||||
return new BukkitEncodeHandler(info, minecraftEncoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitDecodeHandler newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
|
||||
return new BukkitDecodeHandler(info, minecraftDecoder);
|
||||
}
|
||||
}
|
||||
+43
-31
@@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.classgenerator;
|
||||
package us.myles.ViaVersion.bukkit.classgenerator;
|
||||
|
||||
import javassist.*;
|
||||
import javassist.expr.ConstructorCall;
|
||||
@@ -6,9 +6,9 @@ import javassist.expr.ExprEditor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.handlers.ViaEncodeHandler;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
import us.myles.ViaVersion.bukkit.handlers.BukkitDecodeHandler;
|
||||
import us.myles.ViaVersion.bukkit.handlers.BukkitEncodeHandler;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
|
||||
public class ClassGenerator {
|
||||
private static HandlerConstructor constructor = new BasicHandlerConstructor();
|
||||
@@ -27,17 +27,17 @@ public class ClassGenerator {
|
||||
}
|
||||
|
||||
if (ViaVersion.getInstance().isCompatSpigotBuild()) {
|
||||
Class decodeSuper = ReflectionUtil.nms("PacketDecoder");
|
||||
Class encodeSuper = ReflectionUtil.nms("PacketEncoder");
|
||||
Class decodeSuper = NMSUtil.nms("PacketDecoder");
|
||||
Class encodeSuper = NMSUtil.nms("PacketEncoder");
|
||||
// Generate the classes
|
||||
addSpigotCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||
addSpigotCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
||||
addSpigotCompatibility(pool, BukkitDecodeHandler.class, decodeSuper);
|
||||
addSpigotCompatibility(pool, BukkitEncodeHandler.class, encodeSuper);
|
||||
} else {
|
||||
Class decodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedDecoder");
|
||||
Class encodeSuper = Class.forName(getPSPackage() + ".wrapped.WrappedEncoder");
|
||||
Class decodeSuper = Class.forName(getPSPackage().equals("unknown") ? "protocolsupport.protocol.pipeline.common.PacketDecoder" : getPSPackage() + ".wrapped.WrappedDecoder");
|
||||
Class encodeSuper = Class.forName(getPSPackage().equals("unknown") ? "protocolsupport.protocol.pipeline.common.PacketEncoder" : getPSPackage() + ".wrapped.WrappedEncoder");
|
||||
// Generate the classes
|
||||
addPSCompatibility(pool, ViaDecodeHandler.class, decodeSuper);
|
||||
addPSCompatibility(pool, ViaEncodeHandler.class, encodeSuper);
|
||||
addPSCompatibility(pool, BukkitDecodeHandler.class, decodeSuper);
|
||||
addPSCompatibility(pool, BukkitEncodeHandler.class, encodeSuper);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ public class ClassGenerator {
|
||||
pool.importPackage("io.netty.handler.codec");
|
||||
// Implement Methods
|
||||
generated.addMethod(CtMethod.make("public MessageToByteEncoder newEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {\n" +
|
||||
" return new ViaEncodeHandler(info, minecraftEncoder);\n" +
|
||||
" return new BukkitEncodeHandler(info, minecraftEncoder);\n" +
|
||||
" }", generated));
|
||||
generated.addMethod(CtMethod.make("public ByteToMessageDecoder newDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {\n" +
|
||||
" return new ViaDecodeHandler(info, minecraftDecoder);\n" +
|
||||
" return new BukkitDecodeHandler(info, minecraftDecoder);\n" +
|
||||
" }", generated));
|
||||
|
||||
constructor = (HandlerConstructor) generated.toClass(HandlerConstructor.class.getClassLoader()).newInstance();
|
||||
@@ -110,6 +110,7 @@ public class ClassGenerator {
|
||||
}
|
||||
|
||||
private static Class addPSCompatibility(ClassPool pool, Class input, Class superclass) {
|
||||
boolean newPS = getPSPackage().equals("unknown");
|
||||
String newName = "us.myles.ViaVersion.classgenerator.generated." + input.getSimpleName();
|
||||
|
||||
try {
|
||||
@@ -118,23 +119,34 @@ public class ClassGenerator {
|
||||
CtClass toExtend = pool.get(superclass.getName());
|
||||
generated.setSuperclass(toExtend);
|
||||
|
||||
// Override setRealEncoder / setRealDecoder
|
||||
pool.importPackage(getPSPackage());
|
||||
pool.importPackage(getPSPackage() + ".wrapped");
|
||||
if (superclass.getName().endsWith("Decoder")) {
|
||||
// Decoder
|
||||
generated.addMethod(CtMethod.make("public void setRealDecoder(IPacketDecoder dec) {\n" +
|
||||
" WrappedDecoder decoder = new WrappedDecoder();" +
|
||||
" decoder.setRealDecoder(dec);\n" +
|
||||
" this.minecraftDecoder = decoder;\n" +
|
||||
" }", generated));
|
||||
} else {
|
||||
// Encoder
|
||||
generated.addMethod(CtMethod.make("public void setRealEncoder(IPacketEncoder enc) {\n" +
|
||||
" WrappedEncoder encoder = new WrappedEncoder();" +
|
||||
" encoder.setRealEncoder(enc);\n" +
|
||||
" this.minecraftEncoder = encoder;\n" +
|
||||
" }", generated));
|
||||
if (!newPS) {
|
||||
// Override setRealEncoder / setRealDecoder
|
||||
pool.importPackage(getPSPackage());
|
||||
pool.importPackage(getPSPackage() + ".wrapped");
|
||||
if (superclass.getName().endsWith("Decoder")) {
|
||||
// Decoder
|
||||
generated.addMethod(CtMethod.make("public void setRealDecoder(IPacketDecoder dec) {\n" +
|
||||
" ((WrappedDecoder) this.minecraftDecoder).setRealDecoder(dec);\n" +
|
||||
" }", generated));
|
||||
} else {
|
||||
// Encoder
|
||||
pool.importPackage("protocolsupport.api");
|
||||
pool.importPackage("java.lang.reflect");
|
||||
generated.addMethod(CtMethod.make("public void setRealEncoder(IPacketEncoder enc) {\n" +
|
||||
" try {\n" +
|
||||
// Tell ProtocolSupport to decode MINECRAFT_FUTURE packets using the default decoder (for 1.9.4)
|
||||
" Field field = enc.getClass().getDeclaredField(\"version\");\n" +
|
||||
" field.setAccessible(true);\n" +
|
||||
" ProtocolVersion version = (ProtocolVersion) field.get(enc);\n" +
|
||||
|
||||
" if (version == ProtocolVersion.MINECRAFT_FUTURE) enc = enc.getClass().getConstructor(\n" +
|
||||
" new Class[]{ProtocolVersion.class}).newInstance(new Object[] {ProtocolVersion.getLatest()});\n" +
|
||||
" } catch (Exception e) {\n" +
|
||||
// I guess we're not on 1.9.4
|
||||
" }\n" +
|
||||
" ((WrappedEncoder) this.minecraftEncoder).setRealEncoder(enc);\n" +
|
||||
" }", generated));
|
||||
}
|
||||
}
|
||||
}
|
||||
return generated.toClass(HandlerConstructor.class.getClassLoader());
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.classgenerator;
|
||||
package us.myles.ViaVersion.bukkit.classgenerator;
|
||||
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
@@ -0,0 +1,21 @@
|
||||
package us.myles.ViaVersion.bukkit.commands;
|
||||
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BukkitCommandHandler extends ViaCommandHandler implements CommandExecutor, TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
return onCommand(new BukkitCommandSender(sender), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
return onTabComplete(new BukkitCommandSender(sender), args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package us.myles.ViaVersion.bukkit.commands;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BukkitCommandSender implements ViaCommandSender {
|
||||
private CommandSender sender;
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
sender.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
if (sender instanceof Player) {
|
||||
return ((Player) sender).getUniqueId();
|
||||
} else {
|
||||
return UUID.fromString(getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return sender.getName();
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.handlers;
|
||||
package us.myles.ViaVersion.bukkit.handlers;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
@@ -7,17 +7,17 @@ import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
import us.myles.ViaVersion.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.classgenerator.HandlerConstructor;
|
||||
import us.myles.ViaVersion.bukkit.classgenerator.ClassGenerator;
|
||||
import us.myles.ViaVersion.bukkit.classgenerator.HandlerConstructor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
|
||||
public class BukkitChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final ChannelInitializer<SocketChannel> original;
|
||||
private Method method;
|
||||
|
||||
public ViaVersionInitializer(ChannelInitializer<SocketChannel> oldInit) {
|
||||
public BukkitChannelInitializer(ChannelInitializer<SocketChannel> oldInit) {
|
||||
this.original = oldInit;
|
||||
try {
|
||||
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
@@ -43,7 +43,7 @@ public class ViaVersionInitializer extends ChannelInitializer<SocketChannel> {
|
||||
// Add our transformers
|
||||
MessageToByteEncoder encoder = constructor.newEncodeHandler(info, (MessageToByteEncoder) socketChannel.pipeline().get("encoder"));
|
||||
ByteToMessageDecoder decoder = constructor.newDecodeHandler(info, (ByteToMessageDecoder) socketChannel.pipeline().get("decoder"));
|
||||
ViaPacketHandler chunkHandler = new ViaPacketHandler(info);
|
||||
BukkitPacketHandler chunkHandler = new BukkitPacketHandler(info);
|
||||
|
||||
socketChannel.pipeline().replace("encoder", "encoder", encoder);
|
||||
socketChannel.pipeline().replace("decoder", "decoder", decoder);
|
||||
+5
-8
@@ -1,11 +1,9 @@
|
||||
package us.myles.ViaVersion.handlers;
|
||||
package us.myles.ViaVersion.bukkit.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
@@ -16,13 +14,12 @@ import us.myles.ViaVersion.util.PipelineUtil;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
|
||||
public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
public class BukkitDecodeHandler extends ByteToMessageDecoder {
|
||||
|
||||
private final ByteToMessageDecoder minecraftDecoder;
|
||||
private final UserConnection info;
|
||||
public static int PASSTHROUGH_ID = 1000;
|
||||
|
||||
public ViaDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
|
||||
public BukkitDecodeHandler(UserConnection info, ByteToMessageDecoder minecraftDecoder) {
|
||||
this.info = info;
|
||||
this.minecraftDecoder = minecraftDecoder;
|
||||
}
|
||||
@@ -39,7 +36,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
boolean second = info.incrementReceived();
|
||||
// Check PPS
|
||||
if (second) {
|
||||
if (((ViaVersionPlugin) ViaVersion.getInstance()).handlePPS(info))
|
||||
if (info.handlePPS())
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,7 +46,7 @@ public class ViaDecodeHandler extends ByteToMessageDecoder {
|
||||
// Transform
|
||||
ByteBuf newPacket = ctx.alloc().buffer();
|
||||
try {
|
||||
if (id == ViaDecodeHandler.PASSTHROUGH_ID) {
|
||||
if (id == PacketWrapper.PASSTHROUGH_ID) {
|
||||
newPacket.writeBytes(bytebuf);
|
||||
} else {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
|
||||
@@ -0,0 +1,93 @@
|
||||
package us.myles.ViaVersion.bukkit.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.handlers.ChannelHandlerContextWrapper;
|
||||
import us.myles.ViaVersion.handlers.ViaHandler;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class BukkitEncodeHandler extends MessageToByteEncoder implements ViaHandler {
|
||||
private static Field versionField = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
versionField = NMSUtil.nms("PacketEncoder").getDeclaredField("version");
|
||||
versionField.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
// Not compat version
|
||||
}
|
||||
}
|
||||
|
||||
private final UserConnection info;
|
||||
private final MessageToByteEncoder minecraftEncoder;
|
||||
|
||||
public BukkitEncodeHandler(UserConnection info, MessageToByteEncoder minecraftEncoder) {
|
||||
this.info = info;
|
||||
this.minecraftEncoder = minecraftEncoder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void encode(final ChannelHandlerContext ctx, Object o, final ByteBuf bytebuf) throws Exception {
|
||||
if (versionField != null) {
|
||||
versionField.set(minecraftEncoder, versionField.get(this));
|
||||
}
|
||||
// handle the packet type
|
||||
if (!(o instanceof ByteBuf)) {
|
||||
// call minecraft encoder
|
||||
try {
|
||||
PipelineUtil.callEncode(this.minecraftEncoder, new ChannelHandlerContextWrapper(ctx, this), o, bytebuf);
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() instanceof Exception) {
|
||||
throw (Exception) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform(bytebuf);
|
||||
}
|
||||
|
||||
public void transform(ByteBuf bytebuf) throws Exception {
|
||||
if (bytebuf.readableBytes() == 0) {
|
||||
return; // Someone Already Decoded It!
|
||||
}
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf oldPacket = bytebuf.copy();
|
||||
bytebuf.clear();
|
||||
|
||||
try {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(bytebuf);
|
||||
} catch (Exception e) {
|
||||
bytebuf.clear();
|
||||
throw e;
|
||||
} finally {
|
||||
oldPacket.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.handlers;
|
||||
package us.myles.ViaVersion.bukkit.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -8,10 +8,10 @@ import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ViaPacketHandler extends MessageToMessageEncoder {
|
||||
public class BukkitPacketHandler extends MessageToMessageEncoder {
|
||||
private final UserConnection info;
|
||||
|
||||
public ViaPacketHandler(UserConnection info) {
|
||||
public BukkitPacketHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
+18
-23
@@ -1,23 +1,18 @@
|
||||
package us.myles.ViaVersion.update;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class UpdateListener implements Listener {
|
||||
|
||||
private final ViaVersionPlugin plugin;
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (e.getPlayer().hasPermission("viaversion.update")
|
||||
&& ViaVersion.getConfig().isCheckForUpdates()) {
|
||||
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId(), plugin);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package us.myles.ViaVersion.bukkit.listeners;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.update.UpdateUtil;
|
||||
|
||||
public class UpdateListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
if (e.getPlayer().hasPermission("viaversion.update")
|
||||
&& Via.getConfig().isCheckForUpdates()) {
|
||||
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package us.myles.ViaVersion.bukkit.listeners;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaListener;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
public class ViaBukkitListener extends ViaListener implements Listener {
|
||||
private final Plugin plugin;
|
||||
|
||||
public ViaBukkitListener(ViaVersionPlugin plugin, Class<? extends Protocol> requiredPipeline) {
|
||||
super(requiredPipeline);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UserConnection from a player
|
||||
*
|
||||
* @param player Player object
|
||||
* @return The UserConnection
|
||||
*/
|
||||
protected UserConnection getUserConnection(@NonNull Player player) {
|
||||
return getUserConnection(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is on the selected pipe
|
||||
*
|
||||
* @param player Player Object
|
||||
* @return True if on pipe
|
||||
*/
|
||||
protected boolean isOnPipe(Player player) {
|
||||
return isOnPipe(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register as Bukkit event
|
||||
*/
|
||||
@Override
|
||||
public void register() {
|
||||
if (isRegistered()) return;
|
||||
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
setRegistered(true);
|
||||
}
|
||||
}
|
||||
+30
-35
@@ -1,12 +1,10 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
@@ -14,32 +12,36 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.inventory.CraftingInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.ArmorType;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ArmorListener implements Listener {
|
||||
public class ArmorListener extends ViaBukkitListener {
|
||||
|
||||
private static final UUID ARMOR_ATTRIBUTE = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150");
|
||||
private final ViaVersionPlugin plugin;
|
||||
|
||||
public static void sendArmorUpdate(Player player) {
|
||||
public ArmorListener(ViaVersionPlugin plugin) {
|
||||
super(plugin, Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
public void sendArmorUpdate(Player player) {
|
||||
// Ensure that the player is on our pipe
|
||||
UserConnection userConnection = ((ViaVersionPlugin) ViaVersion.getInstance()).getConnection(player);
|
||||
if (userConnection == null) return;
|
||||
if (!userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) return;
|
||||
if (!isOnPipe(player)) return;
|
||||
|
||||
int armor = ArmorType.calculateArmorPoints(player.getInventory().getArmorContents());
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapper(0x4B, null, userConnection);
|
||||
int armor = 0;
|
||||
for (ItemStack stack : player.getInventory().getArmorContents()) {
|
||||
armor += ArmorType.findById(stack.getTypeId()).getArmorPoints();
|
||||
}
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapper(0x4B, null, getUserConnection(player));
|
||||
try {
|
||||
wrapper.write(Type.VAR_INT, player.getEntityId()); // Player ID
|
||||
wrapper.write(Type.INT, 1); // only 1 property
|
||||
@@ -61,17 +63,15 @@ public class ArmorListener implements Listener {
|
||||
HumanEntity human = e.getWhoClicked();
|
||||
if (human instanceof Player && e.getInventory() instanceof CraftingInventory) {
|
||||
final Player player = (Player) human;
|
||||
if (ViaVersion.getInstance().isPorted(player)) {
|
||||
if (e.getCurrentItem() != null) {
|
||||
if (ArmorType.isArmor(e.getCurrentItem().getType())) {
|
||||
sendDelayedArmorUpdate(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (e.getRawSlot() >= 5 && e.getRawSlot() <= 8) {
|
||||
if (e.getCurrentItem() != null) {
|
||||
if (ArmorType.isArmor(e.getCurrentItem().getTypeId())) {
|
||||
sendDelayedArmorUpdate(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (e.getRawSlot() >= 5 && e.getRawSlot() <= 8) {
|
||||
sendDelayedArmorUpdate(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,12 +81,10 @@ public class ArmorListener implements Listener {
|
||||
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
|
||||
final Player player = e.getPlayer();
|
||||
// Due to odd bugs it's 3 ticks later
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (ViaVersion.getInstance().isPorted(player)) {
|
||||
sendArmorUpdate(player);
|
||||
}
|
||||
sendArmorUpdate(player);
|
||||
}
|
||||
}, 3L);
|
||||
}
|
||||
@@ -100,23 +98,20 @@ public class ArmorListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onRespawn(PlayerRespawnEvent e) {
|
||||
if (ViaVersion.getInstance().isPorted(e.getPlayer()))
|
||||
sendDelayedArmorUpdate(e.getPlayer());
|
||||
sendDelayedArmorUpdate(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onWorldChange(PlayerChangedWorldEvent e) {
|
||||
if (ViaVersion.getInstance().isPorted(e.getPlayer()))
|
||||
sendArmorUpdate(e.getPlayer());
|
||||
sendArmorUpdate(e.getPlayer());
|
||||
}
|
||||
|
||||
public void sendDelayedArmorUpdate(final Player player) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||
if (!isOnPipe(player)) return; // Don't start a task if the player is not on the pipe
|
||||
Via.getPlatform().runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (ViaVersion.getInstance().isPorted(player)) {
|
||||
sendArmorUpdate(player);
|
||||
}
|
||||
sendArmorUpdate(player);
|
||||
}
|
||||
});
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.minecraft.Position;
|
||||
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker;
|
||||
|
||||
public class BlockListener extends ViaBukkitListener {
|
||||
|
||||
public BlockListener(ViaVersionPlugin plugin) {
|
||||
super(plugin, Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void placeBlock(BlockPlaceEvent e) {
|
||||
if (isOnPipe(e.getPlayer())) {
|
||||
Block b = e.getBlockPlaced();
|
||||
getUserConnection(e.getPlayer())
|
||||
.get(EntityTracker.class)
|
||||
.addBlockInteraction(new Position((long) b.getX(), (long) b.getY(), (long) b.getZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-26
@@ -1,40 +1,28 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class DeathListener implements Listener {
|
||||
private final ViaVersionPlugin plugin;
|
||||
public class DeathListener extends ViaBukkitListener {
|
||||
public DeathListener(ViaVersionPlugin plugin) {
|
||||
super(plugin, Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onDeath(PlayerDeathEvent e) {
|
||||
Player p = e.getEntity();
|
||||
if (ViaVersion.getConfig().isShowNewDeathMessages() && checkGamerule(p.getWorld()) && e.getDeathMessage() != null && checkPipeline(p)) {
|
||||
if (isOnPipe(p) && ViaVersion.getConfig().isShowNewDeathMessages() && checkGamerule(p.getWorld()) && e.getDeathMessage() != null)
|
||||
sendPacket(p, e.getDeathMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkPipeline(Player p) {
|
||||
UserConnection userConnection = plugin.getConnection(p);
|
||||
return userConnection != null && userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
private UserConnection getUserConnection(Player p) {
|
||||
return plugin.getConnection(p);
|
||||
}
|
||||
|
||||
public boolean checkGamerule(World w) {
|
||||
@@ -46,19 +34,19 @@ public class DeathListener implements Listener {
|
||||
}
|
||||
|
||||
private void sendPacket(final Player p, final String msg) {
|
||||
Bukkit.getScheduler().runTask(plugin, new Runnable() {
|
||||
Via.getPlatform().runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x2C, null, getUserConnection(p));
|
||||
try {
|
||||
wrapper.write(Type.VAR_INT, 2);
|
||||
wrapper.write(Type.VAR_INT, p.getEntityId());
|
||||
wrapper.write(Type.INT, p.getEntityId());
|
||||
Protocol1_9TO1_8.FIX_JSON.write(wrapper, msg);
|
||||
wrapper.write(Type.VAR_INT, 2); // Event - Entity dead
|
||||
wrapper.write(Type.VAR_INT, p.getEntityId()); // Player ID
|
||||
wrapper.write(Type.INT, p.getEntityId()); // Entity ID
|
||||
Protocol1_9TO1_8.FIX_JSON.write(wrapper, msg); // Message
|
||||
|
||||
wrapper.send(Protocol1_9TO1_8.class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
wrapper.clearInputBuffer();
|
||||
}
|
||||
}
|
||||
});
|
||||
+10
-6
@@ -1,18 +1,17 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class HandItemCache extends BukkitRunnable {
|
||||
public static boolean CACHE = false;
|
||||
private static ConcurrentHashMap<UUID, Item> handCache = new ConcurrentHashMap<>();
|
||||
private static Map<UUID, Item> handCache = new ConcurrentHashMap<>();
|
||||
|
||||
public static Item getHandItem(UUID player) {
|
||||
if (!handCache.containsKey(player))
|
||||
@@ -25,7 +24,7 @@ public class HandItemCache extends BukkitRunnable {
|
||||
List<UUID> players = new ArrayList<>(handCache.keySet());
|
||||
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
handCache.put(p.getUniqueId(), Item.getItem(p.getItemInHand()));
|
||||
handCache.put(p.getUniqueId(), convert(p.getItemInHand()));
|
||||
players.remove(p.getUniqueId());
|
||||
}
|
||||
// Remove offline players
|
||||
@@ -33,4 +32,9 @@ public class HandItemCache extends BukkitRunnable {
|
||||
handCache.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public static Item convert(ItemStack itemInHand) {
|
||||
if (itemInHand == null) return new Item((short) 0, (byte) 0, (short) 0, null);
|
||||
return new Item((short) itemInHand.getTypeId(), (byte) itemInHand.getAmount(), itemInHand.getDurability(), null);
|
||||
}
|
||||
}
|
||||
+14
-11
@@ -1,32 +1,35 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.listeners;
|
||||
package us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.bukkit.listeners.ViaBukkitListener;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
|
||||
|
||||
public class PaperPatch implements Listener {
|
||||
public class PaperPatch extends ViaBukkitListener {
|
||||
|
||||
public PaperPatch(ViaVersionPlugin plugin) {
|
||||
super(plugin, Protocol1_9TO1_8.class);
|
||||
}
|
||||
|
||||
/*
|
||||
This patch is applied when Paper is detected.
|
||||
I'm unsure of what causes this but essentially,
|
||||
placing blocks where your standing works?
|
||||
placing blocks where you're standing works?
|
||||
If there is a better fix then we'll replace this.
|
||||
*/
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlace(BlockPlaceEvent e) {
|
||||
if (ViaVersion.getInstance().isPorted(e.getPlayer())) {
|
||||
UserConnection userConnection = ((ViaVersionPlugin) ViaVersion.getInstance()).getConnection(e.getPlayer());
|
||||
if (userConnection == null) return;
|
||||
if (!userConnection.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) return;
|
||||
if (isOnPipe(e.getPlayer())) {
|
||||
Location diff = e.getPlayer().getLocation().subtract(e.getBlock().getLocation().add(0.5D, 0, 0.5D));
|
||||
Material block = e.getBlockPlaced().getType();
|
||||
if (!block.isSolid()) {
|
||||
return;
|
||||
}
|
||||
if (e.getPlayer().getLocation().getBlock().equals(e.getBlock())) {
|
||||
e.setCancelled(true);
|
||||
} else {
|
||||
@@ -0,0 +1,184 @@
|
||||
package us.myles.ViaVersion.bukkit.platform;
|
||||
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||
import us.myles.ViaVersion.util.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class BukkitConfigAPI extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers");
|
||||
|
||||
public BukkitConfigAPI() {
|
||||
super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCheckForUpdates() {
|
||||
return getBoolean("checkforupdates", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventCollision() {
|
||||
return getBoolean("prevent-collision", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNewEffectIndicator() {
|
||||
return getBoolean("use-new-effect-indicator", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowNewDeathMessages() {
|
||||
return getBoolean("use-new-deathmessages", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressMetadataErrors() {
|
||||
return getBoolean("suppress-metadata-errors", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShieldBlocking() {
|
||||
return getBoolean("shield-blocking", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHologramPatch() {
|
||||
return getBoolean("hologram-patch", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean 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 getBoolean("anti-xray-patch", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSendSupportedVersions() {
|
||||
return getBoolean("send-supported-versions", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStimulatePlayerTick() {
|
||||
return getBoolean("simulate-pt", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemCache() {
|
||||
return getBoolean("item-cache", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNMSPlayerTicking() {
|
||||
return getBoolean("nms-player-ticking", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplacePistons() {
|
||||
return getBoolean("replace-pistons", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPistonReplacementId() {
|
||||
return getInt("replacement-piston-id", 0);
|
||||
}
|
||||
|
||||
public boolean isAutoTeam() {
|
||||
// Collision has to be enabled first
|
||||
return isPreventCollision() && getBoolean("auto-team", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isForceJsonTransform() {
|
||||
return getBoolean("force-json-transform", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getBlockedProtocols() {
|
||||
return getIntegerList("block-protocols");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBlockedDisconnectMsg() {
|
||||
return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReloadDisconnectMsg() {
|
||||
return getString("reload-disconnect-msg", "Server reload, please rejoin!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleConfig(Map<String, Object> config) {
|
||||
// Nothing currently
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUnsupportedOptions() {
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package us.myles.ViaVersion.bukkit.platform;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.api.platform.TaskId;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class BukkitTaskId implements TaskId {
|
||||
private Integer object;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package us.myles.ViaVersion.bukkit.platform;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaAPI;
|
||||
import us.myles.ViaVersion.api.ViaVersionAPI;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.command.ViaVersionCommand;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.boss.ViaBossBar;
|
||||
import us.myles.ViaVersion.bukkit.util.ProtocolSupportUtil;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BukkitViaAPI implements ViaAPI<Player>, ViaVersionAPI {
|
||||
private ViaVersionPlugin plugin;
|
||||
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull Player player) {
|
||||
if (!isPorted(player))
|
||||
return getExternalVersion(player);
|
||||
return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull UUID uuid) {
|
||||
if (!isPorted(uuid))
|
||||
return getExternalVersion(Bukkit.getPlayer(uuid));
|
||||
return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
private int getExternalVersion(Player player) {
|
||||
if (!isProtocolSupport()) {
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
} else {
|
||||
return ProtocolSupportUtil.getProtocolVersion(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPorted(Player player) {
|
||||
return isPorted(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPorted(UUID playerUUID) {
|
||||
return getPortedPlayers().containsKey(playerUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return plugin.getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
|
||||
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!");
|
||||
UserConnection ci = getPortedPlayers().get(uuid);
|
||||
ci.sendRawPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException {
|
||||
sendRawPacket(player.getUniqueId(), packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
|
||||
return new ViaBossBar(title, 1F, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
return new ViaBossBar(title, health, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebug() {
|
||||
return Via.getManager().isDebug();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaVersionCommand getCommandHandler() {
|
||||
return Via.getManager().getCommandHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<Integer> getSupportedVersions() {
|
||||
SortedSet<Integer> outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions());
|
||||
outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols());
|
||||
|
||||
return outputSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompatSpigotBuild() {
|
||||
return plugin.isCompatSpigotBuild();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSpigot() {
|
||||
return plugin.isSpigot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProtocolSupport() {
|
||||
return plugin.isProtocolSupport();
|
||||
}
|
||||
|
||||
public Map<UUID, UserConnection> getPortedPlayers() {
|
||||
return Via.getManager().getPortedPlayers();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
package us.myles.ViaVersion.bukkit.platform;
|
||||
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.bukkit.handlers.BukkitChannelInitializer;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
import us.myles.ViaVersion.util.ConcurrentList;
|
||||
import us.myles.ViaVersion.util.ListWrapper;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BukkitViaInjector implements ViaInjector {
|
||||
private List<ChannelFuture> injectedFutures = new ArrayList<>();
|
||||
private List<Pair<Field, Object>> injectedLists = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void inject() throws Exception {
|
||||
try {
|
||||
Object connection = getServerConnection();
|
||||
if (connection == null) {
|
||||
throw new Exception("We failed to find the core component 'ServerConnection', please file an issue on our GitHub.");
|
||||
}
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
final Object value = field.get(connection);
|
||||
if (value instanceof List) {
|
||||
// Inject the list
|
||||
List wrapper = new ListWrapper((List) value) {
|
||||
@Override
|
||||
public synchronized void handleAdd(Object o) {
|
||||
synchronized (this) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
try {
|
||||
injectChannelFuture((ChannelFuture) o);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
injectedLists.add(new Pair<>(field, connection));
|
||||
field.set(connection, wrapper);
|
||||
// Iterate through current list
|
||||
synchronized (wrapper) {
|
||||
for (Object o : (List) value) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
injectChannelFuture((ChannelFuture) o);
|
||||
} else {
|
||||
break; // not the right list.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private void injectChannelFuture(ChannelFuture future) throws Exception {
|
||||
try {
|
||||
List<String> names = future.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
// Pick best
|
||||
for (String name : names) {
|
||||
ChannelHandler handler = future.channel().pipeline().get(name);
|
||||
try {
|
||||
ReflectionUtil.get(handler, "childHandler", ChannelInitializer.class);
|
||||
bootstrapAcceptor = handler;
|
||||
} catch (Exception e) {
|
||||
// Not this one
|
||||
}
|
||||
}
|
||||
// Default to first (Also allows blame to work)
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = future.channel().pipeline().first();
|
||||
}
|
||||
try {
|
||||
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
||||
ChannelInitializer newInit = new BukkitChannelInitializer(oldInit);
|
||||
|
||||
ReflectionUtil.set(bootstrapAcceptor, "childHandler", newInit);
|
||||
injectedFutures.add(future);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// let's find who to blame!
|
||||
ClassLoader cl = bootstrapAcceptor.getClass().getClassLoader();
|
||||
if (cl.getClass().getName().equals("org.bukkit.plugin.java.PluginClassLoader")) {
|
||||
PluginDescriptionFile yaml = ReflectionUtil.get(cl, "description", PluginDescriptionFile.class);
|
||||
throw new Exception("Unable to inject, due to " + bootstrapAcceptor.getClass().getName() + ", try without the plugin " + yaml.getName() + "?");
|
||||
} else {
|
||||
throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: " + bootstrapAcceptor.getClass().getName());
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("We failed to inject ViaVersion, have you got late-bind enabled with something else?");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninject() {
|
||||
// TODO: Uninject from players currently online to prevent protocol lib issues.
|
||||
for (ChannelFuture future : injectedFutures) {
|
||||
List<String> names = future.channel().pipeline().names();
|
||||
ChannelHandler bootstrapAcceptor = null;
|
||||
// Pick best
|
||||
for (String name : names) {
|
||||
ChannelHandler handler = future.channel().pipeline().get(name);
|
||||
try {
|
||||
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(handler, "childHandler", ChannelInitializer.class);
|
||||
if (oldInit instanceof BukkitChannelInitializer) {
|
||||
bootstrapAcceptor = handler;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Not this one
|
||||
}
|
||||
}
|
||||
// Default to first
|
||||
if (bootstrapAcceptor == null) {
|
||||
bootstrapAcceptor = future.channel().pipeline().first();
|
||||
}
|
||||
|
||||
try {
|
||||
ChannelInitializer<SocketChannel> oldInit = ReflectionUtil.get(bootstrapAcceptor, "childHandler", ChannelInitializer.class);
|
||||
if (oldInit instanceof BukkitChannelInitializer) {
|
||||
ReflectionUtil.set(bootstrapAcceptor, "childHandler", ((BukkitChannelInitializer) oldInit).getOriginal());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Failed to remove injection handler, reload won't work with connections, please reboot!");
|
||||
}
|
||||
}
|
||||
injectedFutures.clear();
|
||||
|
||||
for (Pair<Field, Object> pair : injectedLists) {
|
||||
try {
|
||||
Object o = pair.getKey().get(pair.getValue());
|
||||
if (o instanceof ListWrapper) {
|
||||
pair.getKey().set(pair.getValue(), ((ListWrapper) o).getOriginalList());
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
Via.getPlatform().getLogger().severe("Failed to remove injection, reload won't work with connections, please reboot!");
|
||||
}
|
||||
}
|
||||
|
||||
injectedLists.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerProtocolVersion() throws Exception {
|
||||
try {
|
||||
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||
Class<?> pingClazz = NMSUtil.nms("ServerPing");
|
||||
Object ping = null;
|
||||
// Search for ping method
|
||||
for (Field f : serverClazz.getDeclaredFields()) {
|
||||
if (f.getType() != null) {
|
||||
if (f.getType().getSimpleName().equals("ServerPing")) {
|
||||
f.setAccessible(true);
|
||||
ping = f.get(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ping != null) {
|
||||
Object serverData = null;
|
||||
for (Field f : pingClazz.getDeclaredFields()) {
|
||||
if (f.getType() != null) {
|
||||
if (f.getType().getSimpleName().endsWith("ServerData")) {
|
||||
f.setAccessible(true);
|
||||
serverData = f.get(ping);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (serverData != null) {
|
||||
int protocolVersion = -1;
|
||||
for (Field f : serverData.getClass().getDeclaredFields()) {
|
||||
if (f.getType() != null) {
|
||||
if (f.getType() == int.class) {
|
||||
f.setAccessible(true);
|
||||
protocolVersion = (int) f.get(serverData);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (protocolVersion != -1) {
|
||||
return protocolVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Failed to get server", e);
|
||||
}
|
||||
throw new Exception("Failed to get server");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoderName() {
|
||||
return "encoder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDecoderName() {
|
||||
return "decoder";
|
||||
}
|
||||
|
||||
public static Object getServerConnection() throws Exception {
|
||||
Class<?> serverClazz = NMSUtil.nms("MinecraftServer");
|
||||
Object server = ReflectionUtil.invokeStatic(serverClazz, "getServer");
|
||||
Object connection = null;
|
||||
for (Method m : serverClazz.getDeclaredMethods()) {
|
||||
if (m.getReturnType() != null) {
|
||||
if (m.getReturnType().getSimpleName().equals("ServerConnection")) {
|
||||
if (m.getParameterTypes().length == 0) {
|
||||
connection = m.invoke(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public static void patchLists() throws Exception {
|
||||
Object connection = getServerConnection();
|
||||
if (connection == null) {
|
||||
Via.getPlatform().getLogger().warning("We failed to find the core component 'ServerConnection', please file an issue on our GitHub.");
|
||||
return;
|
||||
}
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
final Object value = field.get(connection);
|
||||
if (value instanceof List) {
|
||||
if (!(value instanceof ConcurrentList)) {
|
||||
ConcurrentList list = new ConcurrentList();
|
||||
list.addAll((List) value);
|
||||
field.set(connection, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isBinded() {
|
||||
try {
|
||||
Object connection = getServerConnection();
|
||||
if (connection == null) {
|
||||
return false;
|
||||
}
|
||||
for (Field field : connection.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
final Object value = field.get(connection);
|
||||
if (value instanceof List) {
|
||||
// Inject the list
|
||||
synchronized (value) {
|
||||
for (Object o : (List) value) {
|
||||
if (o instanceof ChannelFuture) {
|
||||
return true;
|
||||
} else {
|
||||
break; // not the right list.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package us.myles.ViaVersion.bukkit.platform;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.minecraft.item.Item;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
|
||||
import us.myles.ViaVersion.bukkit.listeners.UpdateListener;
|
||||
import us.myles.ViaVersion.bukkit.listeners.protocol1_9to1_8.*;
|
||||
import us.myles.ViaVersion.bukkit.providers.BukkitViaBulkChunkTranslator;
|
||||
import us.myles.ViaVersion.bukkit.providers.BukkitViaMovementTransmitter;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BukkitViaLoader implements ViaPlatformLoader {
|
||||
private ViaVersionPlugin plugin;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// Update Listener
|
||||
Bukkit.getPluginManager().registerEvents(new UpdateListener(), plugin);
|
||||
|
||||
/* Base Protocol */
|
||||
final ViaVersionPlugin plugin = (ViaVersionPlugin) Bukkit.getPluginManager().getPlugin("ViaVersion");
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new Listener() {
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
Via.getManager().removePortedClient(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
/* 1.9 client to 1.8 server */
|
||||
|
||||
new ArmorListener(plugin).register();
|
||||
new DeathListener(plugin).register();
|
||||
new BlockListener(plugin).register();
|
||||
|
||||
if (Bukkit.getVersion().toLowerCase().contains("paper") || Bukkit.getVersion().toLowerCase().contains("taco")) {
|
||||
plugin.getLogger().info("Enabling PaperSpigot/TacoSpigot patch: Fixes block placement.");
|
||||
new PaperPatch(plugin).register();
|
||||
}
|
||||
if (plugin.getConf().isItemCache()) {
|
||||
new HandItemCache().runTaskTimerAsynchronously(plugin, 2L, 2L); // Updates player's items :)
|
||||
HandItemCache.CACHE = true;
|
||||
}
|
||||
|
||||
/* Providers */
|
||||
Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new BukkitViaBulkChunkTranslator());
|
||||
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BukkitViaMovementTransmitter());
|
||||
Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() {
|
||||
@Override
|
||||
public Item getHandItem(final UserConnection info) {
|
||||
if (HandItemCache.CACHE) {
|
||||
return HandItemCache.getHandItem(info.get(ProtocolInfo.class).getUuid());
|
||||
} else {
|
||||
try {
|
||||
return Bukkit.getScheduler().callSyncMethod(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Callable<Item>() {
|
||||
@Override
|
||||
public Item call() throws Exception {
|
||||
UUID playerUUID = info.get(ProtocolInfo.class).getUuid();
|
||||
if (Bukkit.getPlayer(playerUUID) != null) {
|
||||
return HandItemCache.convert(Bukkit.getPlayer(playerUUID).getItemInHand());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Error fetching hand item: " + e.getClass().getName());
|
||||
if (Via.getManager().isDebug())
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
+32
-38
@@ -1,69 +1,53 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage;
|
||||
package us.myles.ViaVersion.bukkit.providers;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldType;
|
||||
import us.myles.ViaVersion.api.ViaVersion;
|
||||
import us.myles.ViaVersion.api.data.StoredObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.ViaVersionPlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@Getter
|
||||
public class ClientChunks extends StoredObject {
|
||||
public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider {
|
||||
// Reflection
|
||||
private static ReflectionUtil.ClassReflection mapChunkBulkRef;
|
||||
private static ReflectionUtil.ClassReflection mapChunkRef;
|
||||
private static Method obfuscateRef;
|
||||
private static Class<?> worldRef;
|
||||
|
||||
static {
|
||||
try {
|
||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||
mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk"));
|
||||
if (ViaVersion.getInstance().isSpigot()) {
|
||||
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World"));
|
||||
worldRef = ReflectionUtil.nms("World");
|
||||
mapChunkBulkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunkBulk"));
|
||||
mapChunkRef = new ReflectionUtil.ClassReflection(NMSUtil.nms("PacketPlayOutMapChunk"));
|
||||
if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) {
|
||||
obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, NMSUtil.nms("World"));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Ignore as server is probably 1.9+
|
||||
} catch (Exception e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e);
|
||||
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<Long> loadedChunks = Sets.newConcurrentHashSet();
|
||||
private final Set<Long> bulkChunks = Sets.newConcurrentHashSet();
|
||||
|
||||
public ClientChunks(UserConnection user) {
|
||||
super(user);
|
||||
}
|
||||
|
||||
private static long toLong(int msw, int lsw) {
|
||||
return ((long) msw << 32) + lsw - -2147483648L;
|
||||
}
|
||||
|
||||
public List<Object> transformMapChunkBulk(Object packet) {
|
||||
@Override
|
||||
public List<Object> transformMapChunkBulk(Object packet, ClientChunks clientChunks) {
|
||||
List<Object> list = Lists.newArrayList();
|
||||
try {
|
||||
int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class);
|
||||
int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class);
|
||||
Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class);
|
||||
|
||||
if (ViaVersion.getConfig().isAntiXRay() && ViaVersion.getInstance().isSpigot()) { //Spigot anti-xray patch
|
||||
if (Via.getConfig().isAntiXRay() && ((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { //Spigot anti-xray patch
|
||||
try {
|
||||
Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class);
|
||||
Object spigotConfig = ReflectionUtil.getPublic(world, "spigotConfig", Object.class);
|
||||
Object antiXrayInstance = ReflectionUtil.getPublic(spigotConfig, "antiXrayInstance", Object.class);
|
||||
|
||||
for (int i = 0; i < xcoords.length; ++i) {
|
||||
Object spigotConfig = ReflectionUtil.getPublic(world, "spigotConfig", Object.class);
|
||||
Object antiXrayInstance = ReflectionUtil.getPublic(spigotConfig, "antiXrayInstance", Object.class);
|
||||
|
||||
// TODO: Possibly optimise this
|
||||
Object b = ReflectionUtil.get(chunkMaps[i], "b", Object.class);
|
||||
Object a = ReflectionUtil.get(chunkMaps[i], "a", Object.class);
|
||||
|
||||
@@ -82,12 +66,22 @@ public class ClientChunks extends StoredObject {
|
||||
mapChunkRef.setFieldValue("b", chunkPacket, z);
|
||||
mapChunkRef.setFieldValue("c", chunkPacket, chunkMap);
|
||||
mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up
|
||||
bulkChunks.add(toLong(x, z)); // Store for later
|
||||
clientChunks.getBulkChunks().add(ClientChunks.toLong(x, z)); // Store for later
|
||||
list.add(chunkPacket);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e);
|
||||
Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFiltered(Class<?> packetClass) {
|
||||
return packetClass.getName().endsWith("PacketPlayOutMapChunkBulk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPacketLevel() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package us.myles.ViaVersion.bukkit.providers;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.bukkit.util.NMSUtil;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class BukkitViaMovementTransmitter extends MovementTransmitterProvider {
|
||||
private static boolean USE_NMS = true;
|
||||
// Used for packet mode
|
||||
private Object idlePacket;
|
||||
private Object idlePacket2;
|
||||
// Use for nms
|
||||
private Method getHandle;
|
||||
private Field connection;
|
||||
private Method handleFlying;
|
||||
|
||||
public BukkitViaMovementTransmitter() {
|
||||
USE_NMS = Via.getConfig().isNMSPlayerTicking();
|
||||
|
||||
Class<?> idlePacketClass;
|
||||
try {
|
||||
idlePacketClass = NMSUtil.nms("PacketPlayInFlying");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return; // We'll hope this is 1.9.4+
|
||||
}
|
||||
try {
|
||||
idlePacket = idlePacketClass.newInstance();
|
||||
idlePacket2 = idlePacketClass.newInstance();
|
||||
|
||||
Field flying = idlePacketClass.getDeclaredField("f");
|
||||
flying.setAccessible(true);
|
||||
|
||||
flying.set(idlePacket2, true);
|
||||
} catch (NoSuchFieldException | InstantiationException | IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Couldn't make player idle packet, help!", e);
|
||||
}
|
||||
if (USE_NMS) {
|
||||
try {
|
||||
getHandle = NMSUtil.obc("entity.CraftPlayer").getDeclaredMethod("getHandle");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
|
||||
try {
|
||||
connection = NMSUtil.nms("EntityPlayer").getDeclaredField("playerConnection");
|
||||
} catch (NoSuchFieldException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find Player Connection", e);
|
||||
}
|
||||
|
||||
try {
|
||||
handleFlying = NMSUtil.nms("PlayerConnection").getDeclaredMethod("a", idlePacketClass);
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
throw new RuntimeException("Couldn't find CraftPlayer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFlyingPacket() {
|
||||
if (idlePacket == null)
|
||||
throw new NullPointerException("Could not locate flying packet");
|
||||
return idlePacket2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroundPacket() {
|
||||
if (idlePacket == null)
|
||||
throw new NullPointerException("Could not locate flying packet");
|
||||
return idlePacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayer(UserConnection info) {
|
||||
if (USE_NMS) {
|
||||
Player player = Bukkit.getPlayer(info.get(ProtocolInfo.class).getUuid());
|
||||
if (player != null) {
|
||||
try {
|
||||
// Tick player
|
||||
Object entityPlayer = getHandle.invoke(player);
|
||||
Object pc = connection.get(entityPlayer);
|
||||
if (pc != null) {
|
||||
handleFlying.invoke(pc, (info.get(MovementTracker.class).isGround() ? idlePacket2 : idlePacket));
|
||||
// Tick world
|
||||
info.get(MovementTracker.class).incrementIdlePacket();
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.sendPlayer(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package us.myles.ViaVersion.bukkit.util;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class NMSUtil {
|
||||
private static String BASE = Bukkit.getServer().getClass().getPackage().getName();
|
||||
private static String NMS = BASE.replace("org.bukkit.craftbukkit", "net.minecraft.server");
|
||||
|
||||
public static Class<?> nms(String className) throws ClassNotFoundException {
|
||||
return Class.forName(NMS + "." + className);
|
||||
}
|
||||
|
||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return BASE.substring(BASE.lastIndexOf('.') + 1);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package us.myles.ViaVersion.util;
|
||||
package us.myles.ViaVersion.bukkit.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
name: ViaVersion
|
||||
main: us.myles.ViaVersion.ViaVersionPlugin
|
||||
authors: [_MylesC, Matsv]
|
||||
version: ${project.version}
|
||||
description: ${project.description}
|
||||
load: postworld
|
||||
loadbefore: [ProtocolLib, ProxyPipe, SpigotLib, SkinRestorer]
|
||||
softdepend: [ProtocolSupport, PacketListenerApi]
|
||||
commands:
|
||||
viaversion:
|
||||
description: Shows ViaVersion Version and more.
|
||||
aliases: [viaver, vvbukkit]
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>viaversion-bungee</artifactId>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>.</targetPath>
|
||||
<filtering>true</filtering>
|
||||
<directory>src/main/resources/</directory>
|
||||
<includes>
|
||||
<include>*</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- BungeeCord API -->
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.10-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Common Module -->
|
||||
<dependency>
|
||||
<groupId>us.myles</groupId>
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,162 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
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;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatform;
|
||||
import us.myles.ViaVersion.bungee.commands.BungeeCommand;
|
||||
import us.myles.ViaVersion.bungee.commands.BungeeCommandHandler;
|
||||
import us.myles.ViaVersion.bungee.commands.BungeeCommandSender;
|
||||
import us.myles.ViaVersion.bungee.platform.*;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.dump.PluginInfo;
|
||||
import us.myles.ViaVersion.util.GsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BungeePlugin extends Plugin implements ViaPlatform, Listener {
|
||||
private BungeeViaAPI api;
|
||||
private BungeeConfigAPI config;
|
||||
private BungeeCommandHandler commandHandler;
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
api = new BungeeViaAPI();
|
||||
config = new BungeeConfigAPI(getDataFolder());
|
||||
commandHandler = new BungeeCommandHandler();
|
||||
ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler));
|
||||
// Init platform
|
||||
Via.init(ViaManager.builder()
|
||||
.platform(this)
|
||||
.injector(new BungeeViaInjector())
|
||||
.loader(new BungeeViaLoader(this))
|
||||
.commandHandler(commandHandler)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Inject
|
||||
Via.getManager().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
return getProxy().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return getProxy().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginVersion() {
|
||||
return getDescription().getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runAsync(Runnable runnable) {
|
||||
return new BungeeTaskId(getProxy().getScheduler().runAsync(this, runnable).getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runSync(Runnable runnable) {
|
||||
return runAsync(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskId runRepeatingSync(Runnable runnable, Long ticks) {
|
||||
return new BungeeTaskId(getProxy().getScheduler().schedule(this, runnable, 0, ticks * 50, TimeUnit.MILLISECONDS).getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTask(TaskId taskId) {
|
||||
if (taskId == null) return;
|
||||
if (taskId.getObject() == null) return;
|
||||
if (taskId instanceof BungeeTaskId) {
|
||||
getProxy().getScheduler().cancel((Integer) taskId.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaCommandSender[] getOnlinePlayers() {
|
||||
ViaCommandSender[] array = new ViaCommandSender[getProxy().getPlayers().size()];
|
||||
int i = 0;
|
||||
for (ProxiedPlayer player : getProxy().getPlayers()) {
|
||||
array[i++] = new BungeeCommandSender(player);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(UUID uuid, String message) {
|
||||
getProxy().getPlayer(uuid).sendMessage(TextComponent.fromLegacyText(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean kickPlayer(UUID uuid, String message) {
|
||||
if (getProxy().getPlayer(uuid) != null) {
|
||||
getProxy().getPlayer(uuid).disconnect(TextComponent.fromLegacyText(message));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViaAPI getApi() {
|
||||
return api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BungeeConfigAPI getConf() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationProvider getConfigurationProvider() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
// Injector prints a message <3
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getDump() {
|
||||
JsonObject platformSpecific = new JsonObject();
|
||||
|
||||
List<PluginInfo> plugins = new ArrayList<>();
|
||||
for (Plugin p : ProxyServer.getInstance().getPluginManager().getPlugins())
|
||||
plugins.add(new PluginInfo(true, p.getDescription().getName(), p.getDescription().getVersion(), p.getDescription().getMain(), Arrays.asList(p.getDescription().getAuthor())));
|
||||
|
||||
platformSpecific.add("plugins", GsonUtil.getGson().toJsonTree(plugins));
|
||||
platformSpecific.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getDetectedIds()));
|
||||
return platformSpecific;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerDisconnectEvent e) {
|
||||
Via.getManager().removePortedClient(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package us.myles.ViaVersion.bungee.commands;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Command;
|
||||
import net.md_5.bungee.api.plugin.TabExecutor;
|
||||
|
||||
public class BungeeCommand extends Command implements TabExecutor {
|
||||
private final BungeeCommandHandler handler;
|
||||
|
||||
public BungeeCommand(BungeeCommandHandler handler) {
|
||||
super("viaversion", "", "viaver", "vvbungee"); // The CommandHandler will handle the permission
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender commandSender, String[] strings) {
|
||||
handler.onCommand(new BungeeCommandSender(commandSender), strings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> onTabComplete(CommandSender commandSender, String[] strings) {
|
||||
return handler.onTabComplete(new BungeeCommandSender(commandSender), strings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package us.myles.ViaVersion.bungee.commands;
|
||||
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.bungee.commands.subs.ProbeSubCmd;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
|
||||
public class BungeeCommandHandler extends ViaCommandHandler {
|
||||
public BungeeCommandHandler() {
|
||||
try {
|
||||
registerSubCommand(new ProbeSubCmd());
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Failed to register Bungee subcommands");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package us.myles.ViaVersion.bungee.commands;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BungeeCommandSender implements ViaCommandSender {
|
||||
private CommandSender sender;
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return sender.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String msg) {
|
||||
sender.sendMessage(TextComponent.fromLegacyText(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
if (sender instanceof ProxiedPlayer) {
|
||||
return ((ProxiedPlayer) sender).getUniqueId();
|
||||
} else {
|
||||
return UUID.fromString(getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return sender.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package us.myles.ViaVersion.bungee.commands.subs;
|
||||
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
import us.myles.ViaVersion.api.command.ViaSubCommand;
|
||||
import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
|
||||
public class ProbeSubCmd extends ViaSubCommand {
|
||||
@Override
|
||||
public String name() {
|
||||
return "probe";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Forces ViaVersion to scan server protocol versions " +
|
||||
(((BungeeConfigAPI) Via.getConfig()).getBungeePingInterval() == -1 ?
|
||||
"" : "(Also happens at an interval)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(ViaCommandSender sender, String[] args) {
|
||||
ProtocolDetectorService.getInstance().run();
|
||||
sendMessage(sender, "&6Started searching for protocol versions");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class BungeeChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final ChannelInitializer<Channel> original;
|
||||
private Method method;
|
||||
|
||||
public BungeeChannelInitializer(ChannelInitializer<Channel> oldInit) {
|
||||
this.original = oldInit;
|
||||
try {
|
||||
this.method = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class);
|
||||
this.method.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||
UserConnection info = new UserConnection(socketChannel);
|
||||
// init protocol
|
||||
new ProtocolPipeline(info);
|
||||
// Add originals
|
||||
this.method.invoke(this.original, socketChannel);
|
||||
// Add our transformers
|
||||
BungeeEncodeHandler encoder = new BungeeEncodeHandler(info);
|
||||
BungeeDecodeHandler decoder = new BungeeDecodeHandler(info);
|
||||
|
||||
socketChannel.pipeline().addBefore("packet-encoder", "via-encoder", encoder);
|
||||
socketChannel.pipeline().addBefore("packet-decoder", "via-decoder", decoder);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class BungeeDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
|
||||
|
||||
private final UserConnection info;
|
||||
|
||||
public BungeeDecodeHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
||||
// use transformers
|
||||
if (bytebuf.readableBytes() > 0) {
|
||||
// Ignore if pending disconnect
|
||||
if (info.isPendingDisconnect()) {
|
||||
return;
|
||||
}
|
||||
// Increment received
|
||||
boolean second = info.incrementReceived();
|
||||
// Check PPS
|
||||
if (second) {
|
||||
if (info.handlePPS())
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf newPacket = ctx.alloc().buffer();
|
||||
try {
|
||||
if (id == PacketWrapper.PASSTHROUGH_ID) {
|
||||
newPacket.writeBytes(bytebuf);
|
||||
} else {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(newPacket);
|
||||
}
|
||||
|
||||
bytebuf.clear();
|
||||
bytebuf = newPacket;
|
||||
} catch (Exception e) {
|
||||
// Clear Buffer
|
||||
bytebuf.clear();
|
||||
// Release Packet, be free!
|
||||
newPacket.release();
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
bytebuf.retain();
|
||||
}
|
||||
|
||||
out.add(bytebuf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.bungee.util.BungeePipelineUtil;
|
||||
import us.myles.ViaVersion.exception.CancelException;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
public class BungeeEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
|
||||
private final UserConnection info;
|
||||
private boolean handledCompression = false;
|
||||
|
||||
public BungeeEncodeHandler(UserConnection info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
|
||||
if (bytebuf.readableBytes() == 0) {
|
||||
throw new CancelException();
|
||||
}
|
||||
boolean needsCompress = false;
|
||||
if (!handledCompression) {
|
||||
if (ctx.pipeline().names().indexOf("compress") > ctx.pipeline().names().indexOf("via-encoder")) {
|
||||
// Need to decompress this packet due to bad order
|
||||
bytebuf = BungeePipelineUtil.decompress(ctx, bytebuf);
|
||||
ChannelHandler encoder = ctx.pipeline().get("via-decoder");
|
||||
ChannelHandler decoder = ctx.pipeline().get("via-encoder");
|
||||
ctx.pipeline().remove(encoder);
|
||||
ctx.pipeline().remove(decoder);
|
||||
ctx.pipeline().addAfter("decompress", "via-decoder", encoder);
|
||||
ctx.pipeline().addAfter("compress", "via-encoder", decoder);
|
||||
needsCompress = true;
|
||||
handledCompression = true;
|
||||
}
|
||||
}
|
||||
// Increment sent
|
||||
info.incrementSent();
|
||||
|
||||
if (info.isActive()) {
|
||||
// Handle ID
|
||||
int id = Type.VAR_INT.read(bytebuf);
|
||||
// Transform
|
||||
ByteBuf oldPacket = bytebuf.copy();
|
||||
bytebuf.clear();
|
||||
|
||||
try {
|
||||
PacketWrapper wrapper = new PacketWrapper(id, oldPacket, info);
|
||||
ProtocolInfo protInfo = info.get(ProtocolInfo.class);
|
||||
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
|
||||
wrapper.writeToBuffer(bytebuf);
|
||||
} catch (Exception e) {
|
||||
bytebuf.clear();
|
||||
throw e;
|
||||
} finally {
|
||||
oldPacket.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (needsCompress) {
|
||||
bytebuf = BungeePipelineUtil.compress(ctx, bytebuf);
|
||||
}
|
||||
out.add(bytebuf.retain());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
|
||||
super.exceptionCaught(ctx, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package us.myles.ViaVersion.bungee.handlers;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
import us.myles.ViaVersion.api.Pair;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.bungee.storage.BungeeStorage;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class BungeeServerHandler implements Listener {
|
||||
private static Method getPendingConnection;
|
||||
private static Method getHandshake;
|
||||
private static Method setProtocol;
|
||||
private static Method getEntityMap = null;
|
||||
private static Method setVersion = null;
|
||||
private static Field entityRewrite = null;
|
||||
private static Field channelWrapper = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
getPendingConnection = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getPendingConnection");
|
||||
getHandshake = Class.forName("net.md_5.bungee.connection.InitialHandler").getDeclaredMethod("getHandshake");
|
||||
setProtocol = Class.forName("net.md_5.bungee.protocol.packet.Handshake").getDeclaredMethod("setProtocolVersion", int.class);
|
||||
getEntityMap = Class.forName("net.md_5.bungee.entitymap.EntityMap").getDeclaredMethod("getEntityMap", int.class);
|
||||
setVersion = Class.forName("net.md_5.bungee.netty.ChannelWrapper").getDeclaredMethod("setVersion", int.class);
|
||||
channelWrapper = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("ch");
|
||||
channelWrapper.setAccessible(true);
|
||||
entityRewrite = Class.forName("net.md_5.bungee.UserConnection").getDeclaredField("entityRewrite");
|
||||
entityRewrite.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the handshake version every time someone connects to any server
|
||||
@EventHandler
|
||||
public void onServerConnect(ServerConnectEvent e) {
|
||||
UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId());
|
||||
if (user == null) return;
|
||||
if (!user.has(BungeeStorage.class)) {
|
||||
user.put(new BungeeStorage(user, e.getPlayer()));
|
||||
}
|
||||
|
||||
int protocolId = ProtocolDetectorService.getProtocolId(e.getTarget().getName());
|
||||
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId);
|
||||
|
||||
// Check if ViaVersion can support that version
|
||||
try {
|
||||
Object pendingConnection = getPendingConnection.invoke(e.getPlayer());
|
||||
Object handshake = getHandshake.invoke(pendingConnection);
|
||||
setProtocol.invoke(handshake, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId);
|
||||
} catch (InvocationTargetException | IllegalAccessException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onServerConnected(ServerConnectedEvent e) {
|
||||
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;
|
||||
if (user.has(BungeeStorage.class)) {
|
||||
BungeeStorage storage = user.get(BungeeStorage.class);
|
||||
ProxiedPlayer player = storage.getPlayer();
|
||||
|
||||
if (e.getServer() != null) {
|
||||
if (!e.getServer().getInfo().getName().equals(storage.getCurrentServer())) {
|
||||
String serverName = e.getServer().getInfo().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());
|
||||
}
|
||||
}
|
||||
|
||||
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 wrapper = channelWrapper.get(player);
|
||||
setVersion.invoke(wrapper, protocolId);
|
||||
|
||||
Object entityMap = getEntityMap.invoke(null, protocolId);
|
||||
entityRewrite.set(player, entityMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package us.myles.ViaVersion.bungee.listeners;
|
||||
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
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 implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
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,47 @@
|
||||
package us.myles.ViaVersion.bungee.listeners;
|
||||
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.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 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 implements Listener {
|
||||
private static Method getSettings = null;
|
||||
private static Method setMainHand = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
getSettings = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getSettings");
|
||||
setMainHand = Class.forName("net.md_5.bungee.protocol.packet.ClientSettings").getDeclaredMethod("setMainHand", int.class);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerConnect(ServerConnectEvent event) {
|
||||
// Ignore if it doesn't exist (Like BungeeCord 1.8)
|
||||
if (setMainHand == null)
|
||||
return;
|
||||
|
||||
UserConnection user = Via.getManager().getConnection(event.getPlayer().getUniqueId());
|
||||
if(user == null) return;
|
||||
|
||||
try {
|
||||
if (user.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) {
|
||||
Object settings = getSettings.invoke(event.getPlayer());
|
||||
setMainHand.invoke(settings, user.get(EntityTracker.class).getMainHand());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package us.myles.ViaVersion.bungee.listeners;
|
||||
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.update.UpdateUtil;
|
||||
|
||||
public class UpdateListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PostLoginEvent e) {
|
||||
if (e.getPlayer().hasPermission("viaversion.update")
|
||||
&& Via.getConfig().isCheckForUpdates()) {
|
||||
UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.boss.CommonBoss;
|
||||
|
||||
public class BungeeBossBar extends CommonBoss<ProxiedPlayer> {
|
||||
|
||||
public BungeeBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
super(title, health, color, style);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BossBar addPlayer(ProxiedPlayer player) {
|
||||
addPlayer(player.getUniqueId());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar addPlayers(ProxiedPlayer... players) {
|
||||
for (ProxiedPlayer p : players)
|
||||
addPlayer(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar removePlayer(ProxiedPlayer player) {
|
||||
removePlayer(player.getUniqueId());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
|
||||
import us.myles.ViaVersion.util.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class BungeeConfigAPI extends Config implements ViaVersionConfig {
|
||||
private static List<String> UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch");
|
||||
|
||||
public BungeeConfigAPI(File configFile) {
|
||||
super(new File(configFile, "config.yml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleConfig(Map<String, Object> config) {
|
||||
// Parse servers
|
||||
Map<String, Object> servers;
|
||||
if (!(config.get("bungee-servers") instanceof Map)) {
|
||||
servers = new HashMap<>();
|
||||
} else {
|
||||
servers = (Map) config.get("bungee-servers");
|
||||
}
|
||||
// Convert any bad Protocol Ids
|
||||
for (Map.Entry<String, Object> entry : new HashSet<>(servers.entrySet())) {
|
||||
if (!(entry.getValue() instanceof Integer)) {
|
||||
if (entry.getValue() instanceof String) {
|
||||
ProtocolVersion found = ProtocolVersion.getClosest((String) entry.getValue());
|
||||
if (found != null) {
|
||||
servers.put(entry.getKey(), found.getId());
|
||||
} else {
|
||||
servers.remove(entry.getKey()); // Remove!
|
||||
}
|
||||
} else {
|
||||
servers.remove(entry.getKey()); // Remove!
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ensure default exists
|
||||
if (!servers.containsKey("default")) {
|
||||
servers.put("default", BungeeVersionProvider.getLowestSupportedVersion());
|
||||
}
|
||||
// Put back
|
||||
config.put("bungee-servers", servers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUnsupportedOptions() {
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
public boolean isCheckForUpdates() {
|
||||
return getBoolean("checkforupdates", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventCollision() {
|
||||
return getBoolean("prevent-collision", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNewEffectIndicator() {
|
||||
return getBoolean("use-new-effect-indicator", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowNewDeathMessages() {
|
||||
return getBoolean("use-new-deathmessages", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressMetadataErrors() {
|
||||
return getBoolean("suppress-metadata-errors", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShieldBlocking() {
|
||||
return getBoolean("shield-blocking", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHologramPatch() {
|
||||
return getBoolean("hologram-patch", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean 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 List<Integer> getBlockedProtocols() {
|
||||
return getIntegerList("block-protocols");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBlockedDisconnectMsg() {
|
||||
return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReloadDisconnectMsg() {
|
||||
return getString("reload-disconnect-msg", "Server reload, please rejoin!");
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the interval for checking servers via ping
|
||||
* -1 for disabled
|
||||
*
|
||||
* @return Ping interval in seconds
|
||||
*/
|
||||
public int getBungeePingInterval() {
|
||||
return getInt("bungee-ping-interval", 60);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the bungee ping be saved to the config on change.
|
||||
*
|
||||
* @return True if it should save
|
||||
*/
|
||||
public boolean isBungeePingSave() {
|
||||
return getBoolean("bungee-ping-save", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the listed server protocols in the config.
|
||||
* default will be listed as default.
|
||||
*
|
||||
* @return Map of String, Integer
|
||||
*/
|
||||
public Map<String, Integer> getBungeeServerProtocols() {
|
||||
return get("bungee-servers", Map.class, new HashMap<>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.api.platform.TaskId;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class BungeeTaskId implements TaskId {
|
||||
private Integer object;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.NonNull;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaAPI;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BungeeViaAPI implements ViaAPI<ProxiedPlayer> {
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull ProxiedPlayer player) {
|
||||
if (!isPorted(player.getUniqueId()))
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerVersion(@NonNull UUID uuid) {
|
||||
if (!isPorted(uuid))
|
||||
return ProtocolRegistry.SERVER_PROTOCOL;
|
||||
return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPorted(UUID playerUUID) {
|
||||
return getPortedPlayers().containsKey(playerUUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return Via.getPlatform().getPluginVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException {
|
||||
if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!");
|
||||
UserConnection ci = getPortedPlayers().get(uuid);
|
||||
ci.sendRawPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawPacket(ProxiedPlayer player, ByteBuf packet) throws IllegalArgumentException {
|
||||
sendRawPacket(player.getUniqueId(), packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, BossColor color, BossStyle style) {
|
||||
return new BungeeBossBar(title, 1F, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) {
|
||||
return new BungeeBossBar(title, health, color, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SortedSet<Integer> getSupportedVersions() {
|
||||
SortedSet<Integer> outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions());
|
||||
outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols());
|
||||
|
||||
return outputSet;
|
||||
}
|
||||
|
||||
public Map<UUID, UserConnection> getPortedPlayers() {
|
||||
return Via.getManager().getPortedPlayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces ViaVersion to probe a server
|
||||
*
|
||||
* @param serverInfo The serverinfo to probe
|
||||
*/
|
||||
public void probeServer(ServerInfo serverInfo) {
|
||||
ProtocolDetectorService.probeServer(serverInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.bungee.handlers.BungeeChannelInitializer;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
public class BungeeViaInjector implements ViaInjector {
|
||||
@Override
|
||||
public void inject() throws Exception {
|
||||
try {
|
||||
try {
|
||||
|
||||
Class<?> pipelineUtils = Class.forName("net.md_5.bungee.netty.PipelineUtils");
|
||||
Field field = pipelineUtils.getDeclaredField("SERVER_CHILD");
|
||||
field.setAccessible(true);
|
||||
// Remove any final stuff
|
||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
modifiersField.setAccessible(true);
|
||||
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
|
||||
BungeeChannelInitializer newInit = new BungeeChannelInitializer((ChannelInitializer<Channel>) field.get(null));
|
||||
field.set(null, newInit);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new Exception("Unable to find core component 'childHandler', please check your plugins. issue: ");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Via.getPlatform().getLogger().severe("Unable to inject ViaVersion, please post these details on our GitHub and ensure you're using a compatible server version.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninject() {
|
||||
Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Bungee without a reboot!");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getServerProtocolVersion() throws Exception {
|
||||
return (int) ReflectionUtil.getStatic(Class.forName("net.md_5.bungee.protocol.ProtocolConstants"), "SUPPORTED_VERSION_IDS", List.class).get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoderName() {
|
||||
return "via-encoder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDecoderName() {
|
||||
return "via-decoder";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package us.myles.ViaVersion.bungee.platform;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import us.myles.ViaVersion.BungeePlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
|
||||
import us.myles.ViaVersion.bungee.handlers.BungeeServerHandler;
|
||||
import us.myles.ViaVersion.bungee.listeners.ElytraPatch;
|
||||
import us.myles.ViaVersion.bungee.listeners.MainHandPatch;
|
||||
import us.myles.ViaVersion.bungee.listeners.UpdateListener;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeEntityIdProvider;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeMovementTransmitter;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
|
||||
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
|
||||
import us.myles.ViaVersion.protocols.base.VersionProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.EntityIdProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class BungeeViaLoader implements ViaPlatformLoader {
|
||||
private BungeePlugin plugin;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
// Listeners
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, plugin);
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, new UpdateListener());
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, new BungeeServerHandler());
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, new MainHandPatch());
|
||||
ProxyServer.getInstance().getPluginManager().registerListener(plugin, new ElytraPatch());
|
||||
|
||||
// Providers
|
||||
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BungeeMovementTransmitter());
|
||||
Via.getManager().getProviders().use(VersionProvider.class, new BungeeVersionProvider());
|
||||
Via.getManager().getProviders().use(EntityIdProvider.class, new BungeeEntityIdProvider());
|
||||
if (plugin.getConf().getBungeePingInterval() > 0) {
|
||||
plugin.getProxy().getScheduler().schedule(plugin, new ProtocolDetectorService(plugin), 0, plugin.getConf().getBungeePingInterval(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package us.myles.ViaVersion.bungee.providers;
|
||||
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.bungee.storage.BungeeStorage;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.EntityIdProvider;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class BungeeEntityIdProvider extends EntityIdProvider {
|
||||
private static Method getClientEntityId;
|
||||
|
||||
static {
|
||||
try {
|
||||
getClientEntityId = Class.forName("net.md_5.bungee.UserConnection").getDeclaredMethod("getClientEntityId");
|
||||
} catch (NoSuchMethodException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityId(UserConnection user) throws Exception {
|
||||
BungeeStorage storage = user.get(BungeeStorage.class);
|
||||
ProxiedPlayer player = storage.getPlayer();
|
||||
|
||||
return (int) getClientEntityId.invoke(player);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package us.myles.ViaVersion.bungee.providers;
|
||||
|
||||
import us.myles.ViaVersion.api.PacketWrapper;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker;
|
||||
|
||||
public class BungeeMovementTransmitter extends MovementTransmitterProvider {
|
||||
@Override
|
||||
public Object getFlyingPacket() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroundPacket() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void sendPlayer(UserConnection userConnection) {
|
||||
if (userConnection.get(ProtocolInfo.class).getState() == State.PLAY) {
|
||||
PacketWrapper wrapper = new PacketWrapper(0x03, null, userConnection);
|
||||
wrapper.write(Type.BOOLEAN, userConnection.get(MovementTracker.class).isGround());
|
||||
try {
|
||||
wrapper.sendToServer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// PlayerPackets will increment idle
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package us.myles.ViaVersion.bungee.providers;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
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.base.VersionProvider;
|
||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BungeeVersionProvider extends VersionProvider {
|
||||
private static Class<?> ref;
|
||||
|
||||
static {
|
||||
try {
|
||||
ref = Class.forName("net.md_5.bungee.protocol.ProtocolConstants");
|
||||
} catch (Exception e) {
|
||||
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)
|
||||
List<Integer> list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class);
|
||||
|
||||
ProtocolInfo info = user.get(ProtocolInfo.class);
|
||||
|
||||
// Bungee supports it
|
||||
if (list.contains(info.getProtocolVersion()))
|
||||
return info.getProtocolVersion();
|
||||
|
||||
// Older than bungee supports, get the lowest version
|
||||
if (info.getProtocolVersion() < list.get(0)) {
|
||||
return getLowestSupportedVersion();
|
||||
}
|
||||
|
||||
// Loop through all protocols to get the closest protocol id that bungee supports
|
||||
for (Integer protocol : Lists.reverse(list)) {
|
||||
if (info.getProtocolVersion() > protocol)
|
||||
return protocol;
|
||||
}
|
||||
|
||||
Via.getPlatform().getLogger().severe("Panic, no protocol id found for " + info.getProtocolVersion());
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
public static int getLowestSupportedVersion() {
|
||||
List<Integer> list;
|
||||
try {
|
||||
list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSION_IDS", List.class);
|
||||
return list.get(0);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Fallback
|
||||
return ProxyServer.getInstance().getProtocolVersion();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package us.myles.ViaVersion.bungee.service;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.Callback;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import us.myles.ViaVersion.BungeePlugin;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI;
|
||||
import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider;
|
||||
|
||||
import 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<>();
|
||||
private BungeePlugin plugin;
|
||||
@Getter
|
||||
private static ProtocolDetectorService instance;
|
||||
|
||||
public ProtocolDetectorService(BungeePlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static Integer getProtocolId(String serverName) {
|
||||
// Step 1. Check Config
|
||||
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
|
||||
if (servers.containsKey(serverName)) {
|
||||
return servers.get(serverName);
|
||||
}
|
||||
// Step 2. Check Detected
|
||||
if (detectedProtocolIds.containsKey(serverName)) {
|
||||
return detectedProtocolIds.get(serverName);
|
||||
}
|
||||
// Step 3. Use Default
|
||||
if (servers.containsKey("default")) {
|
||||
return servers.get("default");
|
||||
}
|
||||
// Step 4: Use bungee lowest supported... *cries*
|
||||
return BungeeVersionProvider.getLowestSupportedVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (final Map.Entry<String, ServerInfo> lists : plugin.getProxy().getServers().entrySet()) {
|
||||
probeServer(lists.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static void probeServer(final ServerInfo serverInfo) {
|
||||
final String key = serverInfo.getName();
|
||||
serverInfo.ping(new Callback<ServerPing>() {
|
||||
@Override
|
||||
public void done(ServerPing serverPing, Throwable throwable) {
|
||||
if (throwable == null) {
|
||||
detectedProtocolIds.put(key, serverPing.getVersion().getProtocol());
|
||||
if (((BungeeConfigAPI) Via.getConfig()).isBungeePingSave()) {
|
||||
Map<String, Integer> servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols();
|
||||
if (servers.containsKey(key)) {
|
||||
if (servers.get(key) == serverPing.getVersion().getProtocol()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Save Server
|
||||
servers.put(key, serverPing.getVersion().getProtocol());
|
||||
// Save
|
||||
Via.getPlatform().getConfigurationProvider().saveConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Map<String, Integer> getDetectedIds() {
|
||||
return new HashMap<>(detectedProtocolIds);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package us.myles.ViaVersion.bungee.storage;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import us.myles.ViaVersion.api.data.StoredObject;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BungeeStorage extends StoredObject {
|
||||
private ProxiedPlayer player;
|
||||
private String currentServer;
|
||||
|
||||
public BungeeStorage(UserConnection user, ProxiedPlayer player) {
|
||||
super(user);
|
||||
this.player = player;
|
||||
this.currentServer = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package us.myles.ViaVersion.bungee.util;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BungeePipelineUtil {
|
||||
private static Method DECODE_METHOD;
|
||||
private static Method ENCODE_METHOD;
|
||||
|
||||
static {
|
||||
try {
|
||||
DECODE_METHOD = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class);
|
||||
DECODE_METHOD.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
ENCODE_METHOD = MessageToByteEncoder.class.getDeclaredMethod("encode", ChannelHandlerContext.class, Object.class, ByteBuf.class);
|
||||
ENCODE_METHOD.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Object> callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
|
||||
List<Object> output = new ArrayList<>();
|
||||
try {
|
||||
BungeePipelineUtil.DECODE_METHOD.invoke(decoder, ctx, input, output);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static ByteBuf callEncode(MessageToByteEncoder encoder, ChannelHandlerContext ctx, ByteBuf input) throws InvocationTargetException {
|
||||
ByteBuf output = ctx.alloc().buffer();
|
||||
try {
|
||||
BungeePipelineUtil.ENCODE_METHOD.invoke(encoder, ctx, input, output);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
public static ByteBuf decompress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
|
||||
try {
|
||||
return (ByteBuf) callDecode((MessageToMessageDecoder) ctx.pipeline().get("decompress"), ctx.pipeline().context("decompress"), bytebuf).get(0);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
}
|
||||
|
||||
public static ByteBuf compress(ChannelHandlerContext ctx, ByteBuf bytebuf) {
|
||||
try {
|
||||
return callEncode((MessageToByteEncoder) ctx.pipeline().get("compress"), ctx.pipeline().context("compress"), bytebuf);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return ctx.alloc().buffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
name: ViaVersion
|
||||
main: us.myles.ViaVersion.BungeePlugin
|
||||
description: ${project.description}
|
||||
author: _MylesC, Matsv
|
||||
version: ${project.version}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
machine:
|
||||
java:
|
||||
version: oraclejdk7
|
||||
version: oraclejdk8
|
||||
general:
|
||||
artifacts:
|
||||
- "target/*.jar"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>viaversion-parent</artifactId>
|
||||
<groupId>us.myles</groupId>
|
||||
<version>1.0.2</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>viaversion-common</artifactId>
|
||||
<dependencies>
|
||||
<!-- Snake YAML -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.18-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,117 @@
|
||||
package us.myles.ViaVersion;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.platform.ViaInjector;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatform;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatformLoader;
|
||||
import us.myles.ViaVersion.api.platform.providers.ViaProviders;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.update.UpdateUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Getter
|
||||
public class ViaManager {
|
||||
private final Map<UUID, UserConnection> portedPlayers = new ConcurrentHashMap<>();
|
||||
private ViaPlatform platform;
|
||||
private ViaProviders providers = new ViaProviders();
|
||||
@Setter
|
||||
private boolean debug = false;
|
||||
// Internals
|
||||
private ViaInjector injector;
|
||||
private ViaCommandHandler commandHandler;
|
||||
private ViaPlatformLoader loader;
|
||||
|
||||
@Builder
|
||||
public ViaManager(ViaPlatform platform, ViaInjector injector, ViaCommandHandler commandHandler, ViaPlatformLoader loader) {
|
||||
this.platform = platform;
|
||||
this.injector = injector;
|
||||
this.commandHandler = commandHandler;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (System.getProperty("ViaVersion") != null) {
|
||||
// Reload?
|
||||
platform.onReload();
|
||||
}
|
||||
// Check for updates
|
||||
if (platform.getConf().isCheckForUpdates())
|
||||
UpdateUtil.sendUpdateMessage();
|
||||
// Inject
|
||||
try {
|
||||
injector.inject();
|
||||
} catch (Exception e) {
|
||||
getPlatform().getLogger().severe("ViaVersion failed to inject:");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
// Mark as injected
|
||||
System.setProperty("ViaVersion", getPlatform().getPluginVersion());
|
||||
// If successful
|
||||
platform.runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onServerLoaded();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void onServerLoaded() {
|
||||
// Load Server Protocol
|
||||
try {
|
||||
ProtocolRegistry.SERVER_PROTOCOL = injector.getServerProtocolVersion();
|
||||
} catch (Exception e) {
|
||||
getPlatform().getLogger().severe("ViaVersion failed to get the server protocol!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Check if there are any pipes to this version
|
||||
if (ProtocolRegistry.SERVER_PROTOCOL != -1) {
|
||||
getPlatform().getLogger().info("ViaVersion detected server version: " + ProtocolVersion.getProtocol(ProtocolRegistry.SERVER_PROTOCOL));
|
||||
if (!ProtocolRegistry.isWorkingPipe()) {
|
||||
getPlatform().getLogger().warning("ViaVersion does not have any compatible versions for this server version, please read our resource page carefully.");
|
||||
}
|
||||
}
|
||||
// Load Listeners / Tasks
|
||||
ProtocolRegistry.onServerLoaded();
|
||||
|
||||
// Load Platform
|
||||
loader.load();
|
||||
|
||||
// Refresh Versions
|
||||
ProtocolRegistry.refreshVersions();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
// Uninject
|
||||
getPlatform().getLogger().info("ViaVersion is disabling, if this is a reload and you experience issues consider rebooting.");
|
||||
try {
|
||||
injector.uninject();
|
||||
} catch (Exception e) {
|
||||
getPlatform().getLogger().severe("ViaVersion failed to uninject:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addPortedClient(UserConnection info) {
|
||||
portedPlayers.put(info.get(ProtocolInfo.class).getUuid(), info);
|
||||
}
|
||||
|
||||
public void removePortedClient(UUID clientID) {
|
||||
portedPlayers.remove(clientID);
|
||||
}
|
||||
|
||||
public UserConnection getConnection(UUID playerUUID) {
|
||||
return portedPlayers.get(playerUUID);
|
||||
}
|
||||
|
||||
}
|
||||
+65
-37
@@ -12,11 +12,9 @@ import us.myles.ViaVersion.api.remapper.ValueCreator;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
import us.myles.ViaVersion.api.type.TypeConverter;
|
||||
import us.myles.ViaVersion.exception.InformativeException;
|
||||
import us.myles.ViaVersion.handlers.ViaDecodeHandler;
|
||||
import us.myles.ViaVersion.packets.Direction;
|
||||
import us.myles.ViaVersion.packets.State;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
import us.myles.ViaVersion.util.PipelineUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -25,14 +23,16 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class PacketWrapper {
|
||||
public static final int PASSTHROUGH_ID = 1000;
|
||||
|
||||
private final ByteBuf inputBuffer;
|
||||
private final UserConnection userConnection;
|
||||
private boolean send = true;
|
||||
@Setter
|
||||
@Getter
|
||||
private int id = -1;
|
||||
private LinkedList<Pair<Type, Object>> readableObjects = new LinkedList<>();
|
||||
private List<Pair<Type, Object>> packetValues = new ArrayList<>();
|
||||
private final LinkedList<Pair<Type, Object>> readableObjects = new LinkedList<>();
|
||||
private final List<Pair<Type, Object>> packetValues = new ArrayList<>();
|
||||
|
||||
public PacketWrapper(int packetID, ByteBuf inputBuffer, UserConnection userConnection) {
|
||||
this.id = packetID;
|
||||
@@ -176,7 +176,7 @@ public class PacketWrapper {
|
||||
if (type instanceof TypeConverter) {
|
||||
value = (T) ((TypeConverter) type).from(value);
|
||||
} else {
|
||||
System.out.println("Possible type mismatch: " + value.getClass().getName() + " -> " + type.getOutputClass());
|
||||
Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + type.getOutputClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class PacketWrapper {
|
||||
if (packetValue.getKey() instanceof TypeConverter) {
|
||||
value = ((TypeConverter) packetValue.getKey()).from(value);
|
||||
} else {
|
||||
System.out.println("Possible type mismatch: " + value.getClass().getName() + " -> " + packetValue.getKey().getOutputClass());
|
||||
Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + packetValue.getKey().getOutputClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,31 +282,58 @@ public class PacketWrapper {
|
||||
* @param skipCurrentPipeline - Skip the current pipeline
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
public ChannelFuture send(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline) throws Exception {
|
||||
public void send(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline) throws Exception {
|
||||
send(packetProtocol, skipCurrentPipeline, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send this packet to the associated user.
|
||||
* Be careful not to send packets twice.
|
||||
* (Sends it after current)
|
||||
*
|
||||
* @param packetProtocol - The protocol version of the packet.
|
||||
* @param skipCurrentPipeline - Skip the current pipeline
|
||||
* @param currentThread - Run in the same thread
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
public void send(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline, boolean currentThread) throws Exception {
|
||||
if (!isCancelled()) {
|
||||
// Apply current pipeline
|
||||
List<Protocol> protocols = new ArrayList<>(user().get(ProtocolInfo.class).getPipeline().pipes());
|
||||
// Other way if outgoing
|
||||
Collections.reverse(protocols);
|
||||
int index = 0;
|
||||
for (int i = 0; i < protocols.size(); i++) {
|
||||
if (protocols.get(i).getClass().equals(packetProtocol)) {
|
||||
index = skipCurrentPipeline ? (i + 1) : (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset reader before we start
|
||||
resetReader();
|
||||
|
||||
// Apply other protocols
|
||||
apply(Direction.OUTGOING, user().get(ProtocolInfo.class).getState(), index, protocols);
|
||||
// Send
|
||||
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
|
||||
writeToBuffer(output);
|
||||
return user().sendRawPacketFuture(output);
|
||||
ByteBuf output = constructPacket(packetProtocol, skipCurrentPipeline);
|
||||
user().sendRawPacket(output, currentThread);
|
||||
}
|
||||
return user().getChannel().newFailedFuture(new Exception("Cancelled packet"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Let the packet go through the protocol pipes and write it to ByteBuf
|
||||
*
|
||||
* @param packetProtocol - The protocol version of the packet.
|
||||
* @param skipCurrentPipeline - Skip the current pipeline
|
||||
* @return Packet buffer
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
private ByteBuf constructPacket(Class<? extends Protocol> packetProtocol, boolean skipCurrentPipeline) throws Exception {
|
||||
// Apply current pipeline
|
||||
List<Protocol> protocols = new ArrayList<>(user().get(ProtocolInfo.class).getPipeline().pipes());
|
||||
// Other way if outgoing
|
||||
Collections.reverse(protocols);
|
||||
int index = 0;
|
||||
for (int i = 0; i < protocols.size(); i++) {
|
||||
if (protocols.get(i).getClass().equals(packetProtocol)) {
|
||||
index = skipCurrentPipeline ? (i + 1) : (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset reader before we start
|
||||
resetReader();
|
||||
|
||||
// Apply other protocols
|
||||
apply(Direction.OUTGOING, user().get(ProtocolInfo.class).getState(), index, protocols);
|
||||
// Send
|
||||
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
|
||||
writeToBuffer(output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,15 +359,18 @@ public class PacketWrapper {
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
public ChannelFuture sendFuture(Class<? extends Protocol> packetProtocol) throws Exception {
|
||||
return send(packetProtocol, true);
|
||||
if (!isCancelled()) {
|
||||
ByteBuf output = constructPacket(packetProtocol, true);
|
||||
return user().sendRawPacketFuture(output);
|
||||
}
|
||||
return user().getChannel().newFailedFuture(new Exception("Cancelled packet"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send this packet to the associated user.
|
||||
* Be careful not to send packets twice.
|
||||
* (Sends it after current)
|
||||
* <br />
|
||||
* <b>This method is no longer used, it's favoured to use send(Protocol) as it will handle the pipeline properly.</b>
|
||||
* <b>This method is no longer used, it's favoured to use {@link #send(Class)} as it will handle the pipeline properly.</b>
|
||||
*
|
||||
* @throws Exception if it fails to write
|
||||
*/
|
||||
@@ -386,7 +416,7 @@ public class PacketWrapper {
|
||||
* @param index The index to start from
|
||||
* @param pipeline The pipeline
|
||||
* @return The current packetwrapper
|
||||
* @throws Exception
|
||||
* @throws Exception If it fails to transform a packet, exception will be thrown
|
||||
*/
|
||||
public PacketWrapper apply(Direction direction, State state, int index, List<Protocol> pipeline) throws Exception {
|
||||
for (int i = index; i < pipeline.size(); i++) { // Copy to prevent from removal.
|
||||
@@ -437,18 +467,16 @@ public class PacketWrapper {
|
||||
|
||||
/**
|
||||
* Send the current packet to the server.
|
||||
* (Ensure the ID is suitable for the server version)
|
||||
* (Ensure the ID is suitable for viaversion)
|
||||
*
|
||||
* @throws Exception If it failed to write
|
||||
*/
|
||||
public void sendToServer() throws Exception {
|
||||
if (!isCancelled()) {
|
||||
ByteBuf output = inputBuffer == null ? Unpooled.buffer() : inputBuffer.alloc().buffer();
|
||||
Type.VAR_INT.write(output, ViaDecodeHandler.PASSTHROUGH_ID); // Pass through
|
||||
|
||||
writeToBuffer(output);
|
||||
|
||||
PipelineUtil.getContextBefore("decompress", user().getChannel().pipeline()).fireChannelRead(output);
|
||||
user().getChannel().pipeline().context(Via.getManager().getInjector().getDecoderName()).fireChannelRead(output);
|
||||
}
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,45 @@
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.ViaManager;
|
||||
import us.myles.ViaVersion.api.platform.ViaPlatform;
|
||||
|
||||
public class Via {
|
||||
@Getter
|
||||
private static ViaPlatform platform;
|
||||
@Getter
|
||||
private static ViaManager manager;
|
||||
|
||||
/**
|
||||
* Register the ViaManager associated with the platform.
|
||||
*
|
||||
* @param viaManager The ViaManager
|
||||
*/
|
||||
public static void init(ViaManager viaManager) {
|
||||
Preconditions.checkArgument(manager == null, "ViaManager is already set");
|
||||
|
||||
Via.platform = viaManager.getPlatform();
|
||||
Via.manager = viaManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the API associated with the current platform.
|
||||
*
|
||||
* @return API instance
|
||||
*/
|
||||
public static ViaAPI getAPI() {
|
||||
Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform");
|
||||
return Via.platform.getApi();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config associated with the current platform.
|
||||
*
|
||||
* @return Config instance
|
||||
*/
|
||||
public static ViaVersionConfig getConfig() {
|
||||
Preconditions.checkArgument(platform != null, "ViaVersion has not loaded the Platform");
|
||||
return Via.platform.getConf();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import us.myles.ViaVersion.api.boss.BossBar;
|
||||
import us.myles.ViaVersion.api.boss.BossColor;
|
||||
import us.myles.ViaVersion.api.boss.BossStyle;
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents the ViaAPI
|
||||
*
|
||||
* @param <T> The player type for the specific platform, for bukkit it's {@code ViaAPI<Player>}
|
||||
*/
|
||||
public interface ViaAPI<T> {
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
* Will also retrieve version from ProtocolSupport if it's being used.
|
||||
*
|
||||
* @param player Platform player object, eg. Bukkit this is Player
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(T player);
|
||||
|
||||
/**
|
||||
* Get protocol number from a player
|
||||
*
|
||||
* @param uuid UUID of a player
|
||||
* @return Protocol ID, For example (47=1.8-1.8.8, 107=1.9, 108=1.9.1)
|
||||
*/
|
||||
int getPlayerVersion(UUID uuid);
|
||||
|
||||
/**
|
||||
* Is player using 1.9?
|
||||
*
|
||||
* @param playerUUID UUID of a player
|
||||
* @return True if the client is on 1.9
|
||||
* @deprecated As of 0.9.9, because all players are ported use {@link #getPlayerVersion(UUID)}
|
||||
*/
|
||||
@Deprecated
|
||||
boolean isPorted(UUID playerUUID);
|
||||
|
||||
/**
|
||||
* Get the version of the plugin
|
||||
*
|
||||
* @return Plugin version
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param player Platform player object, eg. Bukkit this is Player
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(T player, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player (Use new IDs)
|
||||
*
|
||||
* @param uuid The uuid from the player to send packet
|
||||
* @param packet The packet, you need a VarInt ID then the packet contents.
|
||||
* @throws IllegalArgumentException If not on 1.9 throws IllegalArg
|
||||
*/
|
||||
void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return BossBar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Create a new bossbar instance
|
||||
*
|
||||
* @param title The title
|
||||
* @param health Number between 0 and 1
|
||||
* @param color The color
|
||||
* @param style The style
|
||||
* @return BossBar instance
|
||||
*/
|
||||
BossBar createBossBar(String title, float health, BossColor color, BossStyle style);
|
||||
|
||||
/**
|
||||
* Get the supported protocol versions
|
||||
* This method removes any blocked protocol versions.
|
||||
*
|
||||
* @return a list of protocol versions
|
||||
* @see ProtocolRegistry#getSupportedVersions() for full list.
|
||||
*/
|
||||
SortedSet<Integer> getSupportedVersions();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package us.myles.ViaVersion.api;
|
||||
|
||||
import lombok.*;
|
||||
import us.myles.ViaVersion.api.data.UserConnection;
|
||||
import us.myles.ViaVersion.api.protocol.Protocol;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
@Setter(AccessLevel.PROTECTED)
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ViaListener {
|
||||
private final Class<? extends Protocol> requiredPipeline;
|
||||
private boolean registered = false;
|
||||
|
||||
/**
|
||||
* Get the UserConnection from an UUID
|
||||
*
|
||||
* @param uuid UUID object
|
||||
* @return The UserConnection
|
||||
*/
|
||||
protected UserConnection getUserConnection(@NonNull UUID uuid) {
|
||||
return Via.getManager().getConnection(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the UUID is on the selected pipe
|
||||
*
|
||||
* @param uuid UUID Object
|
||||
* @return True if on pipe
|
||||
*/
|
||||
protected boolean isOnPipe(UUID uuid) {
|
||||
UserConnection userConnection = getUserConnection(uuid);
|
||||
return userConnection != null &&
|
||||
userConnection.get(ProtocolInfo.class).getPipeline().contains(requiredPipeline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the event
|
||||
*/
|
||||
public abstract void register();
|
||||
}
|
||||
+23
-8
@@ -19,14 +19,14 @@ public interface ViaVersionConfig {
|
||||
boolean isPreventCollision();
|
||||
|
||||
/**
|
||||
* Get if 1.9 & 1.10 clients are shown the new effect indicator in the top-right corner
|
||||
* Get if 1.9 & 1.10 clients are shown the new effect indicator in the top-right corner
|
||||
*
|
||||
* @return true if the using of the new effect indicator is enabled
|
||||
*/
|
||||
boolean isNewEffectIndicator();
|
||||
|
||||
/**
|
||||
* Get if 1.9 & 1.10 clients are shown the new death message on the death screen
|
||||
* Get if 1.9 & 1.10 clients are shown the new death message on the death screen
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
@@ -40,28 +40,35 @@ public interface ViaVersionConfig {
|
||||
boolean isSuppressMetadataErrors();
|
||||
|
||||
/**
|
||||
* Get if blocking in 1.9 & 1.10 appears as a player holding a shield
|
||||
* Get if blocking in 1.9 & 1.10 appears as a player holding a shield
|
||||
*
|
||||
* @return true if shield blocking is enabled
|
||||
*/
|
||||
boolean isShieldBlocking();
|
||||
|
||||
/**
|
||||
* Get if armor stand positions are fixed so holograms show up at the correct height in 1.9 & 1.10
|
||||
* Get if armor stand positions are fixed so holograms show up at the correct height in 1.9 & 1.10
|
||||
*
|
||||
* @return true if hologram patching is enabled
|
||||
*/
|
||||
boolean isHologramPatch();
|
||||
|
||||
/**
|
||||
* Get if boss bars are fixed for 1.9 & 1.10 clients
|
||||
* Get if the 1.11 piston animation patch is enabled
|
||||
*
|
||||
* @return true if the piston patch is enabled.
|
||||
*/
|
||||
boolean isPistonAnimationPatch();
|
||||
|
||||
/**
|
||||
* Get if boss bars are fixed for 1.9 & 1.10 clients
|
||||
*
|
||||
* @return true if boss bar patching is enabled
|
||||
*/
|
||||
boolean isBossbarPatch();
|
||||
|
||||
/**
|
||||
* Get if the boss bars for 1.9 & 1.10 clients are being stopped from flickering
|
||||
* Get if the boss bars for 1.9 & 1.10 clients are being stopped from flickering
|
||||
* This will keep all boss bars on 100% (not recommended)
|
||||
*
|
||||
* @return true if boss bar anti flickering is enabled
|
||||
@@ -108,7 +115,7 @@ public interface ViaVersionConfig {
|
||||
/**
|
||||
* Get the kick message sent if the user hits the max packets per second.
|
||||
*
|
||||
* @return Kick message, with colour codes using '&'
|
||||
* @return Kick message, with colour codes using '&amp;'
|
||||
*/
|
||||
String getMaxPPSKickMessage();
|
||||
|
||||
@@ -136,7 +143,7 @@ public interface ViaVersionConfig {
|
||||
/**
|
||||
* Get the kick message sent if the user goes over the warnings in the interval
|
||||
*
|
||||
* @return Kick message, with colour codes using '&'
|
||||
* @return Kick message, with colour codes using '&amp;'
|
||||
*/
|
||||
String getMaxWarningsKickMessage();
|
||||
|
||||
@@ -209,4 +216,12 @@ public interface ViaVersionConfig {
|
||||
* @return Disconnect message
|
||||
*/
|
||||
String getBlockedDisconnectMsg();
|
||||
|
||||
/**
|
||||
* Get the message sent to players being kicked on reload.
|
||||
* Players are kicked to stop the server crashing
|
||||
*
|
||||
* @return Disconnect message
|
||||
*/
|
||||
String getReloadDisconnectMsg();
|
||||
}
|
||||
+41
-21
@@ -1,17 +1,17 @@
|
||||
package us.myles.ViaVersion.api.boss;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface BossBar {
|
||||
public abstract class BossBar<T> {
|
||||
/**
|
||||
* Get the current title
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
String getTitle();
|
||||
public abstract String getTitle();
|
||||
|
||||
/**
|
||||
* Change the title
|
||||
@@ -19,14 +19,14 @@ public interface BossBar {
|
||||
* @param title Title can be in either JSON or just text
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar setTitle(String title);
|
||||
public abstract BossBar setTitle(String title);
|
||||
|
||||
/**
|
||||
* Get the health
|
||||
*
|
||||
* @return float between 0F - 1F
|
||||
*/
|
||||
float getHealth();
|
||||
public abstract float getHealth();
|
||||
|
||||
/**
|
||||
* Change the health
|
||||
@@ -34,14 +34,14 @@ public interface BossBar {
|
||||
* @param health this float has to be between 0F - 1F
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar setHealth(float health);
|
||||
public abstract BossBar setHealth(float health);
|
||||
|
||||
/**
|
||||
* Get the bossbar color
|
||||
*
|
||||
* @return The colour
|
||||
*/
|
||||
BossColor getColor();
|
||||
public abstract BossColor getColor();
|
||||
|
||||
/**
|
||||
* Yay colors!
|
||||
@@ -49,14 +49,14 @@ public interface BossBar {
|
||||
* @param color Whatever color you want!
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar setColor(BossColor color);
|
||||
public abstract BossBar setColor(BossColor color);
|
||||
|
||||
/**
|
||||
* Get the bosbar style
|
||||
*
|
||||
* @return BossStyle
|
||||
*/
|
||||
BossStyle getStyle();
|
||||
public abstract BossStyle getStyle();
|
||||
|
||||
/**
|
||||
* Change the bosbar style
|
||||
@@ -64,15 +64,19 @@ public interface BossBar {
|
||||
* @param style BossStyle
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar setStyle(BossStyle style);
|
||||
public abstract BossBar setStyle(BossStyle style);
|
||||
|
||||
/**
|
||||
* Show the bossbar to a player.
|
||||
*
|
||||
* @param player The player
|
||||
* @return The BossBar object
|
||||
* @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)}
|
||||
*/
|
||||
BossBar addPlayer(Player player);
|
||||
@Deprecated
|
||||
public BossBar addPlayer(T player) {
|
||||
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the bossbar to a player (uuid)
|
||||
@@ -80,23 +84,39 @@ public interface BossBar {
|
||||
* @param player uuid of the player
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar addPlayer(UUID player);
|
||||
public abstract BossBar addPlayer(UUID player);
|
||||
|
||||
/**
|
||||
* add multiple players
|
||||
*
|
||||
* @param players list of players
|
||||
* @return The BossBar object
|
||||
* @deprecated Deprecated use UUID's instead of Player objects {@link #addPlayer(UUID)}
|
||||
*/
|
||||
BossBar addPlayers(Player... players);
|
||||
@Deprecated
|
||||
public BossBar addPlayers(T... players) {
|
||||
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the bossbar from a player
|
||||
*
|
||||
* @param player The player
|
||||
* @return The BossBar object
|
||||
* @deprecated Deprecated use UUID's instead of Player objects {@link #removePlayer(UUID)}
|
||||
*/
|
||||
BossBar removePlayer(Player player);
|
||||
@Deprecated
|
||||
public BossBar removePlayer(T player) {
|
||||
throw new UnsupportedOperationException("This method is not implemented for the platform " + Via.getPlatform().getPlatformName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the bossbar from a player
|
||||
*
|
||||
* @param uuid The platers YYUD
|
||||
* @return The BossBar object
|
||||
*/
|
||||
public abstract BossBar removePlayer(UUID uuid);
|
||||
|
||||
/**
|
||||
* Add flags
|
||||
@@ -104,7 +124,7 @@ public interface BossBar {
|
||||
* @param flag The flag to add
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar addFlag(BossFlag flag);
|
||||
public abstract BossBar addFlag(BossFlag flag);
|
||||
|
||||
/**
|
||||
* Remove flags.
|
||||
@@ -112,39 +132,39 @@ public interface BossBar {
|
||||
* @param flag The flag to remove
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar removeFlag(BossFlag flag);
|
||||
public abstract BossBar removeFlag(BossFlag flag);
|
||||
|
||||
/**
|
||||
* @param flag The flag to check against
|
||||
* @return True if it has the flag
|
||||
*/
|
||||
boolean hasFlag(BossFlag flag);
|
||||
public abstract boolean hasFlag(BossFlag flag);
|
||||
|
||||
/**
|
||||
* Get players
|
||||
*
|
||||
* @return UUIDS from players (sorry I lied)
|
||||
*/
|
||||
Set<UUID> getPlayers();
|
||||
public abstract Set<UUID> getPlayers();
|
||||
|
||||
/**
|
||||
* Show the bossbar to everyone (In the getPlayer set)
|
||||
*
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar show();
|
||||
public abstract BossBar show();
|
||||
|
||||
/**
|
||||
* Hide the bossbar from everyone (In the getPlayer set)
|
||||
*
|
||||
* @return The BossBar object
|
||||
*/
|
||||
BossBar hide();
|
||||
public abstract BossBar hide();
|
||||
|
||||
/**
|
||||
* Is it visible?
|
||||
*
|
||||
* @return visibility changable with show() and hide()
|
||||
*/
|
||||
boolean isVisible();
|
||||
public abstract boolean isVisible();
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,34 @@
|
||||
package us.myles.ViaVersion.api.command;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ViaCommandSender {
|
||||
/**
|
||||
* Check if the sender has a permission.
|
||||
*
|
||||
* @param permission Permission string eg. viaversion.admin
|
||||
* @return True if the sender has the permission
|
||||
*/
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
/**
|
||||
* Send a message to the sender
|
||||
*
|
||||
* @param msg The message to send
|
||||
*/
|
||||
void sendMessage(String msg);
|
||||
|
||||
/**
|
||||
* Get the senders UUID.
|
||||
*
|
||||
* @return The senders UUID
|
||||
*/
|
||||
UUID getUUID();
|
||||
|
||||
/**
|
||||
* Get the senders name.
|
||||
*
|
||||
* @return The senders name
|
||||
*/
|
||||
String getName();
|
||||
}
|
||||
+9
-10
@@ -1,6 +1,5 @@
|
||||
package us.myles.ViaVersion.api.command;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import us.myles.ViaVersion.commands.ViaCommandHandler;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -10,14 +9,14 @@ public abstract class ViaSubCommand {
|
||||
/**
|
||||
* Subcommand name
|
||||
*
|
||||
* @return The command name
|
||||
* @return The commands name
|
||||
*/
|
||||
public abstract String name();
|
||||
|
||||
/**
|
||||
* subcommand description, this'll show in /viaversion list
|
||||
*
|
||||
* @return The command description
|
||||
* @return The commands description
|
||||
*/
|
||||
public abstract String description();
|
||||
|
||||
@@ -25,7 +24,7 @@ public abstract class ViaSubCommand {
|
||||
* Usage example:
|
||||
* "playerversion [name]"
|
||||
*
|
||||
* @return The command usage
|
||||
* @return The commands usage
|
||||
*/
|
||||
public String usage() {
|
||||
return name();
|
||||
@@ -34,7 +33,7 @@ public abstract class ViaSubCommand {
|
||||
/**
|
||||
* Permission, null for everyone
|
||||
*
|
||||
* @return The permission required to use the command
|
||||
* @return The permission required to use the commands
|
||||
*/
|
||||
public String permission() {
|
||||
return "viaversion.admin";
|
||||
@@ -45,9 +44,9 @@ public abstract class ViaSubCommand {
|
||||
*
|
||||
* @param sender Command sender
|
||||
* @param args Arguments
|
||||
* @return command executed succesfully if false, show usage
|
||||
* @return commands executed succesfully if false, show usage
|
||||
*/
|
||||
public abstract boolean execute(CommandSender sender, String[] args);
|
||||
public abstract boolean execute(ViaCommandSender sender, String[] args);
|
||||
|
||||
/**
|
||||
* Yay, possibility to implement tab-completion
|
||||
@@ -56,7 +55,7 @@ public abstract class ViaSubCommand {
|
||||
* @param args args
|
||||
* @return tab complete possibilities
|
||||
*/
|
||||
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
||||
public List<String> onTabComplete(ViaCommandSender sender, String[] args) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -67,11 +66,11 @@ public abstract class ViaSubCommand {
|
||||
/**
|
||||
* Send message formatted / colored
|
||||
*
|
||||
* @param sender command sender
|
||||
* @param sender commands sender
|
||||
* @param message string message
|
||||
* @param args optional objects
|
||||
*/
|
||||
public void sendMessage(CommandSender sender, String message, Object... args) {
|
||||
public void sendMessage(ViaCommandSender sender, String message, Object... args) {
|
||||
ViaCommandHandler.sendMessage(sender, message, args);
|
||||
}
|
||||
}
|
||||
+20
@@ -1,5 +1,7 @@
|
||||
package us.myles.ViaVersion.api.command;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ViaVersionCommand {
|
||||
/**
|
||||
* Register your own subcommand inside ViaVersion
|
||||
@@ -24,4 +26,22 @@ public interface ViaVersionCommand {
|
||||
* @return ViaSubCommand instance
|
||||
*/
|
||||
ViaSubCommand getSubCommand(String name);
|
||||
|
||||
/**
|
||||
* Executed when the Command sender executes the commands
|
||||
*
|
||||
* @param sender Sender object
|
||||
* @param args arguments provided
|
||||
* @return was successful
|
||||
*/
|
||||
boolean onCommand(ViaCommandSender sender, String[] args);
|
||||
|
||||
/**
|
||||
* Executed when the Command sender tab-completes
|
||||
*
|
||||
* @param sender Sender object
|
||||
* @param args arguments provided
|
||||
* @return was successful
|
||||
*/
|
||||
List<String> onTabComplete(ViaCommandSender sender, String[] args);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package us.myles.ViaVersion.api.configuration;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ConfigurationProvider {
|
||||
|
||||
/**
|
||||
* Sets the specified path to the given value.
|
||||
*
|
||||
* @param path Path of the object to set.
|
||||
* @param value New value to set the path to
|
||||
*/
|
||||
void set(String path, Object value);
|
||||
|
||||
/**
|
||||
* Saves the config
|
||||
*/
|
||||
void saveConfig();
|
||||
|
||||
/**
|
||||
* Reloads the config
|
||||
*/
|
||||
void reloadConfig();
|
||||
|
||||
/**
|
||||
* Get all the configuration values
|
||||
*
|
||||
* @return Map with key-values
|
||||
*/
|
||||
Map<String, Object> getValues();
|
||||
}
|
||||
File renamed without changes.
+52
-16
@@ -5,9 +5,9 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -66,6 +66,14 @@ public class UserConnection {
|
||||
storedObjects.put(object.getClass(), object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all the stored objects
|
||||
* Used for bungee when switching servers.
|
||||
*/
|
||||
public void clearStoredObjects() {
|
||||
storedObjects.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw packet to the player
|
||||
*
|
||||
@@ -73,7 +81,7 @@ public class UserConnection {
|
||||
* @param currentThread Should it run in the same thread
|
||||
*/
|
||||
public void sendRawPacket(final ByteBuf packet, boolean currentThread) {
|
||||
final ChannelHandler handler = channel.pipeline().get("encoder");
|
||||
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
||||
if (currentThread) {
|
||||
channel.pipeline().context(handler).writeAndFlush(packet);
|
||||
} else {
|
||||
@@ -93,7 +101,7 @@ public class UserConnection {
|
||||
* @return ChannelFuture of the packet being sent
|
||||
*/
|
||||
public ChannelFuture sendRawPacketFuture(final ByteBuf packet) {
|
||||
final ChannelHandler handler = channel.pipeline().get("encoder");
|
||||
final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName());
|
||||
return channel.pipeline().context(handler).writeAndFlush(packet);
|
||||
}
|
||||
|
||||
@@ -134,6 +142,37 @@ public class UserConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean handlePPS() {
|
||||
ViaVersionConfig conf = Via.getConfig();
|
||||
// Max PPS Checker
|
||||
if (conf.getMaxPPS() > 0) {
|
||||
if (getPacketsPerSecond() >= conf.getMaxPPS()) {
|
||||
disconnect(conf.getMaxPPSKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + ""));
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
|
||||
// Tracking PPS Checker
|
||||
if (conf.getMaxWarnings() > 0 && conf.getTrackingPeriod() > 0) {
|
||||
if (getSecondsObserved() > conf.getTrackingPeriod()) {
|
||||
// Reset
|
||||
setWarnings(0);
|
||||
setSecondsObserved(1);
|
||||
} else {
|
||||
setSecondsObserved(getSecondsObserved() + 1);
|
||||
if (getPacketsPerSecond() >= conf.getWarningPPS()) {
|
||||
setWarnings(getWarnings() + 1);
|
||||
}
|
||||
|
||||
if (getWarnings() >= conf.getMaxWarnings()) {
|
||||
disconnect(conf.getMaxWarningsKickMessage().replace("%pps", ((Long) getPacketsPerSecond()).intValue() + ""));
|
||||
return true; // don't send current packet
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect a connection
|
||||
*
|
||||
@@ -145,18 +184,15 @@ public class UserConnection {
|
||||
pendingDisconnect = true;
|
||||
if (get(ProtocolInfo.class).getUuid() != null) {
|
||||
final UUID uuid = get(ProtocolInfo.class).getUuid();
|
||||
if (Bukkit.getPlayer(uuid) != null) {
|
||||
Bukkit.getScheduler().runTask(Bukkit.getPluginManager().getPlugin("ViaVersion"), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player != null)
|
||||
player.kickPlayer(ChatColor.translateAlternateColorCodes('&', reason));
|
||||
Via.getPlatform().runSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Via.getPlatform().kickPlayer(uuid, ChatColor.translateAlternateColorCodes('&', reason))) {
|
||||
getChannel().close(); // =)
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
getChannel().close(); // =)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package us.myles.ViaVersion.api.entities;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
// 1.10 Entity / Object ids
|
||||
public class Entity1_10Types {
|
||||
|
||||
public static EntityType getTypeFromId(int typeID, boolean isObject) {
|
||||
Optional<EntityType> type;
|
||||
|
||||
if (isObject)
|
||||
type = ObjectTypes.getPCEntity(typeID);
|
||||
else
|
||||
type = EntityType.findById(typeID);
|
||||
|
||||
if (!type.isPresent()) {
|
||||
Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
|
||||
return EntityType.ENTITY; // Fall back to the basic ENTITY
|
||||
}
|
||||
|
||||
return type.get();
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum EntityType {
|
||||
ENTITY(-1),
|
||||
DROPPED_ITEM(1, EntityType.ENTITY),
|
||||
EXPERIENCE_ORB(2, EntityType.ENTITY),
|
||||
LEASH_HITCH(8, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
|
||||
PAINTING(9, EntityType.ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
|
||||
ARROW(10, EntityType.ENTITY),
|
||||
SNOWBALL(11, EntityType.ENTITY), // Actually EntityProjectile
|
||||
FIREBALL(12, EntityType.ENTITY),
|
||||
SMALL_FIREBALL(13, EntityType.ENTITY),
|
||||
ENDER_PEARL(14, EntityType.ENTITY), // Actually EntityProjectile
|
||||
ENDER_SIGNAL(15, EntityType.ENTITY),
|
||||
THROWN_EXP_BOTTLE(17, EntityType.ENTITY),
|
||||
ITEM_FRAME(18, EntityType.ENTITY), // Actually EntityHanging
|
||||
WITHER_SKULL(19, EntityType.ENTITY),
|
||||
PRIMED_TNT(20, EntityType.ENTITY),
|
||||
FALLING_BLOCK(21, EntityType.ENTITY),
|
||||
FIREWORK(22, EntityType.ENTITY),
|
||||
TIPPED_ARROW(23, EntityType.ARROW),
|
||||
SPECTRAL_ARROW(24, EntityType.ARROW),
|
||||
SHULKER_BULLET(25, EntityType.ENTITY),
|
||||
DRAGON_FIREBALL(26, EntityType.FIREBALL),
|
||||
|
||||
ENTITY_LIVING(-1, ENTITY),
|
||||
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
|
||||
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
|
||||
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
|
||||
ENTITY_HUMAN(-1, ENTITY_LIVING),
|
||||
|
||||
ARMOR_STAND(30, EntityType.ENTITY_LIVING),
|
||||
|
||||
// Vehicles
|
||||
MINECART_ABSTRACT(-1, ENTITY),
|
||||
MINECART_COMMAND(40, MINECART_ABSTRACT),
|
||||
BOAT(41, ENTITY),
|
||||
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
|
||||
MINECART_CHEST(43, MINECART_ABSTRACT),
|
||||
MINECART_FURNACE(44, MINECART_ABSTRACT),
|
||||
MINECART_TNT(45, MINECART_ABSTRACT),
|
||||
MINECART_HOPPER(46, MINECART_ABSTRACT),
|
||||
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
|
||||
|
||||
CREEPER(50, ENTITY_INSENTIENT),
|
||||
SKELETON(51, ENTITY_INSENTIENT),
|
||||
SPIDER(52, ENTITY_INSENTIENT),
|
||||
GIANT(53, ENTITY_INSENTIENT),
|
||||
ZOMBIE(54, ENTITY_INSENTIENT),
|
||||
SLIME(55, ENTITY_INSENTIENT),
|
||||
GHAST(56, ENTITY_INSENTIENT),
|
||||
PIG_ZOMBIE(57, ZOMBIE),
|
||||
ENDERMAN(58, ENTITY_INSENTIENT),
|
||||
CAVE_SPIDER(59, SPIDER),
|
||||
SILVERFISH(60, ENTITY_INSENTIENT),
|
||||
BLAZE(61, ENTITY_INSENTIENT),
|
||||
MAGMA_CUBE(62, SLIME),
|
||||
ENDER_DRAGON(63, ENTITY_INSENTIENT),
|
||||
WITHER(64, ENTITY_INSENTIENT),
|
||||
BAT(65, ENTITY_INSENTIENT),
|
||||
WITCH(66, ENTITY_INSENTIENT),
|
||||
ENDERMITE(67, ENTITY_INSENTIENT),
|
||||
GUARDIAN(68, ENTITY_INSENTIENT),
|
||||
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
|
||||
SHULKER(69, EntityType.IRON_GOLEM),
|
||||
PIG(90, ENTITY_AGEABLE),
|
||||
SHEEP(91, ENTITY_AGEABLE),
|
||||
COW(92, ENTITY_AGEABLE),
|
||||
CHICKEN(93, ENTITY_AGEABLE),
|
||||
SQUID(94, ENTITY_INSENTIENT),
|
||||
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
|
||||
MUSHROOM_COW(96, COW),
|
||||
SNOWMAN(97, EntityType.IRON_GOLEM),
|
||||
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
|
||||
HORSE(100, ENTITY_AGEABLE),
|
||||
RABBIT(101, ENTITY_AGEABLE),
|
||||
POLAR_BEAR(102, ENTITY_AGEABLE),
|
||||
VILLAGER(120, ENTITY_AGEABLE),
|
||||
ENDER_CRYSTAL(200, ENTITY),
|
||||
SPLASH_POTION(-1, ENTITY),
|
||||
LINGERING_POTION(-1, SPLASH_POTION),
|
||||
AREA_EFFECT_CLOUD(-1, ENTITY),
|
||||
EGG(-1, ENTITY),
|
||||
FISHING_HOOK(-1, ENTITY),
|
||||
LIGHTNING(-1, ENTITY),
|
||||
WEATHER(-1, ENTITY),
|
||||
PLAYER(-1, ENTITY_HUMAN),
|
||||
COMPLEX_PART(-1, ENTITY);
|
||||
|
||||
private final int id;
|
||||
private final EntityType parent;
|
||||
|
||||
EntityType(int id) {
|
||||
this.id = id;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
public static Optional<EntityType> findById(int id) {
|
||||
if (id == -1) // Check if this is called
|
||||
return Optional.absent();
|
||||
|
||||
for (EntityType ent : EntityType.values())
|
||||
if (ent.getId() == id)
|
||||
return Optional.of(ent);
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum ObjectTypes {
|
||||
BOAT(1, EntityType.BOAT),
|
||||
ITEM(2, EntityType.DROPPED_ITEM),
|
||||
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
|
||||
MINECART(10, EntityType.MINECART_ABSTRACT),
|
||||
TNT_PRIMED(50, EntityType.PRIMED_TNT),
|
||||
ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL),
|
||||
TIPPED_ARROW(60, EntityType.TIPPED_ARROW),
|
||||
SNOWBALL(61, EntityType.SNOWBALL),
|
||||
EGG(62, EntityType.EGG),
|
||||
FIREBALL(63, EntityType.FIREBALL),
|
||||
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
|
||||
ENDER_PEARL(65, EntityType.ENDER_PEARL),
|
||||
WITHER_SKULL(66, EntityType.WITHER_SKULL),
|
||||
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
|
||||
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
|
||||
ITEM_FRAME(71, EntityType.ITEM_FRAME),
|
||||
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
|
||||
POTION(73, EntityType.SPLASH_POTION),
|
||||
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
|
||||
FIREWORK(76, EntityType.FIREWORK),
|
||||
LEASH(77, EntityType.LEASH_HITCH),
|
||||
ARMOR_STAND(78, EntityType.ARMOR_STAND),
|
||||
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
|
||||
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
|
||||
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
|
||||
|
||||
private final int id;
|
||||
private final EntityType type;
|
||||
|
||||
public static Optional<ObjectTypes> findById(int id) {
|
||||
if (id == -1)
|
||||
return Optional.absent();
|
||||
|
||||
for (ObjectTypes ent : ObjectTypes.values())
|
||||
if (ent.getId() == id)
|
||||
return Optional.of(ent);
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public static Optional<EntityType> getPCEntity(int id) {
|
||||
Optional<ObjectTypes> output = findById(id);
|
||||
|
||||
if (!output.isPresent())
|
||||
return Optional.absent();
|
||||
return Optional.of(output.get().getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package us.myles.ViaVersion.api.entities;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import us.myles.ViaVersion.api.Via;
|
||||
|
||||
// 1.11 Entity / Object ids TODO maybe in the future instead of copying it, some api.
|
||||
public class Entity1_11Types {
|
||||
public static EntityType getTypeFromId(int typeID, boolean isObject) {
|
||||
Optional<EntityType> type;
|
||||
|
||||
if (isObject)
|
||||
type = ObjectTypes.getPCEntity(typeID);
|
||||
else
|
||||
type = EntityType.findById(typeID);
|
||||
|
||||
if (!type.isPresent()) {
|
||||
Via.getPlatform().getLogger().severe("Could not find type id " + typeID + " isObject=" + isObject);
|
||||
return EntityType.ENTITY; // Fall back to the basic ENTITY
|
||||
}
|
||||
|
||||
return type.get();
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum EntityType {
|
||||
ENTITY(-1),
|
||||
DROPPED_ITEM(1, ENTITY),
|
||||
EXPERIENCE_ORB(2, ENTITY),
|
||||
LEASH_HITCH(8, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
|
||||
PAINTING(9, ENTITY), // Actually entity hanging but it doesn't make a lot of difference for metadata
|
||||
ARROW(10, ENTITY),
|
||||
SNOWBALL(11, ENTITY), // Actually EntityProjectile
|
||||
FIREBALL(12, ENTITY),
|
||||
SMALL_FIREBALL(13, ENTITY),
|
||||
ENDER_PEARL(14, ENTITY), // Actually EntityProjectile
|
||||
ENDER_SIGNAL(15, ENTITY),
|
||||
THROWN_EXP_BOTTLE(17, ENTITY),
|
||||
ITEM_FRAME(18, ENTITY), // Actually EntityHanging
|
||||
WITHER_SKULL(19, ENTITY),
|
||||
PRIMED_TNT(20, ENTITY),
|
||||
FALLING_BLOCK(21, ENTITY),
|
||||
FIREWORK(22, ENTITY),
|
||||
TIPPED_ARROW(23, ARROW),
|
||||
SPECTRAL_ARROW(24, ARROW),
|
||||
SHULKER_BULLET(25, ENTITY),
|
||||
DRAGON_FIREBALL(26, FIREBALL),
|
||||
EVOCATION_FANGS(33, ENTITY),
|
||||
|
||||
|
||||
ENTITY_LIVING(-1, ENTITY),
|
||||
ENTITY_INSENTIENT(-1, ENTITY_LIVING),
|
||||
ENTITY_AGEABLE(-1, ENTITY_INSENTIENT),
|
||||
ENTITY_TAMEABLE_ANIMAL(-1, ENTITY_AGEABLE),
|
||||
ENTITY_HUMAN(-1, ENTITY_LIVING),
|
||||
|
||||
ARMOR_STAND(30, ENTITY_LIVING),
|
||||
EVOCATION_ILLAGER(34, ENTITY_INSENTIENT),
|
||||
VEX(35, ENTITY_INSENTIENT),
|
||||
VINDICATION_ILLAGER(36, ENTITY_INSENTIENT),
|
||||
|
||||
// Vehicles
|
||||
MINECART_ABSTRACT(-1, ENTITY),
|
||||
MINECART_COMMAND(40, MINECART_ABSTRACT),
|
||||
BOAT(41, ENTITY),
|
||||
MINECART_RIDEABLE(42, MINECART_ABSTRACT),
|
||||
MINECART_CHEST(43, MINECART_ABSTRACT),
|
||||
MINECART_FURNACE(44, MINECART_ABSTRACT),
|
||||
MINECART_TNT(45, MINECART_ABSTRACT),
|
||||
MINECART_HOPPER(46, MINECART_ABSTRACT),
|
||||
MINECART_MOB_SPAWNER(47, MINECART_ABSTRACT),
|
||||
|
||||
CREEPER(50, ENTITY_INSENTIENT),
|
||||
|
||||
ABSTRACT_SKELETON(-1, ENTITY_INSENTIENT),
|
||||
SKELETON(51, ABSTRACT_SKELETON),
|
||||
WITHER_SKELETON(5, ABSTRACT_SKELETON),
|
||||
STRAY(6, ABSTRACT_SKELETON),
|
||||
|
||||
SPIDER(52, ENTITY_INSENTIENT),
|
||||
GIANT(53, ENTITY_INSENTIENT),
|
||||
|
||||
ZOMBIE(54, ENTITY_INSENTIENT),
|
||||
HUSK(23, ZOMBIE),
|
||||
ZOMBIE_VILLAGER(27, ZOMBIE),
|
||||
|
||||
SLIME(55, ENTITY_INSENTIENT),
|
||||
GHAST(56, ENTITY_INSENTIENT),
|
||||
PIG_ZOMBIE(57, ZOMBIE),
|
||||
ENDERMAN(58, ENTITY_INSENTIENT),
|
||||
CAVE_SPIDER(59, SPIDER),
|
||||
SILVERFISH(60, ENTITY_INSENTIENT),
|
||||
BLAZE(61, ENTITY_INSENTIENT),
|
||||
MAGMA_CUBE(62, SLIME),
|
||||
ENDER_DRAGON(63, ENTITY_INSENTIENT),
|
||||
WITHER(64, ENTITY_INSENTIENT),
|
||||
BAT(65, ENTITY_INSENTIENT),
|
||||
WITCH(66, ENTITY_INSENTIENT),
|
||||
ENDERMITE(67, ENTITY_INSENTIENT),
|
||||
|
||||
GUARDIAN(68, ENTITY_INSENTIENT),
|
||||
ELDER_GUARDIAN(4, EntityType.GUARDIAN), // Moved down to avoid illegal forward reference
|
||||
|
||||
IRON_GOLEM(99, ENTITY_INSENTIENT), // moved up to avoid illegal forward references
|
||||
SHULKER(69, EntityType.IRON_GOLEM),
|
||||
PIG(90, ENTITY_AGEABLE),
|
||||
SHEEP(91, ENTITY_AGEABLE),
|
||||
COW(92, ENTITY_AGEABLE),
|
||||
CHICKEN(93, ENTITY_AGEABLE),
|
||||
SQUID(94, ENTITY_INSENTIENT),
|
||||
WOLF(95, ENTITY_TAMEABLE_ANIMAL),
|
||||
MUSHROOM_COW(96, COW),
|
||||
SNOWMAN(97, EntityType.IRON_GOLEM),
|
||||
OCELOT(98, ENTITY_TAMEABLE_ANIMAL),
|
||||
|
||||
ABSTRACT_HORSE(-1, ENTITY_AGEABLE),
|
||||
HORSE(100, ABSTRACT_HORSE),
|
||||
SKELETON_HORSE(28, ABSTRACT_HORSE),
|
||||
ZOMBIE_HORSE(29, ABSTRACT_HORSE),
|
||||
|
||||
CHESTED_HORSE(-1, ABSTRACT_HORSE),
|
||||
DONKEY(31, CHESTED_HORSE),
|
||||
MULE(32, CHESTED_HORSE),
|
||||
LIAMA(103, CHESTED_HORSE),
|
||||
|
||||
|
||||
RABBIT(101, ENTITY_AGEABLE),
|
||||
POLAR_BEAR(102, ENTITY_AGEABLE),
|
||||
VILLAGER(120, ENTITY_AGEABLE),
|
||||
ENDER_CRYSTAL(200, ENTITY),
|
||||
SPLASH_POTION(-1, ENTITY),
|
||||
LINGERING_POTION(-1, SPLASH_POTION),
|
||||
AREA_EFFECT_CLOUD(-1, ENTITY),
|
||||
EGG(-1, ENTITY),
|
||||
FISHING_HOOK(-1, ENTITY),
|
||||
LIGHTNING(-1, ENTITY),
|
||||
WEATHER(-1, ENTITY),
|
||||
PLAYER(-1, ENTITY_HUMAN),
|
||||
COMPLEX_PART(-1, ENTITY),
|
||||
LIAMA_SPIT(-1, ENTITY);
|
||||
|
||||
private final int id;
|
||||
private final EntityType parent;
|
||||
|
||||
EntityType(int id) {
|
||||
this.id = id;
|
||||
this.parent = null;
|
||||
}
|
||||
|
||||
public static Optional<EntityType> findById(int id) {
|
||||
if (id == -1) // Check if this is called
|
||||
return Optional.absent();
|
||||
|
||||
for (EntityType ent : EntityType.values())
|
||||
if (ent.getId() == id)
|
||||
return Optional.of(ent);
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public boolean is(EntityType... types) {
|
||||
for (EntityType type : types)
|
||||
if (is(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean is(EntityType type) {
|
||||
return this == type;
|
||||
}
|
||||
|
||||
public boolean isOrHasParent(EntityType type) {
|
||||
EntityType parent = this;
|
||||
|
||||
do {
|
||||
if (parent.equals(type))
|
||||
return true;
|
||||
|
||||
parent = parent.getParent();
|
||||
} while (parent != null);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum ObjectTypes {
|
||||
BOAT(1, EntityType.BOAT),
|
||||
ITEM(2, EntityType.DROPPED_ITEM),
|
||||
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
|
||||
MINECART(10, EntityType.MINECART_ABSTRACT),
|
||||
TNT_PRIMED(50, EntityType.PRIMED_TNT),
|
||||
ENDER_CRYSTAL(51, EntityType.ENDER_CRYSTAL),
|
||||
TIPPED_ARROW(60, EntityType.TIPPED_ARROW),
|
||||
SNOWBALL(61, EntityType.SNOWBALL),
|
||||
EGG(62, EntityType.EGG),
|
||||
FIREBALL(63, EntityType.FIREBALL),
|
||||
SMALL_FIREBALL(64, EntityType.SMALL_FIREBALL),
|
||||
ENDER_PEARL(65, EntityType.ENDER_PEARL),
|
||||
WITHER_SKULL(66, EntityType.WITHER_SKULL),
|
||||
SHULKER_BULLET(67, EntityType.SHULKER_BULLET),
|
||||
LIAMA_SPIT(68, EntityType.LIAMA_SPIT),
|
||||
FALLING_BLOCK(70, EntityType.FALLING_BLOCK),
|
||||
ITEM_FRAME(71, EntityType.ITEM_FRAME),
|
||||
ENDER_SIGNAL(72, EntityType.ENDER_SIGNAL),
|
||||
POTION(73, EntityType.SPLASH_POTION),
|
||||
THROWN_EXP_BOTTLE(75, EntityType.THROWN_EXP_BOTTLE),
|
||||
FIREWORK(76, EntityType.FIREWORK),
|
||||
LEASH(77, EntityType.LEASH_HITCH),
|
||||
ARMOR_STAND(78, EntityType.ARMOR_STAND),
|
||||
EVOCATION_FANGS(39, EntityType.EVOCATION_FANGS),
|
||||
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK),
|
||||
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
|
||||
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
|
||||
|
||||
private final int id;
|
||||
private final EntityType type;
|
||||
|
||||
public static Optional<ObjectTypes> findById(int id) {
|
||||
if (id == -1)
|
||||
return Optional.absent();
|
||||
|
||||
for (ObjectTypes ent : ObjectTypes.values())
|
||||
if (ent.getId() == id)
|
||||
return Optional.of(ent);
|
||||
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public static Optional<EntityType> getPCEntity(int id) {
|
||||
Optional<ObjectTypes> output = findById(id);
|
||||
|
||||
if (!output.isPresent())
|
||||
return Optional.absent();
|
||||
return Optional.of(output.get().getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package us.myles.ViaVersion.api.minecraft;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum Environment {
|
||||
NORMAL(0),
|
||||
NETHER(-1),
|
||||
END(1);
|
||||
|
||||
private final int id;
|
||||
private static final Map<Integer, Environment> lookup = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (Environment env : values()) {
|
||||
lookup.put(env.getId(), env);
|
||||
}
|
||||
}
|
||||
|
||||
Environment(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public static Environment getEnvironmentById(int id) {
|
||||
return lookup.get(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package us.myles.ViaVersion.api.minecraft;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class EulerAngle {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,12 @@
|
||||
package us.myles.ViaVersion.api.minecraft;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Vector {
|
||||
private int blockX;
|
||||
private int blockY;
|
||||
private int blockZ;
|
||||
}
|
||||
+6
@@ -1,5 +1,9 @@
|
||||
package us.myles.ViaVersion.api.minecraft.chunks;
|
||||
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Chunk {
|
||||
int getX();
|
||||
|
||||
@@ -14,4 +18,6 @@ public interface Chunk {
|
||||
byte[] getBiomeData();
|
||||
|
||||
int getBitmask();
|
||||
|
||||
List<CompoundTag> getBlockEntities();
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,16 @@
|
||||
package us.myles.ViaVersion.api.minecraft.item;
|
||||
|
||||
import lombok.*;
|
||||
import org.spacehq.opennbt.tag.builtin.CompoundTag;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class Item {
|
||||
private short id;
|
||||
private byte amount;
|
||||
private short data;
|
||||
private CompoundTag tag;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package us.myles.ViaVersion.api.minecraft.metadata;
|
||||
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
public interface MetaType {
|
||||
|
||||
/**
|
||||
* Get the write/read type
|
||||
*
|
||||
* @return Type instance
|
||||
*/
|
||||
Type getType();
|
||||
|
||||
/**
|
||||
* Get type id from the specific MetaDataType
|
||||
*
|
||||
* @return Type id as an integer
|
||||
*/
|
||||
int getTypeID();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package us.myles.ViaVersion.api.minecraft.metadata;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
public class Metadata {
|
||||
private int id;
|
||||
private MetaType metaType;
|
||||
private Object value;
|
||||
}
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
|
||||
package us.myles.ViaVersion.api.minecraft.metadata.types;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.MetaType;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum MetadataTypes {
|
||||
public enum MetaType1_8 implements MetaType {
|
||||
Byte(0, Type.BYTE),
|
||||
Short(1, Type.SHORT),
|
||||
Int(2, Type.INT),
|
||||
@@ -20,7 +21,7 @@ public enum MetadataTypes {
|
||||
private final int typeID;
|
||||
private final Type type;
|
||||
|
||||
public static MetadataTypes byId(int id) {
|
||||
public static MetaType1_8 byId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||
package us.myles.ViaVersion.protocols.protocol1_9to1_8.metadata;
|
||||
package us.myles.ViaVersion.api.minecraft.metadata.types;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import us.myles.ViaVersion.api.minecraft.metadata.MetaType;
|
||||
import us.myles.ViaVersion.api.type.Type;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum NewType {
|
||||
public enum MetaType1_9 implements MetaType {
|
||||
Byte(0, Type.BYTE),
|
||||
VarInt(1, Type.VAR_INT),
|
||||
Float(2, Type.FLOAT),
|
||||
@@ -25,7 +26,7 @@ public enum NewType {
|
||||
private final int typeID;
|
||||
private final Type type;
|
||||
|
||||
public static NewType byId(int id) {
|
||||
public static MetaType1_9 byId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package us.myles.ViaVersion.api.platform;
|
||||
|
||||
public interface TaskId {
|
||||
/**
|
||||
* Returns the actual object represented by this TaskId
|
||||
* Null if task cannot be cancelled.
|
||||
*
|
||||
* @return Platform based Object (don't assume)
|
||||
*/
|
||||
Object getObject();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package us.myles.ViaVersion.api.platform;
|
||||
|
||||
public interface ViaInjector {
|
||||
/**
|
||||
* Inject into the current Platform
|
||||
*
|
||||
* @throws Exception If there is an error with injecting
|
||||
*/
|
||||
void inject() throws Exception;
|
||||
|
||||
/**
|
||||
* Uninject into the current Platform
|
||||
*
|
||||
* @throws Exception If there is an error with uninjecting
|
||||
*/
|
||||
void uninject() throws Exception;
|
||||
|
||||
/**
|
||||
* Get the server protocol version
|
||||
*
|
||||
* @return The server protocol integer
|
||||
* @throws Exception If there is an error with getting this info, eg. not binded.
|
||||
*/
|
||||
int getServerProtocolVersion() throws Exception;
|
||||
|
||||
/**
|
||||
* Get the name of the encoder for then netty pipeline for this platform.
|
||||
*
|
||||
* @return The name
|
||||
*/
|
||||
String getEncoderName();
|
||||
|
||||
/**
|
||||
* Get the name of the decoder for then netty pipeline for this platform.
|
||||
*
|
||||
* @return The name
|
||||
*/
|
||||
String getDecoderName();
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package us.myles.ViaVersion.api.platform;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import us.myles.ViaVersion.api.ViaAPI;
|
||||
import us.myles.ViaVersion.api.ViaVersionConfig;
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender;
|
||||
import us.myles.ViaVersion.api.configuration.ConfigurationProvider;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* ViaPlatform represents a platform ViaVersion runs on
|
||||
*
|
||||
* @param <T> - The player type for the platform, used for API related methods
|
||||
*/
|
||||
public interface ViaPlatform<T> {
|
||||
/**
|
||||
* Get the logger for this platform
|
||||
*
|
||||
* @return Java Logger (may be a wrapper)
|
||||
*/
|
||||
Logger getLogger();
|
||||
|
||||
/**
|
||||
* Get the platform name
|
||||
*
|
||||
* @return Platform Name (simply its name)
|
||||
*/
|
||||
String getPlatformName();
|
||||
|
||||
/**
|
||||
* Get the platform version
|
||||
*
|
||||
* @return Platforn version
|
||||
*/
|
||||
String getPlatformVersion();
|
||||
|
||||
/**
|
||||
* Get the plugin version
|
||||
*
|
||||
* @return Plugin version as a semver string
|
||||
*/
|
||||
String getPluginVersion();
|
||||
|
||||
/**
|
||||
* Run a task Async
|
||||
*
|
||||
* @param runnable The task to run
|
||||
* @return The Task ID
|
||||
*/
|
||||
TaskId runAsync(Runnable runnable);
|
||||
|
||||
/**
|
||||
* Run a task Sync
|
||||
*
|
||||
* @param runnable The task to run
|
||||
* @return The Task ID
|
||||
*/
|
||||
TaskId runSync(Runnable runnable);
|
||||
|
||||
/**
|
||||
* Run a task at a repeating interval.
|
||||
* Initial interval is the same as repeat.
|
||||
*
|
||||
* @param runnable The task to run
|
||||
* @param ticks The interval to run it at
|
||||
* @return The Task ID
|
||||
*/
|
||||
TaskId runRepeatingSync(Runnable runnable, Long ticks);
|
||||
|
||||
/**
|
||||
* Cancel a task
|
||||
*
|
||||
* @param taskId The task ID to cancel
|
||||
*/
|
||||
void cancelTask(TaskId taskId);
|
||||
|
||||
/**
|
||||
* Get the online players
|
||||
*
|
||||
* @return Array of ViaCommandSender
|
||||
*/
|
||||
ViaCommandSender[] getOnlinePlayers();
|
||||
|
||||
/**
|
||||
* Send a message to a player
|
||||
*
|
||||
* @param uuid The player's UUID
|
||||
* @param message The message to send
|
||||
*/
|
||||
void sendMessage(UUID uuid, String message);
|
||||
|
||||
/**
|
||||
* Kick a player for a reason
|
||||
*
|
||||
* @param uuid The player's UUID
|
||||
* @param message The message to kick them with
|
||||
* @return True if it was successful
|
||||
*/
|
||||
boolean kickPlayer(UUID uuid, String message);
|
||||
|
||||
/**
|
||||
* Check if the plugin is enabled.
|
||||
*
|
||||
* @return True if it is enabled
|
||||
*/
|
||||
boolean isPluginEnabled();
|
||||
|
||||
/**
|
||||
* Get the API for this platform
|
||||
*
|
||||
* @return The API for the platform
|
||||
*/
|
||||
ViaAPI<T> getApi();
|
||||
|
||||
/**
|
||||
* Get the config API for this platform
|
||||
*
|
||||
* @return The config API
|
||||
*/
|
||||
ViaVersionConfig getConf();
|
||||
|
||||
/**
|
||||
* Get the backend configuration provider for this platform.
|
||||
* (On some platforms this returns the same as getConf())
|
||||
*
|
||||
* @return The configuration provider
|
||||
*/
|
||||
ConfigurationProvider getConfigurationProvider();
|
||||
|
||||
/**
|
||||
* Called when a reload happens
|
||||
*/
|
||||
void onReload();
|
||||
|
||||
/**
|
||||
* Get the JSON data required for /viaversion dump
|
||||
*
|
||||
* @return The json data
|
||||
*/
|
||||
JsonObject getDump();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package us.myles.ViaVersion.api.platform;
|
||||
|
||||
public interface ViaPlatformLoader {
|
||||
/**
|
||||
* Initialise the loading for a platform, eg. registering listeners / providers / events etc.
|
||||
*/
|
||||
void load();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package us.myles.ViaVersion.api.platform.providers;
|
||||
|
||||
public interface Provider {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package us.myles.ViaVersion.api.platform.providers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ViaProviders {
|
||||
private final Map<Class<? extends Provider>, Provider> providers = new HashMap<>();
|
||||
private final List<Class<? extends Provider>> lonelyProviders = new ArrayList<>();
|
||||
|
||||
public void require(Class<? extends Provider> provider) {
|
||||
lonelyProviders.add(provider);
|
||||
}
|
||||
|
||||
public <T extends Provider> void register(Class<T> provider, T value) {
|
||||
providers.put(provider, value);
|
||||
}
|
||||
|
||||
public <T extends Provider> void use(Class<T> provider, T value) {
|
||||
if (lonelyProviders.contains(provider)) {
|
||||
lonelyProviders.remove(provider);
|
||||
}
|
||||
providers.put(provider, value);
|
||||
}
|
||||
|
||||
public <T extends Provider> T get(Class<T> provider) {
|
||||
if (providers.containsKey(provider)) {
|
||||
return (T) providers.get(provider);
|
||||
} else {
|
||||
if (lonelyProviders.contains(provider)) {
|
||||
throw new IllegalStateException("There was no provider for " + provider + ", one is required!");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 294 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user