Merge pull request #1162 from creeper123123321/proxybossbarfix

Fix bungee and velocity boss bar, implement Velocity channel workaround
This commit is contained in:
Myles 2019-01-19 15:58:12 +00:00 committed by GitHub
commit a016eade01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 99 additions and 57 deletions

View File

@ -8,25 +8,27 @@ import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.event.EventHandler;
import net.md_5.bungee.event.EventPriority; import net.md_5.bungee.event.EventPriority;
import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.PluginMessage;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.api.protocol.ProtocolVersion; import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; import us.myles.ViaVersion.bungee.service.ProtocolDetectorService;
import us.myles.ViaVersion.bungee.storage.BungeeStorage; import us.myles.ViaVersion.bungee.storage.BungeeStorage;
import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.InventoryPackets; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.InventoryPackets;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.UUID;
public class BungeeServerHandler implements Listener { public class BungeeServerHandler implements Listener {
private static Method getHandshake; private static Method getHandshake;
@ -86,14 +88,6 @@ public class BungeeServerHandler implements Listener {
public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception { public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception {
if (user == null) return; if (user == null) return;
// Manually hide ViaVersion-created BossBars if the childserver was version 1.8.x (#666)
if (user.has(EntityTracker.class)) {
EntityTracker tracker = user.get(EntityTracker.class);
if (tracker.getBossBarMap() != null)
for (BossBar bar : tracker.getBossBarMap().values())
bar.hide();
}
// Handle server/version change // Handle server/version change
if (user.has(BungeeStorage.class)) { if (user.has(BungeeStorage.class)) {
BungeeStorage storage = user.get(BungeeStorage.class); BungeeStorage storage = user.get(BungeeStorage.class);
@ -107,6 +101,18 @@ public class BungeeServerHandler implements Listener {
int protocolId = ProtocolDetectorService.getProtocolId(serverName); int protocolId = ProtocolDetectorService.getProtocolId(serverName);
if (protocolId <= ProtocolVersion.v1_8.getId()) { // 1.8 doesn't have BossBar packet
if (storage.getBossbar() != null) {
for (UUID uuid : storage.getBossbar()) {
PacketWrapper wrapper = new PacketWrapper(0x0C, null, user);
wrapper.write(Type.UUID, uuid);
wrapper.write(Type.VAR_INT, 1); // remove
wrapper.send(Protocol1_9TO1_8.class, true, true);
}
storage.getBossbar().clear();
}
}
ProtocolInfo info = user.get(ProtocolInfo.class); ProtocolInfo info = user.get(ProtocolInfo.class);
int previousServerProtocol = info.getServerProtocolVersion(); int previousServerProtocol = info.getServerProtocolVersion();
@ -130,41 +136,32 @@ public class BungeeServerHandler implements Listener {
// Workaround 1.13 server change // Workaround 1.13 server change
Object relayMessages = getRelayMessages.invoke(e.getPlayer().getPendingConnection()); Object relayMessages = getRelayMessages.invoke(e.getPlayer().getPendingConnection());
if (relayMessages instanceof List) { for (Object message : (List) relayMessages) {
for (Object message : (List) relayMessages) { PluginMessage plMsg = (PluginMessage) message;
if (message instanceof PluginMessage) { String channel = plMsg.getTag();
PluginMessage plMsg = (PluginMessage) message; int id1_13 = ProtocolVersion.v1_13.getId();
String channel = plMsg.getTag(); if (previousServerProtocol != -1) {
if (previousServerProtocol != -1) { if (previousServerProtocol < id1_13 && protocolId >= id1_13) {
if (previousServerProtocol < ProtocolVersion.v1_13.getId() channel = InventoryPackets.getNewPluginChannelId(channel);
&& protocolId >= ProtocolVersion.v1_13.getId()) { if (channel.equals("minecraft:register")) {
channel = InventoryPackets.getNewPluginChannelId(channel); String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0");
if (channel.equals("minecraft:register")) { for (int i = 0; i < channels.length; i++) {
String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0"); channels[i] = InventoryPackets.getNewPluginChannelId(channels[i]);
for (int i = 0; i < channels.length; i++) {
channels[i] = InventoryPackets.getNewPluginChannelId(channels[i]);
}
plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8));
}
} else if (previousServerProtocol >= ProtocolVersion.v1_13.getId()
&& protocolId < ProtocolVersion.v1_13.getId()) {
channel = InventoryPackets.getOldPluginChannelId(channel);
if (channel.equals("REGISTER")) {
String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0");
for (int i = 0; i < channels.length; i++) {
channels[i] = InventoryPackets.getOldPluginChannelId(channels[i]);
}
plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8));
}
} }
plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8));
}
} else if (previousServerProtocol >= id1_13 && protocolId < id1_13) {
channel = InventoryPackets.getOldPluginChannelId(channel);
if (channel.equals("REGISTER")) {
String[] channels = new String(plMsg.getData(), StandardCharsets.UTF_8).split("\0");
for (int i = 0; i < channels.length; i++) {
channels[i] = InventoryPackets.getOldPluginChannelId(channels[i]);
}
plMsg.setData(Joiner.on('\0').join(channels).getBytes(StandardCharsets.UTF_8));
} }
plMsg.setTag(channel);
} else {
Via.getPlatform().getLogger().warning("relayMessages contains a element that isn't a Handshake " + message);
} }
} }
} else { plMsg.setTag(channel);
Via.getPlatform().getLogger().warning("relayMessages isn't a List! " + relayMessages);
} }
user.put(info); user.put(info);

View File

@ -5,21 +5,27 @@ import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.player.ServerConnectedEvent; import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.event.player.ServerPreConnectEvent; import com.velocitypowered.api.event.player.ServerPreConnectEvent;
import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.network.ProtocolVersion;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.Pair; import us.myles.ViaVersion.api.Pair;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
import us.myles.ViaVersion.api.boss.BossBar;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.Protocol; import us.myles.ViaVersion.api.protocol.Protocol;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry; import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import us.myles.ViaVersion.api.type.Type;
import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.packets.InventoryPackets;
import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8;
import us.myles.ViaVersion.util.ReflectionUtil;
import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; import us.myles.ViaVersion.velocity.service.ProtocolDetectorService;
import us.myles.ViaVersion.velocity.storage.VelocityStorage; import us.myles.ViaVersion.velocity.storage.VelocityStorage;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
public class VelocityServerHandler { public class VelocityServerHandler {
@ -27,6 +33,7 @@ public class VelocityServerHandler {
private static Method setNextProtocolVersion; private static Method setNextProtocolVersion;
private static Method getMinecraftConnection; private static Method getMinecraftConnection;
private static Method getNextProtocolVersion; private static Method getNextProtocolVersion;
private static Method getKnownChannels;
static { static {
try { try {
@ -38,6 +45,8 @@ public class VelocityServerHandler {
.getDeclaredMethod("getMinecraftConnection"); .getDeclaredMethod("getMinecraftConnection");
getNextProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection") getNextProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection")
.getDeclaredMethod("getNextProtocolVersion"); .getDeclaredMethod("getNextProtocolVersion");
getKnownChannels = Class.forName("com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler")
.getDeclaredMethod("getKnownChannels");
} catch (NoSuchMethodException | ClassNotFoundException e) { } catch (NoSuchMethodException | ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -78,14 +87,6 @@ public class VelocityServerHandler {
public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception { public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception {
if (user == null) return; if (user == null) return;
// Manually hide ViaVersion-created BossBars if the childserver was version 1.8.x (#666)
if (user.has(EntityTracker.class)) {
EntityTracker tracker = user.get(EntityTracker.class);
if (tracker.getBossBarMap() != null)
for (BossBar bar : tracker.getBossBarMap().values())
bar.hide();
}
// Handle server/version change // Handle server/version change
if (user.has(VelocityStorage.class)) { if (user.has(VelocityStorage.class)) {
// Wait all the scheduled packets be sent // Wait all the scheduled packets be sent
@ -99,6 +100,8 @@ public class VelocityServerHandler {
VelocityStorage storage = user.get(VelocityStorage.class); VelocityStorage storage = user.get(VelocityStorage.class);
if (storage.getBossbar() == null) storage.saveServerBossBars();
if (e.getServer() != null) { if (e.getServer() != null) {
if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) { if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) {
String serverName = e.getServer().getServerInfo().getName(); String serverName = e.getServer().getServerInfo().getName();
@ -107,7 +110,20 @@ public class VelocityServerHandler {
int protocolId = ProtocolDetectorService.getProtocolId(serverName); int protocolId = ProtocolDetectorService.getProtocolId(serverName);
if (protocolId <= ProtocolVersion.MINECRAFT_1_8.getProtocol()) { // 1.8 doesn't have BossBar packet
if (storage.getBossbar() != null) {
for (UUID uuid : storage.getBossbar()) {
PacketWrapper wrapper = new PacketWrapper(0x0C, null, user);
wrapper.write(Type.UUID, uuid);
wrapper.write(Type.VAR_INT, 1); // remove
wrapper.send(Protocol1_9TO1_8.class, true, true);
}
storage.getBossbar().clear();
}
}
ProtocolInfo info = user.get(ProtocolInfo.class); ProtocolInfo info = user.get(ProtocolInfo.class);
int previousServerProtocol = info.getServerProtocolVersion();
// Refresh the pipes // Refresh the pipes
List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); List<Pair<Integer, Protocol>> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId);
@ -127,6 +143,33 @@ public class VelocityServerHandler {
// Add version-specific base Protocol // Add version-specific base Protocol
pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId)); pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId));
// Workaround 1.13 server change
Set<String> knownChannels = (Set<String>) getKnownChannels.invoke(
ReflectionUtil.invoke(
getMinecraftConnection.invoke(e.getPlayer()),
"getSessionHandler"
)
);
if (previousServerProtocol != -1) {
int id1_13 = ProtocolVersion.MINECRAFT_1_13.getProtocol();
if (previousServerProtocol < id1_13 && protocolId >= id1_13) {
ArrayList<String> newChannels = new ArrayList<>();
for (String oldChannel : knownChannels) {
newChannels.add(InventoryPackets.getNewPluginChannelId(oldChannel));
}
knownChannels.clear();
knownChannels.addAll(newChannels);
} else if (previousServerProtocol >= id1_13 && protocolId < id1_13) {
ArrayList<String> newChannels = new ArrayList<>();
for (String oldChannel : knownChannels) {
newChannels.add(InventoryPackets.getOldPluginChannelId(oldChannel));
}
knownChannels.clear();
knownChannels.addAll(newChannels);
}
}
user.put(info); user.put(info);
user.put(storage); user.put(storage);

View File

@ -5,8 +5,10 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import us.myles.ViaVersion.api.data.StoredObject; import us.myles.ViaVersion.api.data.StoredObject;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.util.ReflectionUtil;
import java.util.Set; import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.UUID; import java.util.UUID;
@Data @Data
@ -14,24 +16,24 @@ import java.util.UUID;
public class VelocityStorage extends StoredObject { public class VelocityStorage extends StoredObject {
private Player player; private Player player;
private String currentServer; private String currentServer;
private Set<UUID> bossbar; private List<UUID> bossbar;
public VelocityStorage(UserConnection user, Player player) { public VelocityStorage(UserConnection user, Player player) {
super(user); super(user);
this.player = player; this.player = player;
this.currentServer = ""; this.currentServer = "";
}
public void saveServerBossBars() {
// Get bossbar list if it's supported // Get bossbar list if it's supported
/* TODO make this work - do we need this?
try { try {
Object connection = ReflectionUtil.invoke(player, "getConnection"); Object connection = ReflectionUtil.invoke(player, "getMinecraftConnection");
Object sessionHandler = ReflectionUtil.invoke(connection, "getSessionHandler"); Object sessionHandler = ReflectionUtil.invoke(connection, "getSessionHandler");
if (sessionHandler.getClass().getSimpleName().contains("Play")) { if (sessionHandler.getClass().getSimpleName().contains("Play")) {
bossbar = (Set<UUID>) ReflectionUtil.invoke(sessionHandler, "getServerBossBars"); bossbar = (List<UUID>) ReflectionUtil.invoke(sessionHandler, "getServerBossBars");
} }
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} }
*/
} }
} }