1
0
Fork 0

Compare commits

...

28 Commits

Author SHA1 Message Date
dependabot[bot] 3e9a7e45c4
#3616: Bump io.netty:netty-bom from 4.1.106.Final to 4.1.107.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.106.Final to 4.1.107.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.106.Final...netty-4.1.107.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-17 13:41:16 +11:00
dependabot[bot] f6c5332c1a
#3613: Bump org.junit.jupiter:junit-jupiter from 5.10.1 to 5.10.2
Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.1 to 5.10.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.10.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-17 13:41:00 +11:00
md_5 d0fa62d424
Minecraft 24w06a support 2024-02-10 12:26:38 +11:00
md_5 464ed0184c
Improve cookie support during login 2024-02-10 12:26:26 +11:00
md_5 eda268b481
Fix 24w05b spectate packet ID 2024-02-06 07:03:49 +11:00
md_5 3e1007527c
#3612: Error when disconnecting player on PostLoginEvent 2024-02-04 11:47:30 +11:00
md_5 b52b14696c
Add PendingConnection#isTransferred API method 2024-02-04 11:35:20 +11:00
md_5 94d5b0d03c
Minecraft 24w05b support 2024-02-03 15:34:08 +11:00
Diogo Correia c3f228f626
#3610, 3611: inverted isEmpty method on ComponentStyle 2024-02-02 11:16:46 +11:00
Outfluencer 02c5c1ee76
#3602: Minecraft 24w04a support 2024-01-30 07:25:22 +11:00
md_5 c69acf728c
Add JetBrains java-annotations 2024-01-29 20:29:58 +11:00
md_5 a1cd694363
Bump version to 1.20-R0.3-SNAPSHOT 2024-01-20 08:41:57 +11:00
md_5 3e2bc8e2d7
Release 1.20-R0.2 2024-01-20 08:37:37 +11:00
dependabot[bot] ad7163d2d6
#3600: Bump io.netty:netty-bom from 4.1.104.Final to 4.1.106.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.104.Final to 4.1.106.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.104.Final...netty-4.1.106.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-20 08:34:51 +11:00
Valentine 19918c694f
#3594: Fix missing ComponentStyleSerializer 2024-01-09 16:09:55 +11:00
md_5 21c8f2815a
Decode ComponentStyle over network as appropriate 2024-01-06 16:35:33 +11:00
Parker Hawke 737d545fb6
#3569: Separate component styling into a ComponentStyle class 2024-01-06 16:35:30 +11:00
dependabot[bot] b23a51825e
#3588: Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.12.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.12.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-26 08:47:34 +11:00
md_5 708c5b6254
#3585: Fix mistake converting certain NBT to JSON in previous commit 2023-12-22 22:06:23 +11:00
md_5 f5af11193c
#3584: Handle conversion of mixed NBT lists to json 2023-12-22 18:01:30 +11:00
md_5 b711e4033f
#3578: bungeecord-chat does not support array format UUIDs 2023-12-19 19:54:03 +11:00
Outfluencer 3deaaadc3a
#3574: "VarInt too big" should be an OverflowPacketException 2023-12-16 11:29:03 +11:00
dependabot[bot] 51b9a6b0b8
#3577: Bump io.netty:netty-bom from 4.1.101.Final to 4.1.104.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.101.Final to 4.1.104.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.101.Final...netty-4.1.104.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-16 11:28:36 +11:00
dependabot[bot] 1a807731a5
#3567: Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.2 to 3.6.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.2...maven-javadoc-plugin-3.6.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-10 11:00:38 +11:00
dependabot[bot] 772ad9951f
#3566: Bump actions/setup-java from 3 to 4
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3 to 4.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-10 11:00:24 +11:00
dependabot[bot] 2431c40a5c
#3562: Bump io.netty:netty-bom from 4.1.100.Final to 4.1.101.Final
Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.100.Final to 4.1.101.Final.
- [Commits](https://github.com/netty/netty/compare/netty-4.1.100.Final...netty-4.1.101.Final)

---
updated-dependencies:
- dependency-name: io.netty:netty-bom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-10 11:00:05 +11:00
dependabot[bot] 8144ae8d7b
#3555: Bump com.mysql:mysql-connector-j from 8.1.0 to 8.2.0
Bumps [com.mysql:mysql-connector-j](https://github.com/mysql/mysql-connector-j) from 8.1.0 to 8.2.0.
- [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/8.x/CHANGES)
- [Commits](https://github.com/mysql/mysql-connector-j/compare/8.1.0...8.2.0)

---
updated-dependencies:
- dependency-name: com.mysql:mysql-connector-j
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-10 10:59:52 +11:00
md_5 0757c39a6f
Attempt upgrade of resolver libraries 2023-12-10 10:56:39 +11:00
56 changed files with 1453 additions and 289 deletions

View File

@ -13,10 +13,9 @@ updates:
- dependency-name: "com.puppycrawl.tools:checkstyle"
# Newer versions have issues, see #1909 and #2050
- dependency-name: "jline:jline"
# Later versions of these Maven dependencies are incompatible and require careful management - see SPIGOT-7400
# Needs to be synchronised with maven-resolver-provider dependencies
- dependency-name: "org.apache.maven.resolver:maven-resolver-connector-basic"
- dependency-name: "org.apache.maven.resolver:maven-resolver-transport-http"
- dependency-name: "org.apache.maven:maven-resolver-provider"
# Used with maven-resolver dependencies; 2.0 update breaks other providers
- dependency-name: "org.slf4j:slf4j-api"
update-types: ["version-update:semver-major"]

View File

@ -15,7 +15,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
- uses: actions/setup-java@v4
with:
distribution: zulu
java-version: ${{ matrix.java }}

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-API</name>
@ -51,21 +51,21 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.8.5</version>
<version>3.9.6</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.7.3</version>
<version>1.9.18</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.7.3</version>
<version>1.9.18</version>
<!-- not part of the API proper -->
<scope>provided</scope>
</dependency>

View File

@ -2,7 +2,9 @@ package net.md_5.bungee.api.connection;
import java.net.InetSocketAddress;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import net.md_5.bungee.api.config.ListenerInfo;
import org.jetbrains.annotations.ApiStatus;
/**
* Represents a user attempting to log into the proxy.
@ -89,4 +91,26 @@ public interface PendingConnection extends Connection
* @return Whether the client is using a legacy client.
*/
boolean isLegacy();
/**
* Gets if this connection has been transferred from another server.
*
* @return true if the connection has been transferred
*/
@ApiStatus.Experimental
boolean isTransferred();
/**
* Retrieves a cookie from this pending connection.
*
* @param cookie the resource location of the cookie, for example
* "bungeecord:my_cookie"
* @return a {@link CompletableFuture} that will be completed when the
* Cookie response is received. If the cookie is not set in the client, the
* {@link CompletableFuture} will complete with a null value
* @throws IllegalStateException if the player's version is not at least
* 1.20.5
*/
@ApiStatus.Experimental
CompletableFuture<byte[]> retrieveCookie(String cookie);
}

View File

@ -3,6 +3,7 @@ package net.md_5.bungee.api.connection;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.CommandSender;
@ -13,6 +14,7 @@ import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.md_5.bungee.api.score.Scoreboard;
import org.jetbrains.annotations.ApiStatus;
/**
* Represents a player whose connection is being connected to somewhere else,
@ -339,4 +341,45 @@ public interface ProxiedPlayer extends Connection, CommandSender
*/
@Deprecated
Scoreboard getScoreboard();
/**
* Retrieves a cookie from this player.
*
* @param cookie the resource location of the cookie, for example
* "bungeecord:my_cookie"
* @return a {@link CompletableFuture} that will be completed when the
* Cookie response is received. If the cookie is not set in the client, the
* {@link CompletableFuture} will complete with a null value
* @throws IllegalStateException if the player's version is not at least
* 1.20.5
*/
@ApiStatus.Experimental
CompletableFuture<byte[]> retrieveCookie(String cookie);
/**
* Stores a cookie in this player's client.
*
* @param cookie the resource location of the cookie, for example
* "bungeecord:my_cookie"
* @param data the data to store in the cookie
* @throws IllegalStateException if the player's version is not at least
* 1.20.5
*/
@ApiStatus.Experimental
void storeCookie(String cookie, byte[] data);
/**
* Requests this player to connect to a different server specified by host
* and port.
*
* This is a client-side transfer - host and port should not specify a
* BungeeCord backend server.
*
* @param host the host of the server to transfer to
* @param port the port of the server to transfer to
* @throws IllegalStateException if the players version is not at least
* 1.20.5
*/
@ApiStatus.Experimental
void transfer(String host, int port);
}

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Bootstrap</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Chat</name>

View File

@ -20,38 +20,10 @@ public abstract class BaseComponent
BaseComponent parent;
/**
* The color of this component and any child components (unless overridden)
* The component's style.
*/
private ChatColor color;
/**
* The font of this component and any child components (unless overridden)
*/
private String font;
/**
* Whether this component and any child components (unless overridden) is
* bold
*/
private Boolean bold;
/**
* Whether this component and any child components (unless overridden) is
* italic
*/
private Boolean italic;
/**
* Whether this component and any child components (unless overridden) is
* underlined
*/
private Boolean underlined;
/**
* Whether this component and any child components (unless overridden) is
* strikethrough
*/
private Boolean strikethrough;
/**
* Whether this component and any child components (unless overridden) is
* obfuscated
*/
private Boolean obfuscated;
@Getter
private ComponentStyle style = new ComponentStyle();
/**
* The text to insert into the chat when this component (and child
* components) are clicked while pressing the shift key
@ -153,31 +125,31 @@ public abstract class BaseComponent
}
if ( retention == FormatRetention.FORMATTING || retention == FormatRetention.ALL )
{
if ( replace || color == null )
if ( replace || !style.hasColor() )
{
setColor( component.getColorRaw() );
}
if ( replace || font == null )
if ( replace || !style.hasFont() )
{
setFont( component.getFontRaw() );
}
if ( replace || bold == null )
if ( replace || style.isBoldRaw() == null )
{
setBold( component.isBoldRaw() );
}
if ( replace || italic == null )
if ( replace || style.isItalicRaw() == null )
{
setItalic( component.isItalicRaw() );
}
if ( replace || underlined == null )
if ( replace || style.isUnderlinedRaw() == null )
{
setUnderlined( component.isUnderlinedRaw() );
}
if ( replace || strikethrough == null )
if ( replace || style.isStrikethroughRaw() == null )
{
setStrikethrough( component.isStrikethroughRaw() );
}
if ( replace || obfuscated == null )
if ( replace || style.isObfuscatedRaw() == null )
{
setObfuscated( component.isObfuscatedRaw() );
}
@ -266,6 +238,29 @@ public abstract class BaseComponent
return builder.toString();
}
/**
* Set the {@link ComponentStyle} for this component.
* <p>
* Unlike {@link #applyStyle(ComponentStyle)}, this method will overwrite
* all style values on this component.
*
* @param style the style to set, or null to set all style values to default
*/
public void setStyle(ComponentStyle style)
{
this.style = ( style != null ) ? style.clone() : new ComponentStyle();
}
/**
* Set this component's color.
*
* @param color the component color, or null to use the default
*/
public void setColor(ChatColor color)
{
this.style.setColor( color );
}
/**
* Returns the color of this component. This uses the parent's color if this
* component doesn't have one. {@link net.md_5.bungee.api.ChatColor#WHITE}
@ -275,7 +270,7 @@ public abstract class BaseComponent
*/
public ChatColor getColor()
{
if ( color == null )
if ( !style.hasColor() )
{
if ( parent == null )
{
@ -283,7 +278,7 @@ public abstract class BaseComponent
}
return parent.getColor();
}
return color;
return style.getColor();
}
/**
@ -294,7 +289,17 @@ public abstract class BaseComponent
*/
public ChatColor getColorRaw()
{
return color;
return style.getColor();
}
/**
* Set this component's font.
*
* @param font the font to set, or null to use the default
*/
public void setFont(String font)
{
this.style.setFont( font );
}
/**
@ -305,7 +310,7 @@ public abstract class BaseComponent
*/
public String getFont()
{
if ( font == null )
if ( !style.hasFont() )
{
if ( parent == null )
{
@ -313,7 +318,7 @@ public abstract class BaseComponent
}
return parent.getFont();
}
return font;
return style.getFont();
}
/**
@ -324,7 +329,17 @@ public abstract class BaseComponent
*/
public String getFontRaw()
{
return font;
return style.getFont();
}
/**
* Set whether or not this component is bold.
*
* @param bold the new bold state, or null to use the default
*/
public void setBold(Boolean bold)
{
this.style.setBold( bold );
}
/**
@ -336,11 +351,11 @@ public abstract class BaseComponent
*/
public boolean isBold()
{
if ( bold == null )
if ( style.isBoldRaw() == null )
{
return parent != null && parent.isBold();
}
return bold;
return style.isBold();
}
/**
@ -351,7 +366,17 @@ public abstract class BaseComponent
*/
public Boolean isBoldRaw()
{
return bold;
return style.isBoldRaw();
}
/**
* Set whether or not this component is italic.
*
* @param italic the new italic state, or null to use the default
*/
public void setItalic(Boolean italic)
{
this.style.setItalic( italic );
}
/**
@ -363,11 +388,11 @@ public abstract class BaseComponent
*/
public boolean isItalic()
{
if ( italic == null )
if ( style.isItalicRaw() == null )
{
return parent != null && parent.isItalic();
}
return italic;
return style.isItalic();
}
/**
@ -378,7 +403,17 @@ public abstract class BaseComponent
*/
public Boolean isItalicRaw()
{
return italic;
return style.isItalicRaw();
}
/**
* Set whether or not this component is underlined.
*
* @param underlined the new underlined state, or null to use the default
*/
public void setUnderlined(Boolean underlined)
{
this.style.setUnderlined( underlined );
}
/**
@ -390,11 +425,11 @@ public abstract class BaseComponent
*/
public boolean isUnderlined()
{
if ( underlined == null )
if ( style.isUnderlinedRaw() == null )
{
return parent != null && parent.isUnderlined();
}
return underlined;
return style.isUnderlined();
}
/**
@ -405,7 +440,18 @@ public abstract class BaseComponent
*/
public Boolean isUnderlinedRaw()
{
return underlined;
return style.isUnderlinedRaw();
}
/**
* Set whether or not this component is strikethrough.
*
* @param strikethrough the new strikethrough state, or null to use the
* default
*/
public void setStrikethrough(Boolean strikethrough)
{
this.style.setStrikethrough( strikethrough );
}
/**
@ -417,11 +463,11 @@ public abstract class BaseComponent
*/
public boolean isStrikethrough()
{
if ( strikethrough == null )
if ( style.isStrikethroughRaw() == null )
{
return parent != null && parent.isStrikethrough();
}
return strikethrough;
return style.isStrikethrough();
}
/**
@ -432,7 +478,17 @@ public abstract class BaseComponent
*/
public Boolean isStrikethroughRaw()
{
return strikethrough;
return style.isStrikethroughRaw();
}
/**
* Set whether or not this component is obfuscated.
*
* @param obfuscated the new obfuscated state, or null to use the default
*/
public void setObfuscated(Boolean obfuscated)
{
this.style.setObfuscated( obfuscated );
}
/**
@ -444,11 +500,11 @@ public abstract class BaseComponent
*/
public boolean isObfuscated()
{
if ( obfuscated == null )
if ( style.isObfuscatedRaw() == null )
{
return parent != null && parent.isObfuscated();
}
return obfuscated;
return style.isObfuscated();
}
/**
@ -459,7 +515,48 @@ public abstract class BaseComponent
*/
public Boolean isObfuscatedRaw()
{
return obfuscated;
return style.isObfuscatedRaw();
}
/**
* Apply the style from the given {@link ComponentStyle} to this component.
* <p>
* Any style values that have been explicitly set in the style will be
* applied to this component. If a value is not set in the style, it will
* not override the style set in this component.
*
* @param style the style to apply
*/
public void applyStyle(ComponentStyle style)
{
if ( style.hasColor() )
{
setColor( style.getColor() );
}
if ( style.hasFont() )
{
setFont( style.getFont() );
}
if ( style.isBoldRaw() != null )
{
setBold( style.isBoldRaw() );
}
if ( style.isItalicRaw() != null )
{
setItalic( style.isItalicRaw() );
}
if ( style.isUnderlinedRaw() != null )
{
setUnderlined( style.isUnderlinedRaw() );
}
if ( style.isStrikethroughRaw() != null )
{
setStrikethrough( style.isStrikethroughRaw() );
}
if ( style.isObfuscatedRaw() != null )
{
setObfuscated( style.isObfuscatedRaw() );
}
}
public void setExtra(List<BaseComponent> components)
@ -498,6 +595,16 @@ public abstract class BaseComponent
extra.add( component );
}
/**
* Returns whether the component has any styling applied to it.
*
* @return Whether any styling is applied
*/
public boolean hasStyle()
{
return !style.isEmpty();
}
/**
* Returns whether the component has any formatting or events applied to it
*
@ -505,10 +612,8 @@ public abstract class BaseComponent
*/
public boolean hasFormatting()
{
return color != null || font != null || bold != null
|| italic != null || underlined != null
|| strikethrough != null || obfuscated != null
|| insertion != null || hoverEvent != null || clickEvent != null;
return hasStyle() || insertion != null
|| hoverEvent != null || clickEvent != null;
}
/**

View File

@ -423,6 +423,18 @@ public final class ComponentBuilder
return this;
}
/**
* Applies the provided {@link ComponentStyle} to the current part.
*
* @param style the style to apply
* @return this ComponentBuilder for chaining
*/
public ComponentBuilder style(ComponentStyle style)
{
getCurrentComponent().applyStyle( style );
return this;
}
/**
* Sets the insertion text for the current part.
*

View File

@ -0,0 +1,234 @@
package net.md_5.bungee.api.chat;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.md_5.bungee.api.ChatColor;
/**
* Represents a style that may be applied to a {@link BaseComponent}.
*/
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public final class ComponentStyle implements Cloneable
{
/**
* The color of this style.
*/
private ChatColor color;
/**
* The font of this style.
*/
private String font;
/**
* Whether this style is bold.
*/
private Boolean bold;
/**
* Whether this style is italic.
*/
private Boolean italic;
/**
* Whether this style is underlined.
*/
private Boolean underlined;
/**
* Whether this style is strikethrough.
*/
private Boolean strikethrough;
/**
* Whether this style is obfuscated.
*/
private Boolean obfuscated;
/**
* Returns the color of this style. May return null.
*
* @return the color of this style, or null if default color
*/
public ChatColor getColor()
{
return color;
}
/**
* Returns whether or not this style has a color set.
*
* @return whether a color is set
*/
public boolean hasColor()
{
return ( color != null );
}
/**
* Returns the font of this style. May return null.
*
* @return the font of this style, or null if default font
*/
public String getFont()
{
return font;
}
/**
* Returns whether or not this style has a font set.
*
* @return whether a font is set
*/
public boolean hasFont()
{
return ( font != null );
}
/**
* Returns whether this style is bold.
*
* @return whether the style is bold
*/
public boolean isBold()
{
return ( bold != null ) && bold.booleanValue();
}
/**
* Returns whether this style is bold. May return null.
*
* @return whether the style is bold, or null if not set
*/
public Boolean isBoldRaw()
{
return bold;
}
/**
* Returns whether this style is italic. May return null.
*
* @return whether the style is italic
*/
public boolean isItalic()
{
return ( italic != null ) && italic.booleanValue();
}
/**
* Returns whether this style is italic. May return null.
*
* @return whether the style is italic, or null if not set
*/
public Boolean isItalicRaw()
{
return italic;
}
/**
* Returns whether this style is underlined.
*
* @return whether the style is underlined
*/
public boolean isUnderlined()
{
return ( underlined != null ) && underlined.booleanValue();
}
/**
* Returns whether this style is underlined. May return null.
*
* @return whether the style is underlined, or null if not set
*/
public Boolean isUnderlinedRaw()
{
return underlined;
}
/**
* Returns whether this style is strikethrough
*
* @return whether the style is strikethrough
*/
public boolean isStrikethrough()
{
return ( strikethrough != null ) && strikethrough.booleanValue();
}
/**
* Returns whether this style is strikethrough. May return null.
*
* @return whether the style is strikethrough, or null if not set
*/
public Boolean isStrikethroughRaw()
{
return strikethrough;
}
/**
* Returns whether this style is obfuscated.
*
* @return whether the style is obfuscated
*/
public boolean isObfuscated()
{
return ( obfuscated != null ) && obfuscated.booleanValue();
}
/**
* Returns whether this style is obfuscated. May return null.
*
* @return whether the style is obfuscated, or null if not set
*/
public Boolean isObfuscatedRaw()
{
return obfuscated;
}
/**
* Returns whether this style has no formatting explicitly set.
*
* @return true if no value is set, false if at least one is set
*/
public boolean isEmpty()
{
return color == null && font == null && bold == null
&& italic == null && underlined == null
&& strikethrough == null && obfuscated == null;
}
@Override
public ComponentStyle clone()
{
return new ComponentStyle( color, font, bold, italic, underlined, strikethrough, obfuscated );
}
/**
* Get a new {@link ComponentStyleBuilder}.
*
* @return the builder
*/
public static ComponentStyleBuilder builder()
{
return new ComponentStyleBuilder();
}
/**
* Get a new {@link ComponentStyleBuilder} with values initialized to the
* style values of the supplied {@link ComponentStyle}.
*
* @param other the component style whose values to copy into the builder
* @return the builder
*/
public static ComponentStyleBuilder builder(ComponentStyle other)
{
return new ComponentStyleBuilder()
.color( other.color )
.font( other.font )
.bold( other.bold )
.italic( other.italic )
.underlined( other.underlined )
.strikethrough( other.strikethrough )
.obfuscated( other.obfuscated );
}
}

