Compare commits

..

6 Commits

Author SHA1 Message Date
8d8ca7baf6
new event TabCompleteRequestEvent and deprecate TabCompleteEvent 2022-07-28 00:25:03 +02:00
5b3c8c9157
Add CommandsDeclareEvent to declare commands with brigadier API 2022-07-28 00:25:03 +02:00
146a29afa6
Server branding now includes the backend server name 2022-07-28 00:25:03 +02:00
ad3eb412ff
Multi-session with same Minecraft account with specific permission
Players with permission bungeecord.multiple_connect can have multiple connections with the same Minecraft account.
The UUID and player name is altered to avoid collision with other player:
UUID : xxxxxxxx-xxxx-VIxx-xxxx-xxxxxxxxxxxx
- The UUID version (V above) is now the provided version + 8 (for online player, it is 4, so it becomes C).
- The I digit will follow the index of the duplicated player : first duplicated player is 1, second one is 2.
- The name of the player will be the real player name, followed by the character "." (dot) followed by the duplication index.

Bedrock accounts connected using the Floodgate plugin will not be able to connect multiple times due to the risk of xUID collision.
2022-07-28 00:25:03 +02:00
78cee7d86c
Change projet configuration and POM for Pandacube 2022-07-28 00:24:55 +02:00
8f4cd79139
Remove modules and startup delay
We don’t need them for Pandacube
2022-07-27 23:45:28 +02:00
19 changed files with 52 additions and 220 deletions

View File

