Compare commits

..

13 Commits

19 changed files with 220 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,29 @@
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

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
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.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
@ -338,6 +339,12 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19, 0x49 ),
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(
KeepAlive.class,

View File

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

View File

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

View File

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

View File

@ -0,0 +1,78 @@
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
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( message, buf );
writeString( message, buf, 262144 );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
{
buf.writeBoolean( position == ChatMessageType.ACTION_BAR.ordinal() );

View File

@ -24,10 +24,12 @@ import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.text.Format;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
@ -85,6 +87,7 @@ import net.md_5.bungee.conf.Configuration;
import net.md_5.bungee.conf.YamlConfig;
import net.md_5.bungee.forge.ForgeConstants;
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.module.ModuleManager;
import net.md_5.bungee.netty.PipelineUtils;
@ -113,10 +116,9 @@ public class BungeeCord extends ProxyServer
@Getter
public final Configuration config = new Configuration();
/**
* Localization bundle.
* Localization formats.
*/
private ResourceBundle baseBundle;
private ResourceBundle customBundle;
private Map<String, Format> messageFormats;
public EventLoopGroup eventLoops;
/**
* locations.yml save thread.
@ -189,13 +191,6 @@ 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.
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();
// This is a workaround for quite possibly the weirdest bug I have ever encountered in my life!
@ -215,6 +210,21 @@ public class BungeeCord extends ProxyServer
logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader );
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.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) );
@ -537,32 +547,49 @@ public class BungeeCord extends ProxyServer
return ( BungeeCord.class.getPackage().getImplementationVersion() == null ) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion();
}
public void reloadMessages()
public final void reloadMessages()
{
Map<String, Format> cachedFormats = new HashMap<>();
File file = new File( "messages.properties" );
if ( file.isFile() )
{
try ( FileReader rd = new FileReader( file ) )
{
customBundle = new PropertyResourceBundle( rd );
cacheResourceBundle( cachedFormats, new PropertyResourceBundle( rd ) );
} catch ( IOException 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
public String getTranslation(String name, Object... args)
{
String translation = "<translation '" + name + "' missing>";
try
{
translation = MessageFormat.format( customBundle != null && customBundle.containsKey( name ) ? customBundle.getString( name ) : baseBundle.getString( name ), args );
} catch ( MissingResourceException ex )
{
}
return translation;
Format format = messageFormats.get( name );
return ( format != null ) ? format.format( args ) : "<translation '" + name + "' missing>";
}
@Override

View File

@ -59,6 +59,7 @@ import net.md_5.bungee.protocol.packet.Respawn;
import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
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.TabCompleteResponse;
import net.md_5.bungee.tab.TabList;
@ -678,6 +679,15 @@ public class DownstreamBridge extends PacketHandler
}
}
@Override
public void handle(ServerData serverData) throws Exception
{
serverData.setMotd( null );
serverData.setIcon( null );
con.unsafe().sendPacket( serverData );
throw CancelSendSignal.INSTANCE;
}
@Override
public String toString()
{

View File

@ -314,6 +314,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" );
this.handshake = handshake;
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
// 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}.
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.
lost_connection=[Proxy] Lost connection to server.
mojang_fail=Error occurred while contacting login servers, are they down?
lost_connection=\u00a7cProxy lost connection to server.
mojang_fail=\u00a7cError occurred while contacting login servers, are they down?
no_permission=\u00a7cYou do not have permission to execute this command!
no_server=\u00a7cThe specified server does not exist.
no_server_permission=\u00a7cYou don''t have permission to access this server.
outdated_client=Outdated client! Please use {0}
outdated_server=Outdated server! I''m still on {0}
proxy_full=Server is full!
restart=[Proxy] Proxy restarting.
outdated_client=\u00a7cOutdated client! Please use {0}
outdated_server=\u00a7cOutdated server! I''m still on {0}
proxy_full=\u00a7cServer is full!
restart=\u00a7cThe proxy server is restarting
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
total_players=Total players online: {0}
name_invalid=Username contains invalid characters.
ping_cannot_connect=\u00a7c[Bungee] Can''t connect to server.
offline_mode_player=Not authenticated with Minecraft.net
secure_profile_required=A secure profile is required to join this server.
secure_profile_expired=Secure profile expired.
secure_profile_invalid=Secure profile invalid.
name_invalid=\u00a7cUsername contains invalid characters.
ping_cannot_connect=\u00a7cCould not request status from target server.
offline_mode_player=\u00a7cNot authenticated with Minecraft.net
secure_profile_required=\u00a7cA secure profile is required to join this server.
secure_profile_expired=\u00a7cSecure profile expired.
secure_profile_invalid=\u00a7cSecure profile invalid.
message_needed=\u00a7cYou must supply a message.
error_occurred_player=\u00a7cAn error occurred while parsing your message. (Hover for details)
error_occurred_console=\u00a7cAn error occurred while parsing your message: {0}
click_to_connect=Click to connect to the server
username_needed=\u00a7cPlease follow this command by a user name.
username_needed=\u00a7cPlease follow this command by a username.
user_not_online=\u00a7cThat user is not online.
user_online_at=\u00a7a{0} \u00a7ris online at {1}
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_permission=\u00a79- {0}
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.