View File

@ -0,0 +1,126 @@
package net.md_5.bungee.api.chat;
import net.md_5.bungee.api.ChatColor;
/**
* <p>
* ComponentStyleBuilder simplifies creating component styles by allowing the
* use of a chainable builder.
* </p>
* <pre>
* ComponentStyle style = ComponentStyle.builder()
* .color(ChatColor.RED)
* .font("custom:font")
* .bold(true).italic(true).create();
*
* BaseComponent component = new ComponentBuilder("Hello world").style(style).create();
* // Or it can be used directly on a component
* TextComponent text = new TextComponent("Hello world");
* text.applyStyle(style);
* </pre>
*
* @see ComponentStyle#builder()
* @see ComponentStyle#builder(ComponentStyle)
*/
public final class ComponentStyleBuilder
{
private ChatColor color;
private String font;
private Boolean bold, italic, underlined, strikethrough, obfuscated;
/**
* Set the style color.
*
* @param color the color to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder color(ChatColor color)
{
this.color = color;
return this;
}
/**
* Set the style font.
*
* @param font the font key to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder font(String font)
{
this.font = font;
return this;
}
/**
* Set the style's bold property.
*
* @param bold the bold value to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder bold(Boolean bold)
{
this.bold = bold;
return this;
}
/**
* Set the style's italic property.
*
* @param italic the italic value to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder italic(Boolean italic)
{
this.italic = italic;
return this;
}
/**
* Set the style's underlined property.
*
* @param underlined the underlined value to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder underlined(Boolean underlined)
{
this.underlined = underlined;
return this;
}
/**
* Set the style's strikethrough property.
*
* @param strikethrough the strikethrough value to set, or null to use the
* default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder strikethrough(Boolean strikethrough)
{
this.strikethrough = strikethrough;
return this;
}
/**
* Set the style's obfuscated property.
*
* @param obfuscated the obfuscated value to set, or null to use the default
* @return this ComponentStyleBuilder for chaining
*/
public ComponentStyleBuilder obfuscated(Boolean obfuscated)
{
this.obfuscated = obfuscated;
return this;
}
/**
* Build the {@link ComponentStyle} using the values set in this builder.
*
* @return the created ComponentStyle
*/
public ComponentStyle build()
{
return new ComponentStyle( color, font, bold, italic, underlined, strikethrough, obfuscated );
}
}

