// // Decompiled by Procyon v0.5.36 // package net.md_5.bungee; import java.beans.ConstructorProperties; import net.md_5.bungee.util.CaseInsensitiveSet; import java.util.HashSet; import net.md_5.bungee.api.config.TexturePackInfo; import net.md_5.bungee.api.event.PermissionCheckEvent; import java.util.Collections; import java.net.InetSocketAddress; import net.md_5.bungee.protocol.packet.PacketFAPluginMessage; import net.md_5.bungee.protocol.packet.Packet3Chat; import net.md_5.bungee.protocol.packet.PacketFFKick; import java.util.logging.Level; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.internal.PlatformDependent; import java.net.SocketAddress; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelHandler; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.bootstrap.Bootstrap; import io.netty.util.concurrent.Future; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PipelineUtils; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import net.md_5.bungee.api.ChatColor; import java.util.Objects; import java.util.WeakHashMap; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.protocol.packet.DefinedPacket; import com.google.common.base.Preconditions; import java.util.Iterator; import java.util.Map; import net.md_5.bungee.api.connection.Connection; import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.protocol.packet.PacketCCSettings; import net.md_5.bungee.api.tab.TabListHandler; import net.md_5.bungee.api.config.ServerInfo; import java.util.Collection; import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; public final class UserConnection implements ProxiedPlayer { private final ProxyServer bungee; private final ChannelWrapper ch; private final String name; private final InitialHandler pendingConnection; private ServerConnection server; private final Object switchMutex; private final Collection pendingConnects; private TabListHandler tabList; private int sentPingId; private long sentPingTime; private int ping; private final Collection groups; private final Collection permissions; private int clientEntityId; private int serverEntityId; private PacketCCSettings settings; private final Scoreboard serverSentScoreboard; private String displayName; private final Connection.Unsafe unsafe; private final Map attachment = new WeakHashMap(); public void init() { this.displayName = this.name; try { this.tabList = (TabListHandler) this.getPendingConnection().getListener().getTabList().getDeclaredConstructor((Class[]) new Class[0]).newInstance(new Object[0]); } catch (ReflectiveOperationException ex) { throw new RuntimeException(ex); } this.tabList.init(this); final Collection g = this.bungee.getConfigurationAdapter().getGroups(this.name); for (final String s : g) { this.addGroups(s); } } @Override public void setTabList(final TabListHandler tabList) { tabList.init(this); this.tabList = tabList; } public void sendPacket(final byte[] b) { this.ch.write(b); } @Deprecated public boolean isActive() { return !this.ch.isClosed(); } @Override public void setDisplayName(final String name) { Preconditions.checkNotNull((Object) name, (Object) "displayName"); Preconditions.checkArgument(name.length() <= 16, (Object) "Display name cannot be longer than 16 characters"); this.getTabList().onDisconnect(); this.displayName = name; this.getTabList().onConnect(); } @Override public void connect(final ServerInfo target) { this.connect(target, false); } void sendDimensionSwitch() { this.unsafe().sendPacket(PacketConstants.DIM1_SWITCH); this.unsafe().sendPacket(PacketConstants.DIM2_SWITCH); } public void connectNow(final ServerInfo target) { this.sendDimensionSwitch(); this.connect(target); } public void connect(final ServerInfo info, final boolean retry) { final ServerConnectEvent event = new ServerConnectEvent(this, info); if (this.bungee.getPluginManager().callEvent(event).isCancelled()) { return; } final BungeeServerInfo target = (BungeeServerInfo) event.getTarget(); if (this.getServer() != null && Objects.equals(this.getServer().getInfo(), target)) { //this.sendMessage(ChatColor.RED + "Cannot connect to server you are already on!"); return; } if (this.pendingConnects.contains(target)) { this.sendMessage(ChatColor.RED + "Already connecting to this server!"); return; } this.pendingConnects.add(target); final ChannelInitializer initializer = new ChannelInitializer() { protected void initChannel(final Channel ch) throws Exception { PipelineUtils.BASE.initChannel(ch); ((HandlerBoss) ch.pipeline().get((Class) HandlerBoss.class)).setHandler(new ServerConnector(UserConnection.this.bungee, UserConnection.this, target)); } }; final ChannelFutureListener listener = (ChannelFutureListener) new ChannelFutureListener() { public void operationComplete(final ChannelFuture future) throws Exception { if (!future.isSuccess()) { future.channel().close(); UserConnection.this.pendingConnects.remove(target); final ServerInfo def = ProxyServer.getInstance().getServers().get(UserConnection.this.getPendingConnection().getListener().getFallbackServer()); if ((retry & target != def) && (UserConnection.this.getServer() == null || def != UserConnection.this.getServer().getInfo())) { UserConnection.this.sendMessage(UserConnection.this.bungee.getTranslation("fallback_lobby")); UserConnection.this.connect(def, false); } else if (UserConnection.this.server == null) { UserConnection.this.disconnect(UserConnection.this.bungee.getTranslation("fallback_kick") + future.cause().getClass().getName()); } else { UserConnection.this.sendMessage(UserConnection.this.bungee.getTranslation("fallback_kick") + future.cause().getClass().getName()); } } } }; final Bootstrap b = ((Bootstrap) ((Bootstrap) ((Bootstrap) ((Bootstrap) new Bootstrap().channel((Class) NioSocketChannel.class)).group((EventLoopGroup) BungeeCord.getInstance().eventLoops)).handler((ChannelHandler) initializer)) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Integer.valueOf(5000))).remoteAddress((SocketAddress) target.getAddress()); if (!PlatformDependent.isWindows()) { b.localAddress(this.getPendingConnection().getListener().getHost().getHostString(), 0); } b.connect().addListener((GenericFutureListener) listener); } @Override public synchronized void disconnect(final String reason) { if (this.ch.getHandle().isActive()) { this.bungee.getLogger().log(Level.INFO, "[" + this.getName() + "] disconnected with: " + reason); this.unsafe().sendPacket(new PacketFFKick(reason)); this.ch.close(); if (this.server != null) { this.server.disconnect("Quitting"); } } } @Override public void chat(final String message) { Preconditions.checkState(this.server != null, (Object) "Not connected to server"); this.server.getCh().write(new Packet3Chat(message)); } @Override public void sendMessage(final String message) { this.unsafe().sendPacket(new Packet3Chat(message)); } @Override public void sendMessages(final String... messages) { for (final String message : messages) { this.sendMessage(message); } } @Override public void sendData(final String channel, final byte[] data) { this.unsafe().sendPacket(new PacketFAPluginMessage(channel, data)); } @Override public InetSocketAddress getAddress() { return (InetSocketAddress) this.ch.getHandle().remoteAddress(); } @Override public Collection getGroups() { return Collections.unmodifiableCollection((Collection) this.groups); } @Override public void addGroups(final String... groups) { for (final String group : groups) { this.groups.add(group); for (final String permission : this.bungee.getConfigurationAdapter().getPermissions(group)) { this.setPermission(permission, true); } } } @Override public void removeGroups(final String... groups) { for (final String group : groups) { this.groups.remove(group); for (final String permission : this.bungee.getConfigurationAdapter().getPermissions(group)) { this.setPermission(permission, false); } } } @Override public boolean hasPermission(final String permission) { return this.bungee.getPluginManager().callEvent(new PermissionCheckEvent(this, permission, this.permissions.contains(permission))).hasPermission(); } @Override public void setPermission(final String permission, final boolean value) { if (value) { this.permissions.add(permission); } else { this.permissions.remove(permission); } } @Override public String toString() { return this.name; } @Override public void setTexturePack(final TexturePackInfo pack) { this.unsafe().sendPacket(new PacketFAPluginMessage("MC|TPack", (pack.getUrl() + "\u0000" + pack.getSize()).getBytes())); } @Override public Connection.Unsafe unsafe() { return this.unsafe; } @ConstructorProperties({ "bungee", "ch", "name", "pendingConnection" }) public UserConnection(final ProxyServer bungee, final ChannelWrapper ch, final String name, final InitialHandler pendingConnection) { this.switchMutex = new Object(); this.pendingConnects = new HashSet(); this.ping = 100; this.groups = (Collection) new CaseInsensitiveSet(); this.permissions = (Collection) new CaseInsensitiveSet(); this.serverSentScoreboard = new Scoreboard(); this.unsafe = new Connection.Unsafe() { @Override public void sendPacket(final DefinedPacket packet) { UserConnection.this.ch.write(packet); } }; if (bungee == null) { throw new NullPointerException("bungee"); } if (ch == null) { throw new NullPointerException("ch"); } if (name == null) { throw new NullPointerException("name"); } this.bungee = bungee; this.ch = ch; this.name = name; this.pendingConnection = pendingConnection; } @Override public String getName() { return this.name; } @Override public InitialHandler getPendingConnection() { return this.pendingConnection; } @Override public ServerConnection getServer() { return this.server; } public void setServer(final ServerConnection server) { this.server = server; } public Object getSwitchMutex() { return this.switchMutex; } public Collection getPendingConnects() { return this.pendingConnects; } @Override public TabListHandler getTabList() { return this.tabList; } public int getSentPingId() { return this.sentPingId; } public void setSentPingId(final int sentPingId) { this.sentPingId = sentPingId; } public long getSentPingTime() { return this.sentPingTime; } public void setSentPingTime(final long sentPingTime) { this.sentPingTime = sentPingTime; } @Override public int getPing() { return this.ping; } public void setPing(final int ping) { this.ping = ping; } public int getClientEntityId() { return this.clientEntityId; } public void setClientEntityId(final int clientEntityId) { this.clientEntityId = clientEntityId; } public int getServerEntityId() { return this.serverEntityId; } public void setServerEntityId(final int serverEntityId) { this.serverEntityId = serverEntityId; } public PacketCCSettings getSettings() { return this.settings; } public void setSettings(final PacketCCSettings settings) { this.settings = settings; } public Scoreboard getServerSentScoreboard() { return this.serverSentScoreboard; } @Override public String getDisplayName() { return this.displayName; } @Override public Map getAttachment() { return attachment; } }