diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index 40259f23b..c1d8dda58 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -36,7 +36,6 @@ public class UserConnection { // Used for handling warnings (over time) private int secondsObserved = 0; private int warnings = 0; - private ReadWriteLock velocityLock = new ReentrantReadWriteLock(); public UserConnection(Channel channel) { this.channel = channel; diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java index 1b4baa8d4..92fa49b72 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java @@ -35,7 +35,6 @@ public class VelocityDecodeHandler extends MessageToMessageDecoder { if (info.handlePPS()) return; } - info.getVelocityLock().readLock().lock(); if (info.isActive()) { // Handle ID int id = Type.VAR_INT.read(bytebuf); @@ -58,13 +57,11 @@ public class VelocityDecodeHandler extends MessageToMessageDecoder { bytebuf.clear(); // Release Packet, be free! newPacket.release(); - info.getVelocityLock().readLock().unlock(); throw e; } } else { bytebuf.retain(); } - info.getVelocityLock().readLock().unlock(); out.add(bytebuf); } diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java index bf2c32133..9ce0483f7 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java @@ -25,7 +25,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; public class VelocityServerHandler { private static Method setProtocolVersion; @@ -75,113 +77,103 @@ public class VelocityServerHandler { @Subscribe(order = PostOrder.LATE) public void connectedEvent(ServerConnectedEvent e) { - try { - checkServerChange(e, Via.getManager().getConnection(e.getPlayer().getUniqueId())); - } catch (Exception e1) { - e1.printStackTrace(); - } + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); + CompletableFuture.runAsync(() -> { + try { + checkServerChange(e, Via.getManager().getConnection(e.getPlayer().getUniqueId())); + } catch (Exception e1) { + e1.printStackTrace(); + } + }, user.getChannel().eventLoop()).join(); } public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception { if (user == null) return; // Handle server/version change if (user.has(VelocityStorage.class)) { - // Wait all the scheduled packets be sent - Semaphore semaphore = new Semaphore(1); - semaphore.acquireUninterruptibly(); - user.getChannel().eventLoop().submit((Runnable) semaphore::release); - semaphore.acquireUninterruptibly(); - semaphore.release(); + VelocityStorage storage = user.get(VelocityStorage.class); - user.getVelocityLock().writeLock().lock(); + if (e.getServer() != null) { + if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) { + String serverName = e.getServer().getServerInfo().getName(); - try { - VelocityStorage storage = user.get(VelocityStorage.class); + storage.setCurrentServer(serverName); - if (e.getServer() != null) { - if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) { - String serverName = e.getServer().getServerInfo().getName(); + int protocolId = ProtocolDetectorService.getProtocolId(serverName); - storage.setCurrentServer(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(); + 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); - int previousServerProtocol = info.getServerProtocolVersion(); - - // Refresh the pipes - List> 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 prot : protocols) { - pipeline.add(prot.getValue()); - } - } - - info.setServerProtocolVersion(protocolId); - // Add version-specific base Protocol - pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId)); - - Collection knownChannels = (Collection) getKnownChannels.invoke(e.getPlayer()); - if (previousServerProtocol != -1) { - int id1_13 = ProtocolVersion.MINECRAFT_1_13.getProtocol(); - if (previousServerProtocol < id1_13 && protocolId >= id1_13) { - List newChannels = new ArrayList<>(); - for (String oldChannel : knownChannels) { - String transformed = InventoryPackets.getNewPluginChannelId(oldChannel); - if (transformed != null) { - newChannels.add(transformed); - } - } - knownChannels.clear(); - knownChannels.addAll(newChannels); - } else if (previousServerProtocol >= id1_13 && protocolId < id1_13) { - List newChannels = new ArrayList<>(); - for (String oldChannel : knownChannels) { - String transformed = InventoryPackets.getOldPluginChannelId(oldChannel); - if (transformed != null) { - newChannels.add(transformed); - } - } - knownChannels.clear(); - knownChannels.addAll(newChannels); - } - } - - user.put(info); - user.put(storage); - - user.setActive(protocols != null); - - // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. - for (Protocol protocol : pipeline.pipes()) { - protocol.init(user); - } - - Object connection = getMinecraftConnection.invoke(e.getPlayer()); - ProtocolVersion version = (ProtocolVersion) getNextProtocolVersion.invoke(connection); - setProtocolVersion.invoke(connection, version); } + + ProtocolInfo info = user.get(ProtocolInfo.class); + int previousServerProtocol = info.getServerProtocolVersion(); + + // Refresh the pipes + List> 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 prot : protocols) { + pipeline.add(prot.getValue()); + } + } + + info.setServerProtocolVersion(protocolId); + // Add version-specific base Protocol + pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId)); + + Collection knownChannels = (Collection) getKnownChannels.invoke(e.getPlayer()); + if (previousServerProtocol != -1) { + int id1_13 = ProtocolVersion.MINECRAFT_1_13.getProtocol(); + if (previousServerProtocol < id1_13 && protocolId >= id1_13) { + List newChannels = new ArrayList<>(); + for (String oldChannel : knownChannels) { + String transformed = InventoryPackets.getNewPluginChannelId(oldChannel); + if (transformed != null) { + newChannels.add(transformed); + } + } + knownChannels.clear(); + knownChannels.addAll(newChannels); + } else if (previousServerProtocol >= id1_13 && protocolId < id1_13) { + List newChannels = new ArrayList<>(); + for (String oldChannel : knownChannels) { + String transformed = InventoryPackets.getOldPluginChannelId(oldChannel); + if (transformed != null) { + newChannels.add(transformed); + } + } + knownChannels.clear(); + knownChannels.addAll(newChannels); + } + } + + user.put(info); + user.put(storage); + + user.setActive(protocols != null); + + // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. + for (Protocol protocol : pipeline.pipes()) { + protocol.init(user); + } + + Object connection = getMinecraftConnection.invoke(e.getPlayer()); + ProtocolVersion version = (ProtocolVersion) getNextProtocolVersion.invoke(connection); + setProtocolVersion.invoke(connection, version); } - } finally { - user.getVelocityLock().writeLock().unlock(); } } }