View File

@ -8,6 +8,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.UUID;
import net.md_5.bungee.api.chat.BaseComponent;
public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserializer<Entity>
@ -18,9 +19,19 @@ public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserialize
{
JsonObject value = element.getAsJsonObject();
String idString;
JsonElement id = value.get( "id" );
if ( id.isJsonArray() )
{
idString = parseUUID( context.deserialize( id, int[].class ) ).toString();
} else
{
idString = id.getAsString();
}
return new Entity(
( value.has( "type" ) ) ? value.get( "type" ).getAsString() : null,
value.get( "id" ).getAsString(),
idString,
( value.has( "name" ) ) ? context.deserialize( value.get( "name" ), BaseComponent.class ) : null
);
}
@ -37,4 +48,9 @@ public class EntitySerializer implements JsonSerializer<Entity>, JsonDeserialize
}
return object;
}
private static UUID parseUUID(int[] array)
{
return new UUID( (long) array[0] << 32 | (long) array[1] & 0XFFFFFFFFL, (long) array[2] << 32 | (long) array[3] & 0XFFFFFFFFL );
}
}

View File

@ -4,73 +4,25 @@ import com.google.common.base.Preconditions;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Locale;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.hover.content.Content;
public class BaseComponentSerializer
{
private static boolean getAsBoolean(JsonElement el)
{
if ( el.isJsonPrimitive() )
{
JsonPrimitive primitive = (JsonPrimitive) el;
if ( primitive.isBoolean() )
{
return primitive.getAsBoolean();
}
if ( primitive.isNumber() )
{
Number number = primitive.getAsNumber();
if ( number instanceof Byte )
{
return number.byteValue() != 0;
}
}
}
return false;
}
protected void deserialize(JsonObject object, BaseComponent component, JsonDeserializationContext context)
{
if ( object.has( "bold" ) )
{
component.setBold( getAsBoolean( object.get( "bold" ) ) );
}
if ( object.has( "italic" ) )
{
component.setItalic( getAsBoolean( object.get( "italic" ) ) );
}
if ( object.has( "underlined" ) )
{
component.setUnderlined( getAsBoolean( object.get( "underlined" ) ) );
}
if ( object.has( "strikethrough" ) )
{
component.setStrikethrough( getAsBoolean( object.get( "strikethrough" ) ) );
}
if ( object.has( "obfuscated" ) )
{
component.setObfuscated( getAsBoolean( object.get( "obfuscated" ) ) );
}
if ( object.has( "color" ) )
{
component.setColor( ChatColor.of( object.get( "color" ).getAsString() ) );
}
component.applyStyle( context.deserialize( object, ComponentStyle.class ) );
if ( object.has( "insertion" ) )
{
component.setInsertion( object.get( "insertion" ).getAsString() );
@ -90,59 +42,48 @@ public class BaseComponentSerializer
HoverEvent hoverEvent = null;
HoverEvent.Action action = HoverEvent.Action.valueOf( event.get( "action" ).getAsString().toUpperCase( Locale.ROOT ) );
for ( String type : Arrays.asList( "value", "contents" ) )
if ( event.has( "value" ) )
{
if ( !event.has( type ) )
{
continue;
}
JsonElement contents = event.get( type );
try
{
JsonElement contents = event.get( "value" );
// Plugins previously had support to pass BaseComponent[] into any action.
// If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
BaseComponent[] components;
if ( contents.isJsonArray() )
{
components = context.deserialize( contents, BaseComponent[].class );
} else
{
components = new BaseComponent[]
{
context.deserialize( contents, BaseComponent.class )
};
}
hoverEvent = new HoverEvent( action, components );
} catch ( JsonParseException ex )
// Plugins previously had support to pass BaseComponent[] into any action.
// If the GSON is possible to be parsed as BaseComponent, attempt to parse as so.
BaseComponent[] components;
if ( contents.isJsonArray() )
{
Content[] list;
if ( contents.isJsonArray() )
components = context.deserialize( contents, BaseComponent[].class );
} else
{
components = new BaseComponent[]
{
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
} else
{
list = new Content[]
{
context.deserialize( contents, HoverEvent.getClass( action, false ) )
};
}
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
context.deserialize( contents, BaseComponent.class )
};
}
hoverEvent = new HoverEvent( action, components );
} else if ( event.has( "contents" ) )
{
JsonElement contents = event.get( "contents" );
// stop the loop as soon as either one is found
break;
Content[] list;
if ( contents.isJsonArray() )
{
list = context.deserialize( contents, HoverEvent.getClass( action, true ) );
} else
{
list = new Content[]
{
context.deserialize( contents, HoverEvent.getClass( action, false ) )
};
}
hoverEvent = new HoverEvent( action, new ArrayList<>( Arrays.asList( list ) ) );
}
if ( hoverEvent != null )
{
component.setHoverEvent( hoverEvent );
}
}
if ( object.has( "font" ) )
{
component.setFont( object.get( "font" ).getAsString() );
}
if ( object.has( "extra" ) )
{
component.setExtra( Arrays.asList( context.<BaseComponent[]>deserialize( object.get( "extra" ), BaseComponent[].class ) ) );
@ -161,30 +102,9 @@ public class BaseComponentSerializer
{
Preconditions.checkArgument( !ComponentSerializer.serializedComponents.get().contains( component ), "Component loop" );
ComponentSerializer.serializedComponents.get().add( component );
if ( component.isBoldRaw() != null )
{
object.addProperty( "bold", component.isBoldRaw() );
}
if ( component.isItalicRaw() != null )
{
object.addProperty( "italic", component.isItalicRaw() );
}
if ( component.isUnderlinedRaw() != null )
{
object.addProperty( "underlined", component.isUnderlinedRaw() );
}
if ( component.isStrikethroughRaw() != null )
{
object.addProperty( "strikethrough", component.isStrikethroughRaw() );
}
if ( component.isObfuscatedRaw() != null )
{
object.addProperty( "obfuscated", component.isObfuscatedRaw() );
}
if ( component.getColorRaw() != null )
{
object.addProperty( "color", component.getColorRaw().getName() );
}
ComponentStyleSerializer.serializeTo( component.getStyle(), object );
if ( component.getInsertion() != null )
{
object.addProperty( "insertion", component.getInsertion() );
@ -213,10 +133,6 @@ public class BaseComponentSerializer
object.add( "hoverEvent", hoverEvent );
}
if ( component.getFontRaw() != null )
{
object.addProperty( "font", component.getFontRaw() );
}
if ( component.getExtra() != null )
{
object.add( "extra", context.serialize( component.getExtra() ) );

View File

@ -13,6 +13,7 @@ import com.google.gson.JsonPrimitive;
import java.lang.reflect.Type;
import java.util.Set;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.ItemTag;
import net.md_5.bungee.api.chat.KeybindComponent;
import net.md_5.bungee.api.chat.ScoreComponent;
@ -36,6 +37,7 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ).
registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ).
registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ).
registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() ).
registerTypeAdapter( Entity.class, new EntitySerializer() ).
registerTypeAdapter( Text.class, new TextSerializer() ).
registerTypeAdapter( Item.class, new ItemSerializer() ).
@ -118,11 +120,44 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
return gson.fromJson( jsonElement, BaseComponent.class );
}
/**
* Deserialize a JSON-compliant String as a component style.
*
* @param json the component style json to parse
* @return the deserialized component style
* @throws IllegalArgumentException if anything other than a valid JSON
* component style string is passed as input
*/
public static ComponentStyle deserializeStyle(String json)
{
JsonElement jsonElement = JsonParser.parseString( json );
return deserializeStyle( jsonElement );
}
/**
* Deserialize a JSON element as a component style.
*
* @param jsonElement the component style json to parse
* @return the deserialized component style
* @throws IllegalArgumentException if anything other than a valid JSON
* component style is passed as input
*/
public static ComponentStyle deserializeStyle(JsonElement jsonElement)
{
return gson.fromJson( jsonElement, ComponentStyle.class );
}
public static JsonElement toJson(BaseComponent component)
{
return gson.toJsonTree( component );
}
public static JsonElement toJson(ComponentStyle style)
{
return gson.toJsonTree( style );
}
public static String toString(Object object)
{
return gson.toJson( object );
@ -144,6 +179,11 @@ public class ComponentSerializer implements JsonDeserializer<BaseComponent>
}
}
public static String toString(ComponentStyle style)
{
return gson.toJson( style );
}
@Override
public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{

View File

@ -0,0 +1,118 @@
package net.md_5.bungee.chat;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.ComponentStyleBuilder;
public class ComponentStyleSerializer implements JsonSerializer<ComponentStyle>, JsonDeserializer<ComponentStyle>
{
private static boolean getAsBoolean(JsonElement el)
{
if ( el.isJsonPrimitive() )
{
JsonPrimitive primitive = (JsonPrimitive) el;
if ( primitive.isBoolean() )
{
return primitive.getAsBoolean();
}
if ( primitive.isNumber() )
{
Number number = primitive.getAsNumber();
if ( number instanceof Byte )
{
return number.byteValue() != 0;
}
}
}
return false;
}
static void serializeTo(ComponentStyle style, JsonObject object)
{
if ( style.isBoldRaw() != null )
{
object.addProperty( "bold", style.isBoldRaw() );
}
if ( style.isItalicRaw() != null )
{
object.addProperty( "italic", style.isItalicRaw() );
}
if ( style.isUnderlinedRaw() != null )
{
object.addProperty( "underlined", style.isUnderlinedRaw() );
}
if ( style.isStrikethroughRaw() != null )
{
object.addProperty( "strikethrough", style.isStrikethroughRaw() );
}
if ( style.isObfuscatedRaw() != null )
{
object.addProperty( "obfuscated", style.isObfuscatedRaw() );
}
if ( style.hasColor() )
{
object.addProperty( "color", style.getColor().getName() );
}
if ( style.hasFont() )
{
object.addProperty( "font", style.getFont() );
}
}
@Override
public ComponentStyle deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
ComponentStyleBuilder builder = ComponentStyle.builder();
JsonObject object = json.getAsJsonObject();
if ( object.has( "bold" ) )
{
builder.bold( getAsBoolean( object.get( "bold" ) ) );
}
if ( object.has( "italic" ) )
{
builder.italic( getAsBoolean( object.get( "italic" ) ) );
}
if ( object.has( "underlined" ) )
{
builder.underlined( getAsBoolean( object.get( "underlined" ) ) );
}
if ( object.has( "strikethrough" ) )
{
builder.strikethrough( getAsBoolean( object.get( "strikethrough" ) ) );
}
if ( object.has( "obfuscated" ) )
{
builder.obfuscated( getAsBoolean( object.get( "obfuscated" ) ) );
}
if ( object.has( "color" ) )
{
builder.color( ChatColor.of( object.get( "color" ).getAsString() ) );
}
if ( object.has( "font" ) )
{
builder.font( object.get( "font" ).getAsString() );
}
return builder.build();
}
@Override
public JsonElement serialize(ComponentStyle src, Type typeOfSrc, JsonSerializationContext context)
{
JsonObject object = new JsonObject();
serializeTo( src, object );
return object;
}
}