@ -14,10 +14,9 @@ jobs:
name: Java ${{ matrix.java }} name: Java ${{ matrix.java }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-java@v3 - uses: actions/setup-java@v1
with: with:
distribution: zulu
java-version: ${{ matrix.java }} java-version: ${{ matrix.java }}
- run: java -version && mvn --version - run: java -version && mvn --version
- run: mvn --activate-profiles dist --no-transfer-progress package - run: mvn --activate-profiles dist --no-transfer-progress package

View File

@ -72,7 +72,7 @@
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.33</version> <version>1.30</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -8,7 +8,7 @@ import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.PendingConnection;
/** /**
* Called when the proxy is queried for status from the server list. * Called when the proxy is pinged with packet 0xFE from the server list.
*/ */
@Data @Data
@ToString(callSuper = false) @ToString(callSuper = false)

View File

@ -28,7 +28,7 @@
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.33</version> <version>1.30</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>

View File

@ -24,7 +24,6 @@ public class BungeeLogger extends Logger
{ {
super( loggerName, null ); super( loggerName, null );
setLevel( Level.ALL ); setLevel( Level.ALL );
setUseParentHandlers( false );
try try
{ {

View File

@ -1,29 +0,0 @@
package net.md_5.bungee.log;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class LoggingForwardHandler extends Handler
{
private final Logger logger;
@Override
public void publish(LogRecord record)
{
logger.log( record );
}
@Override
public void flush()
{
}
@Override
public void close() throws SecurityException
{
}
}

View File

@ -72,7 +72,7 @@
<properties> <properties>
<build.number>unknown</build.number> <build.number>unknown</build.number>
<lombok.version>1.18.22</lombok.version> <lombok.version>1.18.22</lombok.version>
<netty.version>4.1.85.Final</netty.version> <netty.version>4.1.77.Final</netty.version>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View File

@ -30,7 +30,6 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.protocol.packet.StatusResponse;
@ -209,8 +208,4 @@ public abstract class AbstractPacketHandler
public void handle(GameState gameState) throws Exception public void handle(GameState gameState) throws Exception
{ {
} }
public void handle(ServerData serverData) throws Exception
{
}
} }

View File

@ -21,22 +21,12 @@ public abstract class DefinedPacket
public static void writeString(String s, ByteBuf buf) public static void writeString(String s, ByteBuf buf)
{ {
writeString( s, buf, Short.MAX_VALUE ); if ( s.length() > Short.MAX_VALUE )
}
public static void writeString(String s, ByteBuf buf, int maxLength)
{ {
if ( s.length() > maxLength ) throw new OverflowPacketException( "Cannot send string longer than Short.MAX_VALUE (got " + s.length() + " characters)" );
{
throw new OverflowPacketException( "Cannot send string longer than " + maxLength + " (got " + s.length() + " characters)" );
} }
byte[] b = s.getBytes( Charsets.UTF_8 ); byte[] b = s.getBytes( Charsets.UTF_8 );
if ( b.length > maxLength * 3 )
{
throw new OverflowPacketException( "Cannot send string longer than " + ( maxLength * 3 ) + " (got " + b.length + " bytes)" );
}
writeVarInt( b.length, buf ); writeVarInt( b.length, buf );
buf.writeBytes( b ); buf.writeBytes( b );
} }
@ -49,14 +39,15 @@ public abstract class DefinedPacket
public static String readString(ByteBuf buf, int maxLen) public static String readString(ByteBuf buf, int maxLen)
{ {
int len = readVarInt( buf ); int len = readVarInt( buf );
if ( len > maxLen * 3 ) if ( len > maxLen * 4 )
{ {
throw new OverflowPacketException( "Cannot receive string longer than " + maxLen * 3 + " (got " + len + " bytes)" ); throw new OverflowPacketException( "Cannot receive string longer than " + maxLen * 4 + " (got " + len + " bytes)" );
} }
String s = buf.toString( buf.readerIndex(), len, Charsets.UTF_8 ); byte[] b = new byte[ len ];
buf.readerIndex( buf.readerIndex() + len ); buf.readBytes( b );
String s = new String( b, Charsets.UTF_8 );
if ( s.length() > maxLen ) if ( s.length() > maxLen )
{ {
throw new OverflowPacketException( "Cannot receive string longer than " + maxLen + " (got " + s.length() + " characters)" ); throw new OverflowPacketException( "Cannot receive string longer than " + maxLen + " (got " + s.length() + " characters)" );
@ -284,7 +275,7 @@ public abstract class DefinedPacket
{ {
if ( buf.readBoolean() ) if ( buf.readBoolean() )
{ {
return new PlayerPublicKey( buf.readLong(), readArray( buf, 512 ), readArray( buf, 4096 ) ); return new PlayerPublicKey( buf.readLong(), readArray( buf ), readArray( buf ) );
} }
return null; return null;

View File

@ -36,7 +36,6 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.protocol.packet.StatusResponse;
@ -339,12 +338,6 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19, 0x49 ), map( ProtocolConstants.MINECRAFT_1_19, 0x49 ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C ) map( ProtocolConstants.MINECRAFT_1_19_1, 0x4C )
); );
TO_CLIENT.registerPacket(
ServerData.class,
ServerData::new,
map( ProtocolConstants.MINECRAFT_1_19, 0x3F ),
map( ProtocolConstants.MINECRAFT_1_19_1, 0x42 )
);
TO_SERVER.registerPacket( TO_SERVER.registerPacket(
KeepAlive.class, KeepAlive.class,

View File

@ -54,7 +54,7 @@ public class Chat extends DefinedPacket
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( message, buf, ( direction == ProtocolConstants.Direction.TO_CLIENT ) ? 262144 : ( protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? 256 : 100 ) ); writeString( message, buf );
if ( direction == ProtocolConstants.Direction.TO_CLIENT ) if ( direction == ProtocolConstants.Direction.TO_CLIENT )
{ {
buf.writeByte( position ); buf.writeByte( position );

View File

@ -49,7 +49,7 @@ public class ClientChat extends DefinedPacket
buf.writeBoolean( signedPreview ); buf.writeBoolean( signedPreview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{ {
chain.write( buf, direction, protocolVersion ); chain.write( buf );
} }
} }

View File

@ -67,7 +67,7 @@ public class ClientCommand extends DefinedPacket
buf.writeBoolean( signedPreview ); buf.writeBoolean( signedPreview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{ {
chain.write( buf, direction, protocolVersion ); chain.write( buf );
} }
} }

View File

@ -1,78 +0,0 @@
package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.ProtocolConstants;
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class ServerData extends DefinedPacket
{
private String motd;
private String icon;
private boolean preview;
private boolean enforceSecure;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( buf.readBoolean() )
{
motd = readString( buf, 262144 );
}
if ( buf.readBoolean() )
{
icon = readString( buf );
}
preview = buf.readBoolean();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
enforceSecure = buf.readBoolean();
}
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
if ( motd != null )
{
buf.writeBoolean( true );
writeString( motd, buf, 262144 );
} else
{
buf.writeBoolean( false );
}
if ( icon != null )
{
buf.writeBoolean( true );
writeString( icon, buf );
} else
{
buf.writeBoolean( false );
}
buf.writeBoolean( preview );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
buf.writeBoolean( enforceSecure );
}
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -30,7 +30,7 @@ public class SystemChat extends DefinedPacket
@Override @Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{ {
writeString( message, buf, 262144 ); writeString( message, buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 ) if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{ {
buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() ); buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() );

View File

@ -24,12 +24,10 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.text.Format;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
@ -87,7 +85,6 @@ import net.md_5.bungee.conf.Configuration;
import net.md_5.bungee.conf.YamlConfig; import net.md_5.bungee.conf.YamlConfig;
import net.md_5.bungee.forge.ForgeConstants; import net.md_5.bungee.forge.ForgeConstants;
import net.md_5.bungee.log.BungeeLogger; import net.md_5.bungee.log.BungeeLogger;
import net.md_5.bungee.log.LoggingForwardHandler;
import net.md_5.bungee.log.LoggingOutputStream; import net.md_5.bungee.log.LoggingOutputStream;
import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.netty.PipelineUtils;
import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.DefinedPacket;
@ -115,9 +112,10 @@ public class BungeeCord extends ProxyServer
@Getter @Getter
public final Configuration config = new Configuration(); public final Configuration config = new Configuration();
/** /**
* Localization formats. * Localization bundle.
*/ */
private Map<String, Format> messageFormats; private ResourceBundle baseBundle;
private ResourceBundle customBundle;
public EventLoopGroup eventLoops; public EventLoopGroup eventLoops;
/** /**
* locations.yml save thread. * locations.yml save thread.
@ -189,6 +187,13 @@ public class BungeeCord extends ProxyServer
// Java uses ! to indicate a resource inside of a jar/zip/other container. Running Bungee from within a directory that has a ! will cause this to muck up. // Java uses ! to indicate a resource inside of a jar/zip/other container. Running Bungee from within a directory that has a ! will cause this to muck up.
Preconditions.checkState( new File( "." ).getAbsolutePath().indexOf( '!' ) == -1, "Cannot use BungeeCord in directory with ! in path." ); Preconditions.checkState( new File( "." ).getAbsolutePath().indexOf( '!' ) == -1, "Cannot use BungeeCord in directory with ! in path." );
try
{
baseBundle = ResourceBundle.getBundle( "messages" );
} catch ( MissingResourceException ex )
{
baseBundle = ResourceBundle.getBundle( "messages", Locale.ENGLISH );
}
reloadMessages(); reloadMessages();
// This is a workaround for quite possibly the weirdest bug I have ever encountered in my life! // This is a workaround for quite possibly the weirdest bug I have ever encountered in my life!
@ -208,21 +213,6 @@ public class BungeeCord extends ProxyServer
logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader );
JDK14LoggerFactory.LOGGER = logger; JDK14LoggerFactory.LOGGER = logger;
// Before we can set the Err and Out streams to our LoggingOutputStream we also have to remove
// the default ConsoleHandler from the root logger, which writes to the err stream.
// But we still want to log these records, so we add our own handler which forwards the LogRecord to the BungeeLogger.
// This way we skip the err stream and the problem of only getting a string without context, and can handle the LogRecord itself.
// Thus improving the default bahavior for projects that log on other Logger instances not created by BungeeCord.
Logger rootLogger = Logger.getLogger( "" );
for ( Handler handler : rootLogger.getHandlers() )
{
rootLogger.removeHandler( handler );
}
rootLogger.addHandler( new LoggingForwardHandler( logger ) );
// We want everything that reaches these output streams to be handled by our logger
// since it applies a nice looking format and also writes to the logfile.
System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) ); System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) );
System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) ); System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) );
@ -541,49 +531,32 @@ public class BungeeCord extends ProxyServer
return ( BungeeCord.class.getPackage().getImplementationVersion() == null ) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion(); return ( BungeeCord.class.getPackage().getImplementationVersion() == null ) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion();
} }
public final void reloadMessages() public void reloadMessages()
{ {
Map<String, Format> cachedFormats = new HashMap<>();
File file = new File( "messages.properties" ); File file = new File( "messages.properties" );
if ( file.isFile() ) if ( file.isFile() )
{ {
try ( FileReader rd = new FileReader( file ) ) try ( FileReader rd = new FileReader( file ) )
{ {
cacheResourceBundle( cachedFormats, new PropertyResourceBundle( rd ) ); customBundle = new PropertyResourceBundle( rd );
} catch ( IOException ex ) } catch ( IOException ex )
{ {
getLogger().log( Level.SEVERE, "Could not load custom messages.properties", ex ); getLogger().log( Level.SEVERE, "Could not load custom messages.properties", ex );
} }
} }
ResourceBundle baseBundle;
try
{
baseBundle = ResourceBundle.getBundle( "messages" );
} catch ( MissingResourceException ex )
{
baseBundle = ResourceBundle.getBundle( "messages", Locale.ENGLISH );
}
cacheResourceBundle( cachedFormats, baseBundle );
messageFormats = Collections.unmodifiableMap( cachedFormats );
}
private void cacheResourceBundle(Map<String, Format> map, ResourceBundle resourceBundle)
{
Enumeration<String> keys = resourceBundle.getKeys();
while ( keys.hasMoreElements() )
{
map.computeIfAbsent( keys.nextElement(), (key) -> new MessageFormat( resourceBundle.getString( key ) ) );
}
} }
@Override @Override
public String getTranslation(String name, Object... args) public String getTranslation(String name, Object... args)
{ {
Format format = messageFormats.get( name ); String translation = "<translation '" + name + "' missing>";
return ( format != null ) ? format.format( args ) : "<translation '" + name + "' missing>"; try
{
translation = MessageFormat.format( customBundle != null && customBundle.containsKey( name ) ? customBundle.getString( name ) : baseBundle.getString( name ), args );
} catch ( MissingResourceException ex )
{
}
return translation;
} }
@Override @Override

View File

@ -64,7 +64,6 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay; import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective; import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.ServerData;
import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.tab.TabList; import net.md_5.bungee.tab.TabList;
@ -743,15 +742,6 @@ public class DownstreamBridge extends PacketHandler
return dest; return dest;
} }
@Override
public void handle(ServerData serverData) throws Exception
{
serverData.setMotd( null );
serverData.setIcon( null );
con.unsafe().sendPacket( serverData );
throw CancelSendSignal.INSTANCE;
}
@Override @Override
public String toString() public String toString()
{ {

View File

@ -323,7 +323,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" ); Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" );
this.handshake = handshake; this.handshake = handshake;
ch.setVersion( handshake.getProtocolVersion() ); ch.setVersion( handshake.getProtocolVersion() );
ch.getHandle().pipeline().remove( PipelineUtils.LEGACY_KICKER );
// Starting with FML 1.8, a "\0FML\0" token is appended to the handshake. This interferes // Starting with FML 1.8, a "\0FML\0" token is appended to the handshake. This interferes
// with Bungee's IP forwarding, so we detect it, and remove it from the host string, for now. // with Bungee's IP forwarding, so we detect it, and remove it from the host string, for now.

View File

@ -7,29 +7,29 @@ connect_kick=\u00a7cKicked whilst connecting to {0}: {1}
current_server=\u00a76You are currently connected to {0}. current_server=\u00a76You are currently connected to {0}.
fallback_kick=\u00a7cCould not connect to a default or fallback server. Incorrectly configured address/port/firewall? {0} fallback_kick=\u00a7cCould not connect to a default or fallback server. Incorrectly configured address/port/firewall? {0}
fallback_lobby=\u00a7cCould not connect to target server, you have been moved to a fallback server. fallback_lobby=\u00a7cCould not connect to target server, you have been moved to a fallback server.
lost_connection=\u00a7cProxy lost connection to server. lost_connection=[Proxy] Lost connection to server.
mojang_fail=\u00a7cError occurred while contacting login servers, are they down? mojang_fail=Error occurred while contacting login servers, are they down?
no_permission=\u00a7cYou do not have permission to execute this command! no_permission=\u00a7cYou do not have permission to execute this command!
no_server=\u00a7cThe specified server does not exist. no_server=\u00a7cThe specified server does not exist.
no_server_permission=\u00a7cYou don''t have permission to access this server. no_server_permission=\u00a7cYou don''t have permission to access this server.
outdated_client=\u00a7cOutdated client! Please use {0} outdated_client=Outdated client! Please use {0}
outdated_server=\u00a7cOutdated server! I''m still on {0} outdated_server=Outdated server! I''m still on {0}
proxy_full=\u00a7cServer is full! proxy_full=Server is full!
restart=\u00a7cThe proxy server is restarting restart=[Proxy] Proxy restarting.
server_list=\u00a76You may connect to the following servers at this time: server_list=\u00a76You may connect to the following servers at this time:
server_went_down=\u00a7cThe server you were previously on went down, you have been connected to a fallback server server_went_down=\u00a7cThe server you were previously on went down, you have been connected to a fallback server
total_players=Total players online: {0} total_players=Total players online: {0}
name_invalid=\u00a7cUsername contains invalid characters. name_invalid=Username contains invalid characters.
ping_cannot_connect=\u00a7cCould not request status from target server. ping_cannot_connect=\u00a7c[Bungee] Can''t connect to server.
offline_mode_player=\u00a7cNot authenticated with Minecraft.net offline_mode_player=Not authenticated with Minecraft.net
secure_profile_required=\u00a7cA secure profile is required to join this server. secure_profile_required=A secure profile is required to join this server.
secure_profile_expired=\u00a7cSecure profile expired. secure_profile_expired=Secure profile expired.
secure_profile_invalid=\u00a7cSecure profile invalid. secure_profile_invalid=Secure profile invalid.
message_needed=\u00a7cYou must supply a message. message_needed=\u00a7cYou must supply a message.
error_occurred_player=\u00a7cAn error occurred while parsing your message. (Hover for details) error_occurred_player=\u00a7cAn error occurred while parsing your message. (Hover for details)
error_occurred_console=\u00a7cAn error occurred while parsing your message: {0} error_occurred_console=\u00a7cAn error occurred while parsing your message: {0}
click_to_connect=Click to connect to the server click_to_connect=Click to connect to the server
username_needed=\u00a7cPlease follow this command by a username. username_needed=\u00a7cPlease follow this command by a user name.
user_not_online=\u00a7cThat user is not online. user_not_online=\u00a7cThat user is not online.
user_online_at=\u00a7a{0} \u00a7ris online at {1} user_online_at=\u00a7a{0} \u00a7ris online at {1}
send_cmd_usage=\u00a7cNot enough arguments, usage: /send <server|player|all|current> <target> send_cmd_usage=\u00a7cNot enough arguments, usage: /send <server|player|all|current> <target>
@ -38,5 +38,5 @@ you_got_summoned=\u00a76Summoned to {0} by {1}
command_perms_groups=\u00a76You have the following groups: {0} command_perms_groups=\u00a76You have the following groups: {0}
command_perms_permission=\u00a79- {0} command_perms_permission=\u00a79- {0}
command_ip=\u00a79IP of {0} is {1} command_ip=\u00a79IP of {0} is {1}
illegal_chat_characters=\u00a7cIllegal characters in chat ({0}) illegal_chat_characters=\u00a7cillegal characters in chat ({0})
kick_message=\u00a7cYou have been kicked off the proxy. kick_message=\u00a7cYou have been kicked off the proxy.