View File

@ -8,6 +8,7 @@ import java.util.function.Function;
import java.util.function.ObjIntConsumer;
import java.util.function.Supplier;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.hover.content.Entity;
import net.md_5.bungee.api.chat.hover.content.Text;
import net.md_5.bungee.chat.ComponentSerializer;
import org.junit.jupiter.api.Test;
@ -88,6 +89,14 @@ public class ComponentsTest
*/
}
@Test
public void testArrayUUIDParse()
{
BaseComponent[] uuidComponent = ComponentSerializer.parse( "{\"translate\":\"multiplayer.player.joined\",\"with\":[{\"text\":\"Rexcantor64\",\"hoverEvent\":{\"contents\":{\"type\":\"minecraft:player\",\"id\":[1328556382,-2138814985,-1895806765,-1039963041],\"name\":\"Rexcantor64\"},\"action\":\"show_entity\"},\"insertion\":\"Rexcantor64\",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"/tell Rexcantor64 \"}}],\"color\":\"yellow\"}" );
assertEquals( "4f30295e-8084-45f7-8f00-48d3c2036c5f", ( (Entity) ( (TranslatableComponent) uuidComponent[0] ).getWith().get( 0 ).getHoverEvent().getContents().get( 0 ) ).getId() );
testDissembleReassemble( uuidComponent );
}
@Test
public void testEmptyComponentBuilderCreate()
{
@ -421,6 +430,16 @@ public class ComponentsTest
assertArrayEquals( component, reparsed );
}
@Test
public void testStyle()
{
ComponentStyle style = ComponentSerializer.deserializeStyle( "{\"color\":\"red\",\"font\":\"minecraft:example\",\"bold\":true,\"italic\":false,\"obfuscated\":true}" );
String text = ComponentSerializer.toString( style );
ComponentStyle reparsed = ComponentSerializer.deserializeStyle( text );
assertEquals( style, reparsed );
}
@Test
public void testBuilderAppendCreate()
{
@ -806,6 +825,28 @@ public class ComponentsTest
);
}
@Test
public void testHasFormatting()
{
BaseComponent component = new TextComponent();
assertFalse( component.hasFormatting() );
component.setBold( true );
assertTrue( component.hasFormatting() );
}
@Test
public void testStyleIsEmpty()
{
ComponentStyle style = ComponentStyle.builder().build();
assertTrue( style.isEmpty() );
style = ComponentStyle.builder()
.bold( true )
.build();
assertFalse( style.isEmpty() );
}
/*
* In legacy chat, colors and reset both reset all formatting.
* Make sure it works in combination with ComponentBuilder.

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Config</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Event</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-log</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Log</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-alert</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_alert</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-find</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_find</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-kick</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_kick</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-list</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_list</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-send</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_send</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-cmd-server</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>cmd_server</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord Modules</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-module-reconnect-yaml</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>reconnect_yaml</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-native</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Native</name>

16
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BungeeCord-Parent</name>
@ -83,7 +83,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>4.1.100.Final</version>
<version>4.1.107.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -93,7 +93,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
@ -108,6 +108,12 @@
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations-java5</artifactId>
<version>24.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -122,7 +128,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.2</version>
<version>3.6.3</version>
</plugin>
</plugins>
</pluginManagement>
@ -146,7 +152,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.12.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Protocol</name>

View File

@ -8,6 +8,8 @@ import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.ClientStatus;
import net.md_5.bungee.protocol.packet.Commands;
import net.md_5.bungee.protocol.packet.CookieRequest;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.EntityStatus;
@ -40,6 +42,7 @@ import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.StoreCookie;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
@ -47,6 +50,7 @@ import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.Transfer;
import net.md_5.bungee.protocol.packet.ViewDistance;
public abstract class AbstractPacketHandler
@ -243,4 +247,20 @@ public abstract class AbstractPacketHandler
public void handle(FinishConfiguration finishConfiguration) throws Exception
{
}
public void handle(Transfer transfer) throws Exception
{
}
public void handle(StoreCookie storeCookie) throws Exception
{
}
public void handle(CookieRequest cookieRequest) throws Exception
{
}
public void handle(CookieResponse cookieResponse) throws Exception
{
}
}

View File

@ -19,6 +19,7 @@ import java.util.UUID;
import java.util.function.BiConsumer;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.chat.ComponentSerializer;
import se.llbit.nbt.ErrorTag;
import se.llbit.nbt.NamedTag;
@ -118,6 +119,14 @@ public abstract class DefinedPacket
}
}
public static ComponentStyle readComponentStyle(ByteBuf buf, int protocolVersion)
{
SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion );
JsonElement json = TagUtil.toJson( nbt );
return ComponentSerializer.deserializeStyle( json );
}
public static void writeEitherBaseComponent(Either<String, BaseComponent> message, ByteBuf buf, int protocolVersion)
{
if ( message.isLeft() )
@ -145,6 +154,14 @@ public abstract class DefinedPacket
}
}
public static void writeComponentStyle(ComponentStyle style, ByteBuf buf, int protocolVersion)
{
JsonElement json = ComponentSerializer.toJson( style );
SpecificTag nbt = TagUtil.fromJson( json );
writeTag( nbt, buf, protocolVersion );
}
public static void writeArray(byte[] b, ByteBuf buf)
{
if ( b.length > Short.MAX_VALUE )
@ -231,7 +248,7 @@ public abstract class DefinedPacket
if ( bytes > maxBytes )
{
throw new RuntimeException( "VarInt too big" );
throw new OverflowPacketException( "VarInt too big (max " + maxBytes + ")" );
}
if ( ( in & 0x80 ) != 0x80 )
@ -378,7 +395,7 @@ public abstract class DefinedPacket
case BLANK:
break;
case STYLED:
writeBaseComponent( (BaseComponent) format.getValue(), buf, protocolVersion ); // TODO: style
writeComponentStyle( (ComponentStyle) format.getValue(), buf, protocolVersion );
break;
case FIXED:
writeBaseComponent( (BaseComponent) format.getValue(), buf, protocolVersion );
@ -394,7 +411,7 @@ public abstract class DefinedPacket
case 0:
return new NumberFormat( NumberFormat.Type.BLANK, null );
case 1:
return new NumberFormat( NumberFormat.Type.STYLED, readBaseComponent( buf, protocolVersion ) ); // TODO: style
return new NumberFormat( NumberFormat.Type.STYLED, readComponentStyle( buf, protocolVersion ) );
case 2:
return new NumberFormat( NumberFormat.Type.FIXED, readBaseComponent( buf, protocolVersion ) );
default:

View File

@ -16,6 +16,8 @@ import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.Commands;
import net.md_5.bungee.protocol.packet.CookieRequest;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.EntityStatus;
@ -46,6 +48,7 @@ import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StartConfiguration;
import net.md_5.bungee.protocol.packet.StatusRequest;
import net.md_5.bungee.protocol.packet.StatusResponse;
import net.md_5.bungee.protocol.packet.StoreCookie;
import net.md_5.bungee.protocol.packet.Subtitle;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.TabCompleteRequest;
@ -53,6 +56,7 @@ import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.protocol.packet.Team;
import net.md_5.bungee.protocol.packet.Title;
import net.md_5.bungee.protocol.packet.TitleTimes;
import net.md_5.bungee.protocol.packet.Transfer;
import net.md_5.bungee.protocol.packet.ViewDistance;
public enum Protocol
@ -90,7 +94,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x20 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x1F ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x23 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x24 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x26 )
);
TO_CLIENT.registerPacket(
Login.class,
@ -106,7 +111,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x25 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x24 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x28 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x29 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x2B )
);
TO_CLIENT.registerPacket( Chat.class,
Chat::new,
@ -136,7 +142,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x3D ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x43 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x47 )
);
TO_CLIENT.registerPacket(
BossBar.class,
@ -195,7 +202,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x54 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x58 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5C ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x5E )
);
TO_CLIENT.registerPacket(
ScoreboardScore.class,
@ -212,12 +220,14 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x57 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5D ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x61 )
);
TO_CLIENT.registerPacket(
ScoreboardScoreReset.class,
ScoreboardScoreReset::new,
map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x42 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x44 )
);
TO_CLIENT.registerPacket(
ScoreboardDisplay.class,
@ -234,7 +244,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4D ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x51 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x55 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x57 )
);
TO_CLIENT.registerPacket(
Team.class,
@ -251,7 +262,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x56 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5A ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5C ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x5E ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x60 )
);
TO_CLIENT.registerPacket(
PluginMessage.class,
@ -268,7 +280,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x16 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x15 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x17 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x18 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x19 )
);
TO_CLIENT.registerPacket(
Kick.class,
@ -285,7 +298,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x19 ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x17 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1B ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1D )
);
TO_CLIENT.registerPacket(
Title.class,
@ -303,7 +317,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5B ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x61 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x63 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x65 )
);
TO_CLIENT.registerPacket(
ClearTitles.class,
@ -323,7 +338,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x59 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x5D ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x5F ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x61 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x63 )
);
TO_CLIENT.registerPacket(
TitleTimes.class,
@ -334,7 +350,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x5C ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x60 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x62 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x64 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x66 )
);
TO_CLIENT.registerPacket(
SystemChat.class,
@ -344,7 +361,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x60 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x64 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x67 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x69 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6C )
);
TO_CLIENT.registerPacket(
PlayerListHeaderFooter.class,
@ -365,7 +383,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x61 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x65 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x68 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x6A ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6D )
);
TO_CLIENT.registerPacket(
EntityStatus.class,
@ -382,7 +401,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1A ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x19 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1C ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x1D ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x1F )
);
TO_CLIENT.registerPacket(
Commands.class,
@ -408,7 +428,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_1, 0x1D ),
map( ProtocolConstants.MINECRAFT_1_19_3, 0x1C ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x1F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x20 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x22 )
);
TO_CLIENT.registerPacket(
ViewDistance.class,
@ -422,7 +443,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x4B ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x4F ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x51 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x53 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x62 )
);
TO_CLIENT.registerPacket(
ServerData.class,
@ -432,27 +454,46 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x41 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x45 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x47 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x49 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x4B )
);
TO_CLIENT.registerPacket(
PlayerListItemRemove.class,
PlayerListItemRemove::new,
map( ProtocolConstants.MINECRAFT_1_19_3, 0x35 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x39 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3B ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x3D )
);
TO_CLIENT.registerPacket(
PlayerListItemUpdate.class,
PlayerListItemUpdate::new,
map( ProtocolConstants.MINECRAFT_1_19_3, 0x36 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x3A ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x3C ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x3E )
);
TO_CLIENT.registerPacket(
StartConfiguration.class,
StartConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x65 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x67 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x69 )
);
TO_CLIENT.registerPacket(
CookieRequest.class,
CookieRequest::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x16 )
);
TO_CLIENT.registerPacket(
StoreCookie.class,
StoreCookie::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x6B )
);
TO_CLIENT.registerPacket(
Transfer.class,
Transfer::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x73 )
);
TO_SERVER.registerPacket(
@ -471,7 +512,8 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x11 ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x12 ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x17 )
);
TO_SERVER.registerPacket( Chat.class,
Chat::new,
@ -538,13 +580,19 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_19_3, 0x0C ),
map( ProtocolConstants.MINECRAFT_1_19_4, 0x0D ),
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ),
map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 )
map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x11 )
);
TO_SERVER.registerPacket(
StartConfiguration.class,
StartConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B )
);
TO_SERVER.registerPacket(
CookieResponse.class,
CookieResponse::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x10 )
);
}
},
// 1
@ -605,6 +653,11 @@ public enum Protocol
LoginPayloadRequest::new,
map( ProtocolConstants.MINECRAFT_1_13, 0x04 )
);
TO_CLIENT.registerPacket(
CookieRequest.class,
CookieRequest::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x05 )
);
TO_SERVER.registerPacket(
LoginRequest.class,
@ -626,6 +679,11 @@ public enum Protocol
LoginAcknowledged::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
);
TO_SERVER.registerPacket(
CookieResponse.class,
CookieResponse::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 )
);
}
},
// 3
@ -633,25 +691,45 @@ public enum Protocol
{
{
TO_CLIENT.registerPacket(
CookieRequest.class,
CookieRequest::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x00 )
);
TO_CLIENT.registerPacket(
PluginMessage.class,
PluginMessage::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x00 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x01 )
);
TO_CLIENT.registerPacket(
Kick.class,
Kick::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x02 )
);
TO_CLIENT.registerPacket(
FinishConfiguration.class,
FinishConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x03 )
);
TO_CLIENT.registerPacket(
KeepAlive.class,
KeepAlive::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 )
);
TO_CLIENT.registerPacket(
StoreCookie.class,
StoreCookie::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x09 )
);
TO_CLIENT.registerPacket(
Transfer.class,
Transfer::new,
map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A )
);
TO_SERVER.registerPacket(
@ -662,17 +740,20 @@ public enum Protocol
TO_SERVER.registerPacket(
PluginMessage.class,
PluginMessage::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x01 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x02 )
);
TO_SERVER.registerPacket(
FinishConfiguration.class,
FinishConfiguration::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x02 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x03 )
);
TO_SERVER.registerPacket(
KeepAlive.class,
KeepAlive::new,
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 )
map( ProtocolConstants.MINECRAFT_1_20_2, 0x03 ),
map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 )
);
}
};

View File

@ -45,6 +45,7 @@ public class ProtocolConstants
public static final int MINECRAFT_1_20 = 763;
public static final int MINECRAFT_1_20_2 = 764;
public static final int MINECRAFT_1_20_3 = 765;
public static final int MINECRAFT_1_20_5 = 1073742000;
public static final List<String> SUPPORTED_VERSIONS;
public static final List<Integer> SUPPORTED_VERSION_IDS;
@ -109,7 +110,7 @@ public class ProtocolConstants
if ( SNAPSHOT_SUPPORT )
{
// supportedVersions.add( "1.20.x" );
// supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_3 );
supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_20_5 );
}
SUPPORTED_VERSIONS = supportedVersions.build();

View File

@ -124,9 +124,11 @@ public final class TagUtil
for ( JsonElement jsonEl : jsonArray )
{
SpecificTag subTag = fromJson( jsonEl );
if ( subTag.tagType() != listType )
if ( !( subTag instanceof CompoundTag ) )
{
throw new IllegalArgumentException( "Cannot convert mixed JsonArray to Tag" );
CompoundTag wrapper = new CompoundTag();
wrapper.add( "", subTag );
subTag = wrapper;
}
tagItems.add( subTag );
@ -179,6 +181,20 @@ public final class TagUtil
JsonArray jsonList = new JsonArray( items.size() );
for ( SpecificTag subTag : items )
{
if ( subTag instanceof CompoundTag )
{
CompoundTag compound = (CompoundTag) subTag;
if ( compound.size() == 1 )
{
SpecificTag first = (SpecificTag) compound.get( "" );
if ( !first.isError() )
{
jsonList.add( toJson( first ) );
continue;
}
}
}
jsonList.add( toJson( subTag ) );
}

View File

@ -0,0 +1,38 @@
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 CookieRequest extends DefinedPacket
{
private String cookie;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
cookie = readString( buf );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( cookie, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -0,0 +1,41 @@
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 CookieResponse extends DefinedPacket
{
private String cookie;
private byte[] data;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
cookie = readString( buf );
data = readNullable( DefinedPacket::readArray, buf );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( cookie, buf );
writeNullable( data, DefinedPacket::writeArray, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -19,6 +19,7 @@ public class EncryptionRequest extends DefinedPacket
private String serverId;
private byte[] publicKey;
private byte[] verifyToken;
private boolean shouldAuthenticate;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
@ -26,6 +27,10 @@ public class EncryptionRequest extends DefinedPacket
serverId = readString( buf );
publicKey = readArray( buf );
verifyToken = readArray( buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
shouldAuthenticate = buf.readBoolean();
}
}
@Override
@ -34,6 +39,10 @@ public class EncryptionRequest extends DefinedPacket
writeString( serverId, buf );
writeArray( publicKey, buf );
writeArray( verifyToken, buf );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
buf.writeBoolean( shouldAuthenticate );
}
}
@Override

View File

@ -41,6 +41,7 @@ public class Login extends DefinedPacket
private boolean flat;
private Location deathLocation;
private int portalCooldown;
private boolean secureProfile;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
@ -154,6 +155,11 @@ public class Login extends DefinedPacket
{
portalCooldown = readVarInt( buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
secureProfile = buf.readBoolean();
}
}
@Override
@ -275,6 +281,11 @@ public class Login extends DefinedPacket
{
writeVarInt( portalCooldown, buf );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_20_5 )
{
buf.writeBoolean( secureProfile );
}
}
@Override

View File

@ -33,7 +33,7 @@ public class ServerData extends DefinedPacket
{
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 )
{
icon = DefinedPacket.readArray( buf );
icon = readArray( buf );
} else
{
icon = readString( buf );
@ -45,7 +45,7 @@ public class ServerData extends DefinedPacket
preview = buf.readBoolean();
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 && protocolVersion < ProtocolConstants.MINECRAFT_1_20_5 )
{
enforceSecure = buf.readBoolean();
}
@ -76,7 +76,7 @@ public class ServerData extends DefinedPacket
buf.writeBoolean( true );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_4 )
{
DefinedPacket.writeArray( (byte[]) icon, buf );
writeArray( (byte[]) icon, buf );
} else
{
writeString( (String) icon, buf );
@ -91,7 +91,7 @@ public class ServerData extends DefinedPacket
buf.writeBoolean( preview );
}
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 )
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_19_1 && protocolVersion < ProtocolConstants.MINECRAFT_1_20_5 )
{
buf.writeBoolean( enforceSecure );
}

View File

@ -0,0 +1,41 @@
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 StoreCookie extends DefinedPacket
{
private String key;
private byte[] data;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
key = readString( buf );
data = readArray( buf, 5120 );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( key, buf );
writeArray( data, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -0,0 +1,41 @@
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 Transfer extends DefinedPacket
{
private String host;
private int port;
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
host = readString( buf );
port = readVarInt( buf );
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( host, buf );
writeVarInt( port, buf );
}
@Override
public void handle(AbstractPacketHandler handler) throws Exception
{
handler.handle( this );
}
}

View File

@ -0,0 +1,29 @@
package net.md_5.bungee.protocol;
import static org.junit.jupiter.api.Assertions.*;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import org.junit.jupiter.api.Test;
import se.llbit.nbt.SpecificTag;
public class TagUtilTest
{
private static final Gson GSON = new Gson();
private static void testDissembleReassemble(String json)
{
JsonElement parsedJson = GSON.fromJson( json, JsonElement.class );
SpecificTag nbt = TagUtil.fromJson( parsedJson );
JsonElement convertedElement = TagUtil.toJson( nbt );
String convertedJson = GSON.toJson( convertedElement );
assertEquals( json, convertedJson );
}
@Test
public void testStringLiteral()
{
testDissembleReassemble( "{\"text\":\"\",\"extra\":[\"hello\",{\"text\":\"there\",\"color\":\"#ff0000\"},{\"text\":\"friend\",\"font\":\"minecraft:default\"}]}" );
}
}

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Proxy</name>
@ -96,26 +96,26 @@
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
<version>8.2.0</version>
<scope>runtime</scope>
</dependency>
<!-- add these back in as they are not exposed by the API -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-resolver-provider</artifactId>
<version>3.8.5</version>
<version>3.9.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>1.7.3</version>
<version>1.9.18</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>1.7.3</version>
<version>1.9.18</version>
<scope>runtime</scope>
</dependency>
</dependencies>

View File

@ -58,6 +58,7 @@ import net.md_5.bungee.api.ReconnectHandler;
import net.md_5.bungee.api.ServerPing;
import net.md_5.bungee.api.Title;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentStyle;
import net.md_5.bungee.api.chat.KeybindComponent;
import net.md_5.bungee.api.chat.ScoreComponent;
import net.md_5.bungee.api.chat.SelectorComponent;
@ -70,6 +71,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.chat.ComponentStyleSerializer;
import net.md_5.bungee.chat.KeybindComponentSerializer;
import net.md_5.bungee.chat.ScoreComponentSerializer;
import net.md_5.bungee.chat.SelectorComponentSerializer;
@ -169,6 +171,7 @@ public class BungeeCord extends ProxyServer
.registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() )
.registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() )
.registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() )
.registerTypeAdapter( ComponentStyle.class, new ComponentStyleSerializer() )
.registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() )
.registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
@Getter

View File

@ -73,7 +73,8 @@ public class EncryptionUtil
byte[] pubKey = keys.getPublic().getEncoded();
byte[] verify = new byte[ 4 ];
random.nextBytes( verify );
return new EncryptionRequest( hash, pubKey, verify );
// always auth for now
return new EncryptionRequest( hash, pubKey, verify, true );
}
public static boolean check(PlayerPublicKey publicKey, UUID uuid) throws GeneralSecurityException

View File

@ -10,6 +10,7 @@ import java.util.Locale;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor;
@ -39,6 +40,8 @@ import net.md_5.bungee.protocol.Either;
import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.CookieRequest;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EntityStatus;
import net.md_5.bungee.protocol.packet.GameState;
@ -187,6 +190,12 @@ public class ServerConnector extends PacketHandler
ch.setCompressionThreshold( setCompression.getThreshold() );
}
@Override
public void handle(CookieRequest cookieRequest) throws Exception
{
user.retrieveCookie( cookieRequest.getCookie() ).thenAccept( (cookie) -> ch.write( new CookieResponse( cookieRequest.getCookie(), cookie ) ) );
}
@Override
public void handle(Login login) throws Exception
{
@ -243,7 +252,7 @@ public class ServerConnector extends PacketHandler
// Set tab list size, TODO: what shall we do about packet mutability
Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(),
(byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.getSimulationDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isLimitedCrafting(), login.isDebug(), login.isFlat(), login.getDeathLocation(),
login.getPortalCooldown() );
login.getPortalCooldown(), login.isSecureProfile() );
user.unsafe().sendPacket( modLogin );
@ -339,6 +348,14 @@ public class ServerConnector extends PacketHandler
private void cutThrough(ServerConnection server)
{
// TODO: Fix this?
if ( !user.isActive() )
{
server.disconnect( "Quitting" );
bungee.getLogger().log( Level.WARNING, "[{0}] No client connected for pending server!", user );
return;
}
if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_2 )
{
if ( user.getServer() != null )
@ -360,15 +377,6 @@ public class ServerConnector extends PacketHandler
user.getServer().disconnect( "Quitting" );
}
// TODO: Fix this?
if ( !user.isActive() )
{
server.disconnect( "Quitting" );
// Silly server admins see stack trace and die
bungee.getLogger().warning( "No client connected for pending server!" );
return;
}
// Add to new server
// TODO: Move this to the connected() method of DownstreamBridge
target.addPlayer( user );

View File

@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import lombok.Getter;
@ -60,7 +61,9 @@ import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter;
import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.StoreCookie;
import net.md_5.bungee.protocol.packet.SystemChat;
import net.md_5.bungee.protocol.packet.Transfer;
import net.md_5.bungee.tab.ServerUnique;
import net.md_5.bungee.tab.TabList;
import net.md_5.bungee.util.CaseInsensitiveSet;
@ -771,4 +774,26 @@ public final class UserConnection implements ProxiedPlayer
{
return serverSentScoreboard;
}
@Override
public CompletableFuture<byte[]> retrieveCookie(String cookie)
{
return pendingConnection.retrieveCookie( cookie );
}
@Override
public void storeCookie(String cookie, byte[] data)
{
Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Cookies are only supported in 1.20.5 and above" );
unsafe().sendPacket( new StoreCookie( cookie, data ) );
}
@Override
public void transfer(String host, int port)
{
Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Transfers are only supported in 1.20.5 and above" );
unsafe().sendPacket( new Transfer( host, port ) );
}
}

View File

@ -68,6 +68,7 @@ public class Configuration implements ProxyConfig
private int compressionThreshold = 256;
private boolean preventProxyConnections;
private boolean forgeSupport;
private boolean rejectTransfers;
public void load()
{
@ -103,6 +104,7 @@ public class Configuration implements ProxyConfig
compressionThreshold = adapter.getInt( "network_compression_threshold", compressionThreshold );
preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections );
forgeSupport = adapter.getBoolean( "forge_support", forgeSupport );
rejectTransfers = adapter.getBoolean( "reject_transfers", rejectTransfers );
disabledCommands = new CaseInsensitiveSet( (Collection<String>) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) );

View File

@ -11,12 +11,19 @@ import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.time.Instant;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
import javax.crypto.SecretKey;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.EncryptionUtil;
@ -51,6 +58,8 @@ import net.md_5.bungee.protocol.PacketWrapper;
import net.md_5.bungee.protocol.PlayerPublicKey;
import net.md_5.bungee.protocol.Protocol;
import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.CookieRequest;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.EncryptionResponse;
import net.md_5.bungee.protocol.packet.Handshake;
@ -86,6 +95,19 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Getter
private final Set<String> registeredChannels = new HashSet<>();
private State thisState = State.HANDSHAKE;
private final Queue<CookieFuture> requestedCookies = new LinkedList<>();
@Data
@ToString
@EqualsAndHashCode
@AllArgsConstructor
public static class CookieFuture
{
private String cookie;
private CompletableFuture<byte[]> future;
}
private final Unsafe unsafe = new Unsafe()
{
@Override
@ -109,6 +131,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
private boolean legacy;
@Getter
private String extraDataInHandshake = "";
@Getter
private boolean transferred;
private UserConnection userCon;
@Override
@ -349,6 +373,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
ch.setProtocol( Protocol.STATUS );
break;
case 2:
case 3:
transferred = handshake.getRequestedProtocol() == 3;
// Login
bungee.getLogger().log( Level.INFO, "{0} has connected", this );
thisState = State.USERNAME;
@ -365,6 +391,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
}
return;
}
if ( transferred && bungee.config.isRejectTransfers() )
{
disconnect( bungee.getTranslation( "reject_transfer" ) );
return;
}
break;
default:
throw new QuietException( "Cannot request protocol " + handshake.getRequestedProtocol() );
@ -621,6 +653,13 @@ public class InitialHandler extends PacketHandler implements PendingConnection
ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) );
bungee.getPluginManager().callEvent( new PostLoginEvent( userCon ) );
// #3612: Don't progress further if disconnected during event
if ( ch.isClosed() )
{
return;
}
ServerInfo server;
if ( bungee.getReconnectHandler() != null )
{
@ -643,6 +682,34 @@ public class InitialHandler extends PacketHandler implements PendingConnection
disconnect( "Unexpected custom LoginPayloadResponse" );
}
@Override
public void handle(CookieResponse cookieResponse)
{
// be careful, backend server could also make the client send a cookie response
CookieFuture future;
synchronized ( requestedCookies )
{
future = requestedCookies.peek();
if ( future != null )
{
if ( future.cookie.equals( cookieResponse.getCookie() ) )
{
Preconditions.checkState( future == requestedCookies.poll(), "requestedCookies queue mismatch" );
} else
{
future = null; // leave for handling by backend
}
}
}
if ( future != null )
{
future.getFuture().complete( cookieResponse.getData() );
throw CancelSendSignal.INSTANCE;
}
}
@Override
public void disconnect(String reason)
{
@ -775,4 +842,26 @@ public class InitialHandler extends PacketHandler implements PendingConnection
brandMessage = input;
}
}
@Override
public CompletableFuture<byte[]> retrieveCookie(String cookie)
{
Preconditions.checkState( getVersion() >= ProtocolConstants.MINECRAFT_1_20_5, "Cookies are only supported in 1.20.5 and above" );
Preconditions.checkState( loginRequest != null, "Cannot retrieve cookies for status or legacy connections" );
if ( cookie.indexOf( ':' ) == -1 )
{
// if we request an invalid resource location (no prefix) the client will respond with "minecraft:" prefix
cookie = "minecraft:" + cookie;
}
CompletableFuture<byte[]> future = new CompletableFuture<>();
synchronized ( requestedCookies )
{
requestedCookies.add( new CookieFuture( cookie, future ) );
}
unsafe.sendPacket( new CookieRequest( cookie ) );
return future;
}
}

View File

@ -32,6 +32,7 @@ import net.md_5.bungee.protocol.packet.Chat;
import net.md_5.bungee.protocol.packet.ClientChat;
import net.md_5.bungee.protocol.packet.ClientCommand;
import net.md_5.bungee.protocol.packet.ClientSettings;
import net.md_5.bungee.protocol.packet.CookieResponse;
import net.md_5.bungee.protocol.packet.FinishConfiguration;
import net.md_5.bungee.protocol.packet.KeepAlive;
import net.md_5.bungee.protocol.packet.LoginAcknowledged;
@ -128,7 +129,7 @@ public class UpstreamBridge extends PacketHandler
@Override
public boolean shouldHandle(PacketWrapper packet) throws Exception
{
return con.getServer() != null || packet.packet instanceof PluginMessage;
return con.getServer() != null || packet.packet instanceof PluginMessage || packet.packet instanceof CookieResponse;
}
@Override
@ -363,6 +364,12 @@ public class UpstreamBridge extends PacketHandler
con.sendQueuedPackets();
}
@Override
public void handle(CookieResponse cookieResponse) throws Exception
{
con.getPendingConnection().handle( cookieResponse );
}
@Override
public String toString()
{

View File

@ -86,6 +86,8 @@ public abstract class EntityMap
return EntityMap_1_16_2.INSTANCE_1_20_2;
case ProtocolConstants.MINECRAFT_1_20_3:
return EntityMap_1_16_2.INSTANCE_1_20_3;
case ProtocolConstants.MINECRAFT_1_20_5:
return EntityMap_1_16_2.INSTANCE_1_20_5;
}
throw new RuntimeException( "Version " + version + " has no entity map" );
}

View File

@ -22,6 +22,7 @@ class EntityMap_1_16_2 extends EntityMap
static final EntityMap_1_16_2 INSTANCE_1_19_4 = new EntityMap_1_16_2( 0x03, 0x30 );
static final EntityMap_1_16_2 INSTANCE_1_20_2 = new EntityMap_1_16_2( -1, 0x33 );
static final EntityMap_1_16_2 INSTANCE_1_20_3 = new EntityMap_1_16_2( -1, 0x34 );
static final EntityMap_1_16_2 INSTANCE_1_20_5 = new EntityMap_1_16_2( -1, 0x36 );
//
private final int spawnPlayerId;
private final int spectateId;

View File

@ -40,3 +40,4 @@ command_perms_permission=\u00a79- {0}
command_ip=\u00a79IP of {0} is {1}
illegal_chat_characters=\u00a7cIllegal characters in chat ({0})
kick_message=\u00a7cYou have been kicked off the proxy.
reject_transfer=\u00a7cYour transfer was rejected.

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-query</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Query</name>

View File

@ -6,13 +6,13 @@
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-slf4j</artifactId>
<version>1.20-R0.2-SNAPSHOT</version>
<version>1.20-R0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-SLF4J